diff --git a/app/build.gradle b/app/build.gradle index ddf3e1a..e5042a6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "com.uam.wmi.findmytutor" minSdkVersion 22 targetSdkVersion 27 - versionCode 3 - versionName "0.9.0-alpha" + versionCode 8 + versionName "0.9.1-alpha" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true } @@ -30,7 +30,7 @@ repositories { } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'com.android.support:preference-v7:27.1.1' implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support:design:27.1.1' @@ -43,18 +43,18 @@ dependencies { implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' - implementation "io.swagger:swagger-annotations:1.5.15" - implementation "org.threeten:threetenbp:1.3.5" + implementation 'io.swagger:swagger-annotations:1.5.15' + implementation 'org.threeten:threetenbp:1.3.5' implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:6.6.5' implementation 'io.reactivex.rxjava2:rxjava:2.2.0' implementation 'com.android.support:recyclerview-v7:27.1.1' implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' - implementation "com.jakewharton:butterknife:8.8.1" + implementation 'com.jakewharton:butterknife:8.8.1' annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1" - implementation "com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0" - implementation "com.squareup.okhttp3:okhttp:3.11.0" - implementation "com.squareup.okhttp3:okhttp-urlconnection:3.10.0" - implementation "com.squareup.okhttp3:logging-interceptor:3.11.0" + implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' + implementation 'com.squareup.okhttp3:okhttp:3.11.0' + implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.10.0' + implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0' implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' implementation 'com.auth0.android:jwtdecode:1.1.1' implementation 'com.annimon:stream:1.2.1' @@ -62,5 +62,5 @@ dependencies { implementation 'com.mapbox.mapboxsdk:mapbox-sdk-turf:4.0.0' // FloatingBarMenu implementation 'com.getbase:floatingactionbutton:1.10.1' - + implementation 'org.apache.commons:commons-collections4:4.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ed85fed..3f3dd4d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,7 +25,6 @@ android:theme="@style/AppTheme"> @@ -36,17 +35,14 @@ + android:name=".activity.SettingsActivity" /> + \ No newline at end of file diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png new file mode 100644 index 0000000..25b1968 Binary files /dev/null and b/app/src/main/ic_launcher-web.png differ diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/BaseActivity.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/BaseActivity.java index c347afc..6126794 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/BaseActivity.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/BaseActivity.java @@ -20,6 +20,7 @@ import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.SearchView; import android.support.v7.widget.Toolbar; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -38,7 +39,10 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; +import io.reactivex.Observable; +import io.reactivex.ObservableSource; import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; @@ -92,15 +96,14 @@ public abstract class BaseActivity } else if (itemName.equals(getResources().getString(R.string.navigation_item_profile))) { - /* launchIntent = new Intent(getApplicationContext(), ProfileActivity.class); - startActivity(launchIntent);*/ + launchIntent = new Intent(getApplicationContext(), TutorTab.class); + startActivity(launchIntent); } else if (itemName.equals(getResources().getString(R.string.navigation_item_settings))) { launchIntent = new Intent(getApplicationContext(), SettingsActivity.class); startActivity(launchIntent); } else if (itemName.equals(getResources().getString(R.string.navigation_item_logout))) { if(PrefUtils.isBackgroundLocationServiceRunning(getApplicationContext())) { - stopBackgroundLocalizationTask(); } @@ -194,7 +197,7 @@ public abstract class BaseActivity Intent startIntent = new Intent(getApplicationContext(), BackgroundLocalizationService.class); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) { startForegroundService(startIntent); } else { startService(startIntent); @@ -202,13 +205,11 @@ public abstract class BaseActivity } public void handleBackgroundTaskLifeCycle() { - Boolean shouldServiceRun = PrefUtils.isEnableSharingLocalization(getApplicationContext()) - && !PrefUtils.isBackgroundLocationServiceRunning(getApplicationContext()); + Boolean shouldServiceRun = PrefUtils.isEnableSharingLocalization(getApplicationContext()) && isTutor; if (shouldServiceRun) { startBackgroundLocalizationTask(); - } else if (PrefUtils.isBackgroundLocationServiceRunning(getApplicationContext()) && - !PrefUtils.isEnableSharingLocalization(getApplicationContext())) { + } else { stopBackgroundLocalizationTask(); } } @@ -273,13 +274,13 @@ public abstract class BaseActivity } }); - RxSearchObservable.fromView(searchView) + .skip(0) .map(String::toLowerCase) - .debounce(300, TimeUnit.MILLISECONDS) - .distinctUntilChanged() + .debounce(250, TimeUnit.MILLISECONDS) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) + .switchMap((Function>) Observable::just) .subscribe(this::executeSearch); return true; @@ -288,16 +289,15 @@ public abstract class BaseActivity private void executeSearch(String input) { if (activeFragment.equals(ActiveFragment.USER_LIST)) { ((UsersListFragment) userListFragment).searchUser(input); + } else if (activeFragment.equals(ActiveFragment.NONE)) { searchUser(input); } } - public void searchUser(String textToSearch) { - } + abstract void searchUser(String textToSearch); - public void restoreMapMarkers() { - } + abstract void restoreMapMarkers(); @Override public boolean onOptionsItemSelected(MenuItem item) { diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/LoginActivity.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/LoginActivity.java index 912598a..a7dd423 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/LoginActivity.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/LoginActivity.java @@ -10,14 +10,11 @@ import android.os.Bundle; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; - -import android.util.Log; import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.EditText; -import android.widget.Switch; import com.auth0.android.jwt.Claim; import com.auth0.android.jwt.JWT; @@ -44,7 +41,6 @@ import okhttp3.ResponseBody; public class LoginActivity extends AppCompatActivity { - // UI references. private AutoCompleteTextView mLoginNameView; private EditText mPasswordView; private View mProgressView; @@ -151,11 +147,10 @@ public class LoginActivity extends AppCompatActivity { } - private void loginProcess(String email, String password) { - ValidateUser user = new ValidateUser(email, password); + ValidateUser user = new ValidateUser(email, password); - disposable.add(ldapService.validate(user) + disposable.add(ldapService.validate(user) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::handleResponse, this::handleError)); @@ -164,9 +159,9 @@ public class LoginActivity extends AppCompatActivity { private void getUserProfile(String userId) { disposable.add(userService.getUserById(userId) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::saveUserProfileToSharedPreferences, this::handleError)); + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::saveUserProfileToSharedPreferences, this::handleError)); } private void showSnackBarMessage(String message) { @@ -182,10 +177,12 @@ public class LoginActivity extends AppCompatActivity { Claim userId = jwt.getClaim("nameid"); Claim role = jwt.getClaim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role"); - if(!Objects.requireNonNull(role.asString()).equals("Student")){ + if (Objects.requireNonNull(role.asString()).equals("Student")) { + PrefUtils.storeIsTutor(getApplicationContext(), false); + } else { PrefUtils.storeIsTutor(getApplicationContext(), true); } - + PrefUtils.storeIsLoggedIn(getApplicationContext(), true); PrefUtils.storeApiKey(getApplicationContext(), token); PrefUtils.storeUserId(getApplicationContext(), userId.asString()); @@ -217,6 +214,5 @@ public class LoginActivity extends AppCompatActivity { PrefUtils.storeUserLastName(getApplicationContext(), user.getLastName()); PrefUtils.storeUserName(getApplicationContext(), user.getUserName()); } - } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/MapActivity.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/MapActivity.java index 543bf03..81f878b 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/MapActivity.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/MapActivity.java @@ -4,16 +4,19 @@ import android.Manifest; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; +import android.graphics.Color; import android.location.Location; import android.os.Bundle; import android.os.Handler; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; +import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.animation.LinearInterpolator; import android.widget.Button; +import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; @@ -37,12 +40,18 @@ import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; import com.uam.wmi.findmytutor.R; import com.uam.wmi.findmytutor.model.Coordinate; +import com.uam.wmi.findmytutor.model.PredefinedCoordViewModel; import com.uam.wmi.findmytutor.model.User; import com.uam.wmi.findmytutor.network.ApiClient; import com.uam.wmi.findmytutor.service.CoordinateService; +import com.uam.wmi.findmytutor.service.PredefinedStatusesService; import com.uam.wmi.findmytutor.service.UserService; +import com.uam.wmi.findmytutor.utils.FeedbackUtils; +import com.uam.wmi.findmytutor.utils.ManualLocationUtils; +import com.uam.wmi.findmytutor.utils.MapMarker; import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.RestApiHelper; +import com.uam.wmi.findmytutor.utils.SharingLevel; import com.uam.wmi.findmytutor.utils.mapUtils; import java.util.ArrayList; @@ -58,11 +67,9 @@ import io.reactivex.schedulers.Schedulers; import okhttp3.ResponseBody; import timber.log.Timber; - public class MapActivity extends BaseActivity implements PermissionsListener, OnMapReadyCallback { - private String tag = getClass().getName(); private PermissionsManager permissionsManager; private LocationComponent locationComponent; @@ -82,22 +89,23 @@ public class MapActivity extends BaseActivity private Marker tmpLocalMarker; private Coordinate droppedMarkercoordinate; private HashMap coordsMap = new HashMap<>(); - private HashMap markerHash = new HashMap<>(); + private HashMap markerHash = new HashMap<>(); + private HashMap markerUserHash = new HashMap<>(); private Set previousCoordsIds = new HashSet<>(); - + private ManualLocationUtils manualLocationUtils; // Camera Animation params private int zoomParam = 17; private int bearingParam = 180; private int tiltParam = 30; - private String myID; - + private String myId; + private boolean isTutor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + isTutor = PrefUtils.getIsTutor(this); + myId = PrefUtils.getUserId(getApplicationContext()); - myID = PrefUtils.getUserId(getApplicationContext()); - // fetching coords service coordinateService = ApiClient.getClient(getApplicationContext()) .create(CoordinateService.class); @@ -110,6 +118,7 @@ public class MapActivity extends BaseActivity } finally { mHandler.postDelayed(mStatusChecker, mInterval); } + }; @@ -122,6 +131,8 @@ public class MapActivity extends BaseActivity //start background task handleBackgroundTaskLifeCycle(); + manualLocationUtils = new ManualLocationUtils(MapActivity.this); + } @Override @@ -131,15 +142,15 @@ public class MapActivity extends BaseActivity enableLocationPlugin(); mapboxMap.setOnMarkerClickListener(marker -> { - String id = marker.getTitle(); - if (id.equals(myID)) { + String id = markerUserHash.get(marker.getId()); + String locationLevel = PrefUtils.getLocationLevel(getApplicationContext()); + + if (id.equals(myId) && (locationLevel.equals(SharingLevel.MANUAL.toString()) || locationLevel.equals(SharingLevel.PREDEFINED.toString()))) { selectLocationButton.setVisibility(View.GONE); removeLocationButton.setVisibility(View.VISIBLE); removeLocationButton.setOnClickListener(view -> { - Log.e(tag + "Manual", "manual coords sending stopped"); - // TODO to remove after BGserv - manualLocHandler.removeCallbacks(manualLocStatusChecker); + stopBackgroundLocalizationTask(); removeLocationButton.setVisibility(View.GONE); Toast.makeText(MapActivity.this, "Your marker will disappear in next couple minutes", Toast.LENGTH_SHORT).show(); @@ -152,26 +163,32 @@ public class MapActivity extends BaseActivity return true; }); - - setToggleMapBoundsArea(); setOnMapLongClickListener(); + mapUtils.setMapBoundsArea(getApplicationContext(), mapboxMap, mapView, true); } - private void setToggleMapBoundsArea() { - - mapUtils.setMapBoundsArea(getApplicationContext(), mapboxMap, mapView, true); + private void updateUserHashMap(String userId, Long markerId) { + disposable.add(userService.getUserById(userId) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(t -> saveUserToHashMap(t, markerId), this::handleError)); + } + private void saveUserToHashMap(User user, Long markerId) { + markerUserHash.put(markerId, user.getId()); + markerHash.get(user.getId()).getMarker().setTitle(user.getFirstName() + " " + user.getLastName()); } private void createMarkerModal(String userId) { disposable.add(userService.getUserById(userId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::createMarkerModal, this::handleError)); + .subscribe(this::createMarkerModalView, this::handleError)); } - private void createMarkerModal(User user) { + private void createMarkerModalView(User user) { String cordStatus = coordsMap.get(user.getId()).getLabel(); + String sharingLevel = coordsMap.get(user.getId()).getDisplayMode(); LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext()); @SuppressLint("InflateParams") View view = layoutInflaterAndroid.inflate(R.layout.marker_modal, null); @@ -185,12 +202,13 @@ public class MapActivity extends BaseActivity TextView userName = view.findViewById(R.id.userName); TextView status = view.findViewById(R.id.label); + TextView sharingLevelView = view.findViewById(R.id.sharing_level); userName.setText(String.format("%s %s", user.getFirstName(), user.getLastName())); - status.setText(String.format("%s ", cordStatus)); + status.setText(String.format("%s: %s", getResources().getString(R.string.status_switch_title), cordStatus)); + sharingLevelView.setText(String.format("%s: %s", getResources().getString(R.string.settings_location_level), sharingLevel)); final AlertDialog alertDialog = alertDialogBuilderUserInput.create(); - alertDialog.show(); } @@ -209,7 +227,6 @@ public class MapActivity extends BaseActivity message = "Network Error!"; } - Toast.makeText(MapActivity.this, message, Toast.LENGTH_SHORT).show(); } @@ -219,15 +236,20 @@ public class MapActivity extends BaseActivity mapboxMap.addOnMapLongClickListener((LatLng latLng) -> { selectLocationButton.setVisibility(View.VISIBLE); removeLocationButton.setVisibility(View.GONE); - Icon icon = IconFactory.getInstance(MapActivity.this).fromResource(R.drawable.green_marker); if (tmpLocalMarker == null) { + String sharingLevel = SharingLevel.MANUAL.toString(); + Icon defaultIcon = getMapIcon(sharingLevel, myId); + + MarkerOptions markerOptions = new MarkerOptions() + .setIcon(defaultIcon) + .position(latLng); + + tmpLocalMarker = mapboxMap.addMarker(markerOptions); + MapMarker marker = new MapMarker(tmpLocalMarker, markerOptions, defaultIcon, sharingLevel); + + updateUserHashMap(myId, marker.getMarker().getId()); - tmpLocalMarker = mapboxMap.addMarker(new MarkerOptions() - .position(latLng) - .icon(icon) - .title("My Loc") - .setSnippet("Snipecik")); } else { ValueAnimator markerAnimator = ObjectAnimator.ofObject(tmpLocalMarker, "position", @@ -238,8 +260,8 @@ public class MapActivity extends BaseActivity selectLocationButton.setOnClickListener((View view) -> { if (tmpLocalMarker != null) { - // Toast instructing user to tap on the mapboxMap - // TODO PUT MANUAL CORD + + try { droppedMarkercoordinate = new Coordinate( latLng.getLatitude(), @@ -251,42 +273,8 @@ public class MapActivity extends BaseActivity PrefUtils.getLocationLevel(getApplicationContext()) ); - // TODO remove after BG sending - manualLocStatusChecker = () -> { - try { - Log.e(tag + "Manual", "sending manual coords"); - // TODO ^^^ wrapper to removve - disposable.add( - coordinateService - .postCoordinate(droppedMarkercoordinate) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeWith(new DisposableSingleObserver() { - @SuppressLint("LongLogTag") - @Override - public void onSuccess(Coordinate coord) { - Log.e(tag + "POST", String.valueOf(coord)); - } - - @SuppressLint("LongLogTag") - @Override - public void onError(Throwable e) { - - Log.e(tag + "onError", e.getMessage()); - - if (e instanceof HttpException) { - ResponseBody responseBody = ((HttpException) e).response().errorBody(); - Log.e(tag + "onError", RestApiHelper.getErrorMessage(responseBody)); - - } - } - })); - // TODO \/\/\/\/\/ wrapper to removve - } finally { - manualLocHandler.postDelayed(manualLocStatusChecker, mInterval); - } - }; - manualLocStatusChecker.run(); + PrefUtils.putManualLocation(this, latLng); + handleBackgroundTaskLifeCycle(); } catch (IllegalArgumentException e) { @@ -302,28 +290,100 @@ public class MapActivity extends BaseActivity selectLocationButton.setVisibility(View.GONE); mapboxMap.removeMarker(tmpLocalMarker); tmpLocalMarker = null; + + showLocationDialog(latLng); } }); }); } + public void showLocationDialog(LatLng latLng) { + + LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext()); + @SuppressLint("InflateParams") View view = layoutInflaterAndroid.inflate(R.layout.location_modal, null); + AlertDialog.Builder alertDialogBuilderUserInput = new android.support.v7.app.AlertDialog.Builder(this); + + alertDialogBuilderUserInput.setView(view).setPositiveButton(getApplicationContext().getString(R.string.modal_location_send), null); + + alertDialogBuilderUserInput + .setPositiveButton(R.string.lbl_ok, null) + .setNegativeButton(R.string.lbl_cancel, null); + + final AlertDialog alertDialog = alertDialogBuilderUserInput.create(); + + EditText modalUserInput = view.findViewById(R.id.feedback_input); + + alertDialog.setOnShowListener(dialogInterface -> { + Button sendButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); + + Button dismissButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE); + + dismissButton.setOnClickListener(view1 -> alertDialog.dismiss()); + + sendButton.setOnClickListener(view1 -> { + String body = modalUserInput.getText().toString(); + + if (TextUtils.isEmpty(body)) { + Toast.makeText(getApplicationContext(), getApplicationContext().getString(R.string.modal_location_hint), Toast.LENGTH_SHORT).show(); + modalUserInput.requestFocus(); + } else { + PrefUtils.putManualLocation(getApplicationContext(), latLng); + sendLocation(body,latLng); + alertDialog.dismiss(); + } + }); + }); + + + + + + alertDialog.show(); + } + + + private void sendLocation(String body, LatLng latLng) { + PredefinedCoordViewModel droppedMarkercoordinate = new PredefinedCoordViewModel( + latLng.getLatitude(), + latLng.getLongitude(), + latLng.getAltitude(), + PrefUtils.getUserId(getApplicationContext()), + "string", + "predefined", + body + ); + + PredefinedStatusesService predefinedStatusesService = ApiClient.getClient(getApplicationContext()).create(PredefinedStatusesService.class); + CompositeDisposable disposable = new CompositeDisposable(); + disposable.add(predefinedStatusesService.postUserPredefinedCoord(PrefUtils.getUserId(getApplicationContext()), droppedMarkercoordinate) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::handleResponse, this::handleError)); + } + + private void handleResponse(List resp) { + Toast.makeText(getApplicationContext(), "Location saved!", Toast.LENGTH_SHORT).show(); + } + private void fetchTopCoords() { disposable.add( coordinateService.getOnlineCoordinates() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) + .map(tutors -> Stream.of(tutors). + filterNot(t -> t.getDisplayMode().equals(SharingLevel.PRESENCE.toString())).toList()) .subscribeWith(new DisposableSingleObserver>() { @Override public void onSuccess(List coordsList) { - if (coordsList.isEmpty() && tmpLocalMarker != null) { + if (tmpLocalMarker != null && coordsList.isEmpty()) { Timber.e("200 empty []"); mapboxMap.clear(); - return; + } ArrayList tmp = new ArrayList<>(); @@ -336,36 +396,39 @@ public class MapActivity extends BaseActivity previousCoordsIds.addAll(currentCoordsIds); } else { // here we clear + it returns bool if sth was removed - if (previousCoordsIds.removeAll(currentCoordsIds)) { - for (String toRemoveId : previousCoordsIds) { - Log.e(tag + "delete: ", "removing: " + toRemoveId + ": " + markerHash.get(toRemoveId)); - mapboxMap.removeMarker(markerHash.get(toRemoveId)); - markerHash.remove(toRemoveId); - coordsMap.remove(toRemoveId); - } - } else { - // TODO double check when some markers api will change - Log.e(tag + "delete: ", "nothing to remove"); + + previousCoordsIds.removeAll(currentCoordsIds); + for (String toRemoveId : previousCoordsIds) { + Log.e(tag + "delete: ", "removing: " + toRemoveId + ": " + markerHash.get(toRemoveId)); + mapboxMap.removeMarker(markerHash.get(toRemoveId).getMarker()); + markerHash.remove(toRemoveId); + coordsMap.remove(toRemoveId); } } - for (Coordinate element : coordsList) { String id = element.getUserId(); String newLabel = element.getLabel(); + String newSharingLevel = element.getDisplayMode(); Coordinate coordinate = coordsMap.get(id); + Log.e(tag, "hashMapSize: " + coordsMap.size()); Log.e(tag, "markerMapSize: " + coordsMap.size()); if (coordinate != null) { - Log.e(tag, "Coordin: " + coordinate.getLatitude() + " | " + coordinate.getLongitude()); - boolean statement = coordinate.getLatitude().equals(element.getLatitude()) || coordinate.getLongitude().equals(element.getLongitude()); - Log.e(tag, "diff || diff: " + !statement); - if (!statement) { - Log.e(tag, "replace and animate"); - Marker marker = markerHash.get(id); + boolean isTheSameLocalization = coordinate.getLatitude().equals(element.getLatitude()) || coordinate.getLongitude().equals(element.getLongitude()); + + if (!isTheSameLocalization) { + //Replace prev marker and animate + Marker marker = markerHash.get(id).getMarker(); + Boolean showModalAfterAnimation = false; + + if (marker.isInfoWindowShown()) { + marker.hideInfoWindow(); + showModalAfterAnimation = true; + } LatLng toDestination = new LatLng(element.getLatitude(), element.getLongitude()); // TODO fix flickiering markers @@ -377,29 +440,51 @@ public class MapActivity extends BaseActivity markerAnimator.setInterpolator(new LinearInterpolator()); markerAnimator.start(); - // chba niepotrzbene - mapboxMap.getMarkerViewManager().update(); coordsMap.put(id, element); marker.setPosition(toDestination); - } - } else { - Log.e(tag, "Marker Added: " + id); + if (showModalAfterAnimation) { + mapboxMap.selectMarker(marker); + } + + mapboxMap.getMarkerViewManager().update(); + } + + + } else { + //Add new marker coordsMap.put(id, element); + String sharingLevel = coordsMap.get(id).getDisplayMode(); + Icon defaultIcon = getMapIcon(sharingLevel, id); + MarkerOptions markerOptions = new MarkerOptions() - .title(id) + .setIcon(defaultIcon) .position(new LatLng(element.getLatitude(), element.getLongitude())); - // Check if this is me - if (id.equals(myID)) { - Icon icon = IconFactory.getInstance(MapActivity.this).fromResource(R.drawable.blue_marker); - markerOptions.setIcon(icon); - } - Marker marker = mapboxMap.addMarker(markerOptions); + + Marker markerMapbox = mapboxMap.addMarker(markerOptions); + MapMarker marker = new MapMarker(markerMapbox, markerOptions, defaultIcon, sharingLevel); markerHash.put(id, marker); + updateUserHashMap(id, marker.getMarker().getId()); + + } + + + //Change marker if sharing mode has been changed + Boolean newLocalizationMode = markerHash.get(id).getMarkerType().equals(newSharingLevel); + + if (!newLocalizationMode) { + Icon defaultIcon = getMapIcon(newSharingLevel, id); + MapMarker marker = markerHash.get(id); + coordsMap.get(id).setDisplayMode(newSharingLevel); + + marker.setDefaultIcon(defaultIcon); + marker.restoreDefaultIcon(); + markerHash.get(id).setMarkerType(newSharingLevel); + mapboxMap.getMarkerViewManager().update(); } coordsMap.get(id).setLabel(newLabel); @@ -410,22 +495,28 @@ public class MapActivity extends BaseActivity previousCoordsIds.addAll(currentCoordsIds); } - @SuppressLint("LongLogTag") @Override public void onError(Throwable e) { - - Log.e("MapActivity onError", e.getMessage()); - - if (e instanceof HttpException) { - ResponseBody responseBody = ((HttpException) e).response().errorBody(); - Log.e("MapActivity onError", RestApiHelper.getErrorMessage(responseBody)); - - } + showError(e); } }) ); } + private Icon getMapIcon(String sharingLevel, String id) { + Icon defaultIcon = IconFactory.getInstance(MapActivity.this).fromResource(R.drawable.exact_localization_marker); + + if (sharingLevel.equals(SharingLevel.APPROXIMATED.toString())) { + defaultIcon = IconFactory.getInstance(MapActivity.this).fromResource(R.drawable.approximate_localization_marker); + } else if (sharingLevel.equals(SharingLevel.MANUAL.toString()) || + sharingLevel.equals(SharingLevel.PREDEFINED.toString())) { + defaultIcon = IconFactory.getInstance(MapActivity.this).fromResource(R.drawable.manual_localization_marker); + } else if (id.equals(myId)) { + defaultIcon = IconFactory.getInstance(MapActivity.this).fromResource(R.drawable.my_marker); + } + + return defaultIcon; + } @SuppressWarnings({"MissingPermission"}) private void enableLocationPlugin() { @@ -548,7 +639,6 @@ public class MapActivity extends BaseActivity @Override public void onRequestPermissionsResult(int requestCode, @android.support.annotation.NonNull String[] permissions, @android.support.annotation.NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); -// permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults); } @Override @@ -595,23 +685,32 @@ public class MapActivity extends BaseActivity private void filterMarkers(List users) { restoreMapMarkers(); - Icon icon1 = IconFactory.getInstance(MapActivity.this).fromResource(R.drawable.custom_marker); - - List markersToSet = Stream.of(mapboxMap.getMarkers()) - .filter(m -> Stream.of(users).anyMatch(u -> u.getId().equals(m.getTitle()))) + Icon markedMarker = IconFactory.getInstance(MapActivity.this).fromResource(R.drawable.search_marker); + List markersToSet = Stream.of(mapboxMap.getMarkers()) + .filter(m -> Stream.of(users).anyMatch(u -> u.getId().equals(markerUserHash.get(m.getId())))) + .map(m -> markerUserHash.get(m.getId())) + .map(m -> markerHash.get(m)) .toList(); - for (Marker marker : markersToSet) { - marker.setIcon(icon1); + for (MapMarker marker : markersToSet) { + marker.getMarker().setIcon(markedMarker); + + if (markersToSet.size() == 1) + mapboxMap.selectMarker(marker.getMarker()); } + + mapboxMap.getMarkerViewManager().update(); } public void restoreMapMarkers() { - Icon icon = IconFactory.getInstance(MapActivity.this).fromResource(R.drawable.red_marker); for (Marker marker : mapboxMap.getMarkers()) { - marker.setIcon(icon); - } - } + MapMarker markerMap = markerHash.get(markerUserHash.get(marker.getId())); + markerMap.restoreDefaultIcon(); + mapboxMap.deselectMarker(marker); + } + + mapboxMap.getMarkerViewManager().update(); + } } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/SharingFragment.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/SharingFragment.java index e08ad48..56d342e 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/SharingFragment.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/SharingFragment.java @@ -1,12 +1,7 @@ package com.uam.wmi.findmytutor.activity; import android.annotation.SuppressLint; -import android.app.Activity; import android.app.FragmentTransaction; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Build; import android.os.Bundle; import android.preference.ListPreference; import android.preference.Preference; @@ -16,45 +11,34 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; import android.widget.Toast; +import com.annimon.stream.Stream; import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; import com.uam.wmi.findmytutor.R; -import com.uam.wmi.findmytutor.model.Feedback; +import com.uam.wmi.findmytutor.model.PredefinedCoordViewModel; import com.uam.wmi.findmytutor.network.ApiClient; -import com.uam.wmi.findmytutor.service.BackgroundLocalizationService; -import com.uam.wmi.findmytutor.service.FeedbackService; import com.uam.wmi.findmytutor.service.PredefinedStatusesService; import com.uam.wmi.findmytutor.utils.PrefUtils; - import com.uam.wmi.findmytutor.utils.RestApiHelper; import com.uam.wmi.findmytutor.utils.RightButtonPreference; import com.uam.wmi.findmytutor.utils.SharingLevel; -import java.util.Arrays; +import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Objects; -import java.util.Set; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.observers.DisposableSingleObserver; import io.reactivex.schedulers.Schedulers; import okhttp3.ResponseBody; -import retrofit2.Response; import static com.mapbox.mapboxsdk.Mapbox.getApplicationContext; public class SharingFragment extends PreferenceFragment { - private HashMap locationLevelMapping; - private HashMap statusMapping; - private PredefinedStatusesService statusesService; - private CompositeDisposable disposable; protected Preference locationSharing; protected Preference locationMode; protected Preference manualLocationList; @@ -62,15 +46,50 @@ public class SharingFragment extends PreferenceFragment { protected RightButtonPreference manualLocationButton; protected Preference manualStatus; protected ListPreference statusList; + protected List predefinedCoordsList = new ArrayList<>(); + private HashMap locationLevelMapping; + private HashMap statusMapping; + private PredefinedStatusesService statusesService; + private CompositeDisposable disposable; + + public static SharingFragment newInstance() { + return new SharingFragment(); + } + + void getStatuses(CompositeDisposable disposable) { - void getStatuses(CompositeDisposable disposable){ disposable.add(statusesService.getUserPredefinedStatuses(PrefUtils.getUserId(getApplicationContext())) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableSingleObserver>() { @Override public void onSuccess(List strings) { - setListPreferenceData(statusList.getKey(),strings.toArray(new String[strings.size()])); + String[] statusesArray = strings.toArray(new String[strings.size()]); + setListPreferenceData(statusList.getKey(), statusesArray); + } + + @Override + public void onError(Throwable e) { + Toast.makeText(getApplicationContext(), "Error handling status fetch", Toast.LENGTH_SHORT).show(); + } + + })); + } + + void getLocations(CompositeDisposable disposable) { + disposable.add(statusesService.getUserPredefinedCoords(PrefUtils.getUserId(getApplicationContext())) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeWith(new DisposableSingleObserver>() { + + @Override + public void onSuccess(List coords) { + List names = Stream.of(coords).map(PredefinedCoordViewModel::getName).collect(com.annimon.stream.Collectors.toList()); + predefinedCoordsList.addAll(coords); + String[] stringnames = names.toArray(new String[0]); + + setListPreferenceData(manualLocationList.getKey(), stringnames); + } @Override @@ -86,46 +105,51 @@ public class SharingFragment extends PreferenceFragment { public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.layout.pref_sharing); - locationSharing = findPreference("key_sharing_enabled"); locationMode = findPreference("key_location_level"); preferenceCategory = (PreferenceCategory) findPreference("category_sharing"); manualLocationList = findPreference("key_manual_location_value"); manualLocationButton = (RightButtonPreference) findPreference("manual_location_button"); manualStatus = findPreference("key_manual_status"); - statusList =(ListPreference) findPreference("key_status_value"); + statusList = (ListPreference) findPreference("key_status_value"); statusesService = ApiClient.getClient(getApplicationContext()).create(PredefinedStatusesService.class); disposable = new CompositeDisposable(); getStatuses(disposable); + if (PrefUtils.getLocationLevel(getApplicationContext()).equals("manual")) { + getLocations(disposable); + } + locationLevelMapping = new HashMap(); locationLevelMapping.put(0, SharingLevel.PRESENCE.toString()); locationLevelMapping.put(1, SharingLevel.APPROXIMATED.toString()); locationLevelMapping.put(2, SharingLevel.EXACT.toString()); locationLevelMapping.put(3, SharingLevel.MANUAL.toString()); - statusMapping = new HashMap(); - statusMapping.put(0,"available"); - statusMapping.put(1,"consultation"); - statusMapping.put(2,"busy"); + statusMapping.put(0, "available"); + statusMapping.put(1, "consultation"); + statusMapping.put(2, "busy"); /** Main sharing switch**/ locationSharing.setOnPreferenceChangeListener((buttonView, newValue) -> { PrefUtils.storeEnableSharingLocalization(getApplicationContext(), (Boolean) newValue); - ((MapActivity)getActivity()).handleBackgroundTaskLifeCycle(); + ((MapActivity) getActivity()).handleBackgroundTaskLifeCycle(); return true; }); /** Sharing level list **/ locationMode.setOnPreferenceChangeListener((preference, newValue) -> { - PrefUtils.storeLocationMode(getApplicationContext(),locationLevelMapping.get(Integer.parseInt((String) newValue))); - if(PrefUtils.getLocationLevel(getApplicationContext()) == "manual"){ + + PrefUtils.storeLocationMode(getApplicationContext(), locationLevelMapping.get(Integer.parseInt((String) newValue))); + if (PrefUtils.getLocationLevel(getApplicationContext()).equals("manual")) { + preferenceCategory.addPreference(manualLocationList); + getLocations(disposable); preferenceCategory.addPreference(manualLocationButton); - }else{ + } else { preferenceCategory.removePreference(manualLocationList); preferenceCategory.removePreference(manualLocationButton); } @@ -133,59 +157,51 @@ public class SharingFragment extends PreferenceFragment { }); /** Manual location category hiding when location level is != manual **/ - if(!PrefUtils.getLocationLevel(getApplicationContext()).equals("manual")){ + if (!PrefUtils.getLocationLevel(getApplicationContext()).equals("manual")) { preferenceCategory.removePreference(manualLocationList); preferenceCategory.removePreference(manualLocationButton); } /** Custom manual location list change listener **/ manualLocationList.setOnPreferenceChangeListener((preference, newValue) -> { ListPreference lp = (ListPreference) preference; - //ToDo handle manual location change + + PredefinedCoordViewModel temp = Stream.of(predefinedCoordsList).filter(p -> p.getName().equals(lp.getEntries()[Integer.parseInt((String) newValue)].toString())).single(); + + PrefUtils.putManualLocation(getApplicationContext(), temp.getGeoData()); return true; }); + /** Button 'choose from map' button listener **/ - manualLocationButton.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object o) { - //ToDO wywołanie wybierania lokalizacji z mapy - FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); - fragmentTransaction.hide(SharingFragment.this); - fragmentTransaction.commit(); - return true; - } + manualLocationButton.setOnPreferenceChangeListener((preference, o) -> { + FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); + fragmentTransaction.hide(SharingFragment.this); + fragmentTransaction.commit(); + return true; }); /** Status list change listener **/ statusList.setOnPreferenceChangeListener((preference, newValue) -> { ListPreference lp = (ListPreference) preference; - CharSequence [] entries = lp.getEntries(); - PrefUtils.storeStatus(getApplicationContext(),(String) entries[Integer.parseInt((String) newValue)]); -// PrefUtils.storeStatus(getApplicationContext(),statusMapping.get(Integer.parseInt((String) newValue))); + CharSequence[] entries = lp.getEntries(); + PrefUtils.storeStatus(getApplicationContext(), (String) entries[Integer.parseInt((String) newValue)]); return true; }); /** Custom status list change listener **/ manualStatus.setOnPreferenceChangeListener((preference, newValue) -> { -// ListPreference lp = (ListPreference) findPreference("key_status_value"); -// updateListPreference(lp, newValue, "manual_statuses"); -// PrefUtils.storeStatus(getApplicationContext(),(String) newValue); -// statusList.setValue((String) newValue); - disposable.add(statusesService.postUserPredefinedStatus(PrefUtils.getUserId(getApplicationContext()),(String) newValue) + + disposable.add(statusesService.postUserPredefinedStatus(PrefUtils.getUserId(getApplicationContext()), (String) newValue) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::handleResponse, this::handleError)); + return true; }); } - public static SharingFragment newInstance() { - return new SharingFragment(); - } - - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); @@ -194,53 +210,31 @@ public class SharingFragment extends PreferenceFragment { return view; } - public String getListPreferenceValue(String key){ - ListPreference lp = (ListPreference) findPreference(key); - return (String)lp.getEntry(); - - } - protected void updateListPreference(ListPreference lp,Object newValue,String storageKey){ - CharSequence [] entries = lp.getEntries(); - Set defaultEntries = new HashSet(Arrays.asList(entries)); - SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE); - - Set manualStatusSet = sharedPref.getStringSet(storageKey,defaultEntries); - manualStatusSet.add((String) newValue); - String [] manualStatusArr = manualStatusSet.toArray(new String[0]); - //Arrays.sort(manualStatusArr); - setListPreferenceData(lp.getKey(),manualStatusArr); -// lp.setValue((String) newValue); - - SharedPreferences.Editor editor = sharedPref.edit(); - editor.putStringSet(storageKey,manualStatusSet); - editor.apply(); - } - - protected void setListPreferenceData(String lp_name, String [] entries) { + protected void setListPreferenceData(String lp_name, String[] entries) { //todo bug z pustym statusem ListPreference lp = (ListPreference) findPreference(lp_name); lp.setEntries(entries); - CharSequence[] entryValues = new CharSequence [entries.length]; + CharSequence[] entryValues = new CharSequence[entries.length]; - for (int i = 0; i < entries.length; i++){ + for (int i = 0; i < entries.length; i++) { entryValues[i] = Integer.toString(i); } - lp.setDefaultValue("1"); + lp.setDefaultValue("0"); lp.setEntryValues(entryValues); } - private void handleResponse(List resp) { - getStatuses(disposable); - String newStatus = resp.toArray(new String[resp.size()])[resp.size()-1]; -// Toast.makeText(getApplicationContext(), newStatus, Toast.LENGTH_SHORT).show(); - statusList.setValue(Integer.toString(resp.size()-1)); - statusList.setSummary(newStatus); + private void handleResponse(List resp) { + String[] statusesArray = resp.toArray(new String[resp.size()]); + setListPreferenceData(statusList.getKey(), statusesArray); + + statusList.setValueIndex(resp.size() - 1); + PrefUtils.storeStatus(getApplicationContext(), resp.get(resp.size() - 1)); + } private void handleError(Throwable error) { if (error instanceof HttpException) { - ResponseBody responseBody = ((HttpException) error).response().errorBody(); Toast.makeText(getApplicationContext(), RestApiHelper.getErrorMessage(responseBody), Toast.LENGTH_SHORT).show(); @@ -248,7 +242,6 @@ public class SharingFragment extends PreferenceFragment { } else { Toast.makeText(getApplicationContext(), "Network error " + error.getMessage(), Toast.LENGTH_SHORT).show(); - Log.d("FEEDBACK",error.getMessage()); } } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/TutorTab.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/TutorTab.java new file mode 100644 index 0000000..d98a4f5 --- /dev/null +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/TutorTab.java @@ -0,0 +1,162 @@ +package com.uam.wmi.findmytutor.activity; + +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.annimon.stream.Stream; +import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; +import com.uam.wmi.findmytutor.R; +import com.uam.wmi.findmytutor.model.DutyHourViewModel; +import com.uam.wmi.findmytutor.model.TutorTabViewModel; +import com.uam.wmi.findmytutor.model.User; +import com.uam.wmi.findmytutor.network.ApiClient; +import com.uam.wmi.findmytutor.service.TutorTabApi; +import com.uam.wmi.findmytutor.service.UserService; +import com.uam.wmi.findmytutor.utils.PrefUtils; +import com.uam.wmi.findmytutor.utils.RestApiHelper; + +import java.util.Arrays; +import java.util.List; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.observers.DisposableSingleObserver; +import io.reactivex.schedulers.Schedulers; +import okhttp3.ResponseBody; +import retrofit2.Response; + +public class TutorTab extends AppCompatActivity { + private TutorTabApi tutorTabService; + private UserService userService; + private CompositeDisposable disposable = new CompositeDisposable(); + private TextView userName; + private TextView userDutyHours; + private EditText userNote; + private TextView userRoom; + private TextView userEmail; + private TextView department; + private Button saveButon; + private TutorTabViewModel newTab; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + tutorTabService = ApiClient.getClient(getApplicationContext()) + .create(TutorTabApi.class); + userService = ApiClient.getClient(getApplicationContext()) + .create(UserService.class); + setContentView(R.layout.content_tutor_tab); + TextView userName = findViewById(R.id.userName); + TextView userDutyHours = findViewById(R.id.userDutyHours); + EditText userNote = findViewById(R.id.userNote); + TextView userRoom = findViewById(R.id.userRoom); + TextView userEmail = findViewById(R.id.userEmail); + TextView department = findViewById(R.id.userDepartment); + Button saveButon = findViewById(R.id.saveButon); + + userName.setText(String.format("%s %s", PrefUtils.getUserFirstName(getApplicationContext()), PrefUtils.getUserLastName(getApplicationContext()))); + disposable.add( + tutorTabService.apiUsersTutorTabByTutorIdGet(PrefUtils.getUserId(getApplicationContext())) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeWith(new DisposableSingleObserver() { + @Override + public void onSuccess(TutorTabViewModel tutorTabViewModel) { + + List dutyHoursList = Stream.of(tutorTabViewModel.getDutyHours()) + .map(DutyHourViewModel::getSummary).toList(); + + userRoom.setText(String.format("%s: %s", getString(R.string.userRoom), tutorTabViewModel.getRoom())); + userEmail.setText(String.format("%s: %s", getString(R.string.userEmail), tutorTabViewModel.getEmailTutorTab())); + if (!tutorTabViewModel.getNote().equals("")) { + userNote.setText(String.format("%s", tutorTabViewModel.getNote())); + } + userDutyHours.setText(String.format("%s: %s", getString(R.string.userDutyHoursHeader), Arrays.toString(dutyHoursList.toArray()))); + + } + + @Override + public void onError(Throwable e) { + showError(e); + } + })); + disposable.add( + + userService.getUserById(PrefUtils.getUserId(getApplicationContext())) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeWith(new DisposableSingleObserver() { + @Override + public void onSuccess(User user) { + department.setText(user.getDepartment()); + Log.d("TUTORTAB", (user.getDepartment())); + + } + + @Override + public void onError(Throwable e) { + showError(e); + } + })); + setUpSaveListener(saveButon, userNote); + } + + private void setUpSaveListener(Button button, EditText note) { + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + newTab = new TutorTabViewModel(PrefUtils.getUserId(getApplicationContext()),note.getText().toString()); + putUserTab(newTab); + } + }); + } + + private void putUserTab(TutorTabViewModel tutorTabViewModel) { + disposable.add(tutorTabService.apiUsersTutorTabByTutorIdPut(PrefUtils.getUserId(getApplicationContext()), tutorTabViewModel) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::handleResponse, this::handleError)); + } + + private void handleResponse(TutorTabViewModel tutorTabViewModel) { + Toast.makeText(getApplicationContext(), getApplicationContext().getString(R.string.modal_feedback_thankyou), Toast.LENGTH_SHORT).show(); + + } + + + private void handleError(Throwable error) { + if (error instanceof HttpException) { + + ResponseBody responseBody = ((HttpException) error).response().errorBody(); + Toast.makeText(getApplicationContext(), + RestApiHelper.getErrorMessage(responseBody), Toast.LENGTH_SHORT).show(); + + } else { + Toast.makeText(getApplicationContext(), + "Network error " + error.getMessage(), Toast.LENGTH_SHORT).show(); + } + } + + private void showError(Throwable e) { + String message; + + if (e instanceof HttpException) { + ResponseBody responseBody = ((HttpException) e).response().errorBody(); + message = RestApiHelper.getErrorMessage(responseBody); + } else { + message = "Network Error!"; + } + +// Snackbar.make(coordinatorLayout, message, Snackbar.LENGTH_LONG) +// .show(); + Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show(); + } + +} diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/UsersListFragment.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/UsersListFragment.java index 433ed70..1f26899 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/UsersListFragment.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/UsersListFragment.java @@ -9,6 +9,7 @@ import android.support.v7.app.AlertDialog; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -31,9 +32,12 @@ import com.uam.wmi.findmytutor.utils.MyDividerItemDecoration; import com.uam.wmi.findmytutor.utils.RecyclerTouchListener; import com.uam.wmi.findmytutor.utils.RestApiHelper; +import java.text.Collator; +import java.text.Normalizer; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import butterknife.BindView; import butterknife.ButterKnife; @@ -61,6 +65,7 @@ public class UsersListFragment extends Fragment { private TutorsListAdapter mAdapter; private List tutorsList = new ArrayList<>(); private List tutorsFiltered = new ArrayList<>(); + private Collator plCollator = Collator.getInstance(Locale.forLanguageTag("pl-PL")); public UsersListFragment() { } @@ -108,6 +113,7 @@ public class UsersListFragment extends Fragment { } public void searchUser(String textToSearch) { + tutorsFiltered.clear(); tutorsFiltered.addAll(Stream.of(tutorsList).filter(t -> t.toSearchAbleString().toLowerCase().contains(textToSearch.toLowerCase())).toList()); @@ -212,7 +218,7 @@ public class UsersListFragment extends Fragment { private int sortByUserName(User t1, User t2) { - return t1.getFirstName().compareTo(t2.getFirstName()); + return plCollator.compare(t1.getLastName(),t2.getLastName()); } private void showError(Throwable e) { diff --git a/app/src/main/java/com/uam/wmi/findmytutor/model/Coordinate.java b/app/src/main/java/com/uam/wmi/findmytutor/model/Coordinate.java index 9b9d580..9fc2acf 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/model/Coordinate.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/model/Coordinate.java @@ -14,8 +14,8 @@ import io.swagger.annotations.ApiModelProperty; */ public class Coordinate extends BaseResponse { - Range latitudeRange = Range.create(52.466709, 52.467007); - Range longtitudeRange = Range.create(16.926159, 16.926976); + Range latitudeRange = Range.create(52.46598, 52.467545); + Range longtitudeRange = Range.create(16.926099, 16.927794); @SerializedName("coordinateId") private UUID coordinateId = null; @@ -45,8 +45,8 @@ public class Coordinate extends BaseResponse { private String label; public Coordinate (Double latitude, Double longitude, Double altitude, String approximatedLocation, String label, String userId, String displayMode) { - //if (!latitudeRange.contains(latitude)) throw new IllegalArgumentException("Inappropriate latitude value" + latitude); - //if (!longtitudeRange.contains(longitude)) throw new IllegalArgumentException("Inappropriate longitude value" + longitude); + if (!latitudeRange.contains(latitude)) throw new IllegalArgumentException("Inappropriate latitude value" + latitude); + if (!longtitudeRange.contains(longitude)) throw new IllegalArgumentException("Inappropriate longitude value" + longitude); //if (approximatedLocation == null) throw new IllegalArgumentException("Inappropriate approximatedLocation"); this.latitude = latitude; diff --git a/app/src/main/java/com/uam/wmi/findmytutor/model/Feedback.java b/app/src/main/java/com/uam/wmi/findmytutor/model/Feedback.java index 1726c75..5d438f8 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/model/Feedback.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/model/Feedback.java @@ -1,5 +1,5 @@ - package com.uam.wmi.findmytutor.model; + import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; @@ -8,18 +8,53 @@ public class Feedback { @SerializedName("isAnonymous") @Expose private Boolean isAnonymous; - @SerializedName("header") + @SerializedName("type") @Expose - private String header; + private String type; + @SerializedName("user") + @Expose + private String user; + @SerializedName("deviceOS") + @Expose + private String deviceOS; + @SerializedName("appVersion") + @Expose + private String appVersion; + @SerializedName("deviceModel") + @Expose + private String deviceModel; @SerializedName("body") @Expose private String body; - public Feedback(boolean isAnonymous, String header, String body){ + /** + * No args constructor for use in serialization + * + */ + public Feedback() { + } + + /** + * + * @param body + * @param appVersion + * @param deviceModel + * @param type + * @param isAnonymous + * @param user + * @param deviceOS + */ + public Feedback(Boolean isAnonymous, String type, String user, String deviceOS, String appVersion, String deviceModel, String body) { + super(); this.isAnonymous = isAnonymous; - this.header = header; + this.type = type; + this.user = user; + this.deviceOS = deviceOS; + this.appVersion = appVersion; + this.deviceModel = deviceModel; this.body = body; } + public Boolean getIsAnonymous() { return isAnonymous; } @@ -28,12 +63,74 @@ public class Feedback { this.isAnonymous = isAnonymous; } - public String getHeader() { - return header; + public Feedback withIsAnonymous(Boolean isAnonymous) { + this.isAnonymous = isAnonymous; + return this; } - public void setHeader(String header) { - this.header = header; + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Feedback withType(String type) { + this.type = type; + return this; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public Feedback withUser(String user) { + this.user = user; + return this; + } + + public String getDeviceOS() { + return deviceOS; + } + + public void setDeviceOS(String deviceOS) { + this.deviceOS = deviceOS; + } + + public Feedback withDeviceOS(String deviceOS) { + this.deviceOS = deviceOS; + return this; + } + + public String getAppVersion() { + return appVersion; + } + + public void setAppVersion(String appVersion) { + this.appVersion = appVersion; + } + + public Feedback withAppVersion(String appVersion) { + this.appVersion = appVersion; + return this; + } + + public String getDeviceModel() { + return deviceModel; + } + + public void setDeviceModel(String deviceModel) { + this.deviceModel = deviceModel; + } + + public Feedback withDeviceModel(String deviceModel) { + this.deviceModel = deviceModel; + return this; } public String getBody() { @@ -44,4 +141,38 @@ public class Feedback { this.body = body; } -} \ No newline at end of file + public Feedback withBody(String body) { + this.body = body; + return this; + } + + @Override + public String toString() { + return Boolean.toString(this.isAnonymous) + this.type + this.user+this.deviceOS+this.appVersion+this.deviceModel+this.body; + } + // @Override +// public String toString() { +// return new ToStringBuilder(this).append("isAnonymous", isAnonymous).append("type", type).append("user", user).append("deviceOS", deviceOS).append("appVersion", appVersion).append("deviceModel", deviceModel).append("body", body).toString(); +// } + +} + +// private Boolean isAnonymous; +// @SerializedName("type") +// @Expose +// private String type; +// @SerializedName("user") +// @Expose +// private String user; +// @SerializedName("deviceOS") +// @Expose +// private String deviceOS; +// @SerializedName("appVersion") +// @Expose +// private String appVersion; +// @SerializedName("deviceModel") +// @Expose +// private String deviceModel; +// @SerializedName("body") +// @Expose +// private String body; \ No newline at end of file diff --git a/app/src/main/java/com/uam/wmi/findmytutor/model/PredefinedCoordViewModel.java b/app/src/main/java/com/uam/wmi/findmytutor/model/PredefinedCoordViewModel.java index 78b4897..e881da6 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/model/PredefinedCoordViewModel.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/model/PredefinedCoordViewModel.java @@ -2,6 +2,7 @@ package com.uam.wmi.findmytutor.model; import java.util.UUID; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; +import com.mapbox.mapboxsdk.geometry.LatLng; public class PredefinedCoordViewModel { @@ -46,9 +47,9 @@ public class PredefinedCoordViewModel { @SerializedName("displayMode") @Expose private String displayMode = "predefined"; - @SerializedName("label") + @SerializedName("name") @Expose - private String label; + private String name; /** * No args constructor for use in serialization @@ -62,22 +63,21 @@ public class PredefinedCoordViewModel { * @param altitude * @param userId * @param displayMode - * @param label + * @param name * @param longitude * @param latitude * @param approximatedLocation * @param predefinedCoordinateId */ - public PredefinedCoordViewModel(UUID predefinedCoordinateId, Double latitude, Double longitude, Double altitude, String userId, String approximatedLocation, String displayMode, String label) { + public PredefinedCoordViewModel(Double latitude, Double longitude, Double altitude, String userId, String approximatedLocation, String displayMode, String name) { super(); - this.predefinedCoordinateId = predefinedCoordinateId; this.latitude = latitude; this.longitude = longitude; this.altitude = altitude; this.userId = userId; this.approximatedLocation = approximatedLocation; this.displayMode = displayMode; - this.label = label; + this.name = name; } public UUID getPredefinedCoordinateId() { @@ -176,12 +176,29 @@ public class PredefinedCoordViewModel { this.displayMode = displayMode; } - public String getLabel() { - return label; + public String getName() { + return name; } - public void setLabel(String label) { - this.label = label; + public void setName(String name) { + this.name = name; } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class PredefinedCoordinate {\n"); + sb.append(" lat: ").append(latitude).append("\n"); + sb.append(" long: ").append(longitude).append("\n"); + sb.append(" att: ").append(altitude).append("\n"); + sb.append(" userID: ").append(userId).append("\n"); + sb.append(" approx: ").append(approximatedLocation).append("\n"); + sb.append(" dispMode: ").append(displayMode).append("\n"); + sb.append(" name: ").append(name).append("\n"); + sb.append("}"); + return sb.toString(); + } + public LatLng getGeoData(){ + return new LatLng(this.latitude,this.longitude,this.altitude); + } } \ No newline at end of file diff --git a/app/src/main/java/com/uam/wmi/findmytutor/model/TutorTabViewModel.java b/app/src/main/java/com/uam/wmi/findmytutor/model/TutorTabViewModel.java index f74d50c..e726ce9 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/model/TutorTabViewModel.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/model/TutorTabViewModel.java @@ -33,11 +33,19 @@ public class TutorTabViewModel { @SerializedName("dutyHours") private List dutyHours = null; + public TutorTabViewModel(String userId, String note){ + this.userId=userId; +// this.room=room; +// this.emailTutorTab=emailTutorTab; + this.note=note; + } + public TutorTabViewModel tutorTabId(UUID tutorTabId) { this.tutorTabId = tutorTabId; return this; } + /** * Get tutorTabId * @return tutorTabId diff --git a/app/src/main/java/com/uam/wmi/findmytutor/model/User.java b/app/src/main/java/com/uam/wmi/findmytutor/model/User.java index 7788f61..7363608 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/model/User.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/model/User.java @@ -701,23 +701,18 @@ public class User extends BaseResponse { return Objects.hash(isOnline, isUsingBlacklist, isUsingWhitelist, blacklist, whitelist, department, ldapLogin, title, firstName, lastName, isActive, tutorTab, coordinates, id, userName, normalizedUserName, email, normalizedEmail, emailConfirmed, passwordHash, securityStamp, concurrencyStamp, phoneNumber, phoneNumberConfirmed, twoFactorEnabled, lockoutEnd, lockoutEnabled, accessFailedCount); } - public String toSearchAbleString() { - StringBuilder sb = new StringBuilder(); - sb.append(getFirstName()).append(" "); - sb.append(getLastName()).append(" "); - sb.append(getDepartment()).append(" "); - sb.append(getEmail()); - return sb.toString(); + return getFirstName() + " " + + getLastName() + " " + + getDepartment() + " " + + getEmail(); } public String toSearchAbleUserName(){ - StringBuilder sb = new StringBuilder(); - sb.append(getFirstName()); - sb.append(getLastName()); - return sb.toString(); + return getFirstName() + + getLastName(); } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/network/ApiClient.java b/app/src/main/java/com/uam/wmi/findmytutor/network/ApiClient.java index e95a240..7763c68 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/network/ApiClient.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/network/ApiClient.java @@ -22,7 +22,7 @@ public class ApiClient { private static Retrofit retrofit = null; private static int REQUEST_TIMEOUT = 60; private static OkHttpClient okHttpClient; - private static final String BASE_URL = "https://s416084.projektstudencki.pl/develop/"; + private static final String BASE_URL = "https://s416084.projektstudencki.pl/master/"; public static Retrofit getClient(Context context) { diff --git a/app/src/main/java/com/uam/wmi/findmytutor/network/RetrofitClientInstance.java b/app/src/main/java/com/uam/wmi/findmytutor/network/RetrofitClientInstance.java deleted file mode 100644 index c59609b..0000000 --- a/app/src/main/java/com/uam/wmi/findmytutor/network/RetrofitClientInstance.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.uam.wmi.findmytutor.network; - -import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; - -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.logging.HttpLoggingInterceptor; -import retrofit2.Retrofit; -import retrofit2.converter.gson.GsonConverterFactory; - -public class RetrofitClientInstance { - - private static final String BASE_URL = "https://s416084.projektstudencki.pl/develop/"; - - private static Retrofit.Builder builder - = new Retrofit.Builder() - .baseUrl(BASE_URL) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .addConverterFactory(GsonConverterFactory.create()); - - private static Retrofit retrofit = builder.build(); - - private static OkHttpClient.Builder httpClient - = new OkHttpClient.Builder(); - - private static HttpLoggingInterceptor logging - = new HttpLoggingInterceptor() - .setLevel(HttpLoggingInterceptor.Level.BASIC); - - public static S createService(Class serviceClass) { - if (!httpClient.interceptors().contains(logging)) { - httpClient.addInterceptor(logging); - builder.client(httpClient.build()); - retrofit = builder.build(); - } - return retrofit.create(serviceClass); - } - - public static S createService(Class serviceClass, final String token) { - if (token != null) { - httpClient.interceptors().clear(); - httpClient.addInterceptor(chain -> { - Request original = chain.request(); - Request.Builder builder1 = original.newBuilder() - .header("Authorization", "Bearer " + token); - Request request = builder1.build(); - return chain.proceed(request); - }); - builder.client(httpClient.build()); - retrofit = builder.build(); - } - return retrofit.create(serviceClass); - } -} - diff --git a/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundLocalizationService.java b/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundLocalizationService.java index b257bfd..bf5f19d 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundLocalizationService.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundLocalizationService.java @@ -25,13 +25,12 @@ import android.util.Log; import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.LocationServices; -import com.google.android.gms.tasks.OnSuccessListener; import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; import com.mapbox.geojson.Point; +import com.mapbox.mapboxsdk.geometry.LatLng; import com.uam.wmi.findmytutor.model.Coordinate; import com.uam.wmi.findmytutor.network.ApiClient; import com.uam.wmi.findmytutor.utils.ApproximatedLocalization; -import com.uam.wmi.findmytutor.utils.Consts; import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.RestApiHelper; import com.uam.wmi.findmytutor.utils.SharingLevel; @@ -49,7 +48,7 @@ import timber.log.Timber; import static com.uam.wmi.findmytutor.utils.Consts.presenceApproximatedName; import static com.uam.wmi.findmytutor.utils.Consts.presenceLatitude; -import static com.uam.wmi.findmytutor.utils.Consts.presencelongitude; +import static com.uam.wmi.findmytutor.utils.Consts.presenceLongitude; import static com.uam.wmi.findmytutor.utils.PrefUtils.storeBackgroundLocationStatus; public class BackgroundLocalizationService extends Service { @@ -57,19 +56,27 @@ public class BackgroundLocalizationService extends Service { private static final String TAG = "MyLocationService"; private static final int LOCATION_INTERVAL = 1000; private static final float LOCATION_DISTANCE = 5f; - private static long notify_interval = 10000; - Location mLastLocation; - Boolean stopService = false; - - ArrayList providers = new ArrayList(); - LocationListener[] mLocationListeners; + public static String str_receiver = "background.location.broadcast"; + private static long notify_interval = 20000; private LocationManager mLocationManager = null; private Handler mHandler = new Handler(); private HandlerThread mHandlerThread = null; private Runnable mStatusChecker; private FusedLocationProviderClient mFusedLocationClient; + private Double latitude; + private Double longitude; + private Double altitude; + private String approximatedBuildingPart = null; + private CompositeDisposable disposable = new CompositeDisposable(); + private CoordinateService coordinateService = null; + private Location mLastLocation; + private Boolean stopService = false; + private Intent intent; + private ArrayList providers = new ArrayList(); + private LocationListener[] mLocationListeners; + private ApproximatedLocalization approximatedLocalization; public BackgroundLocalizationService() { providers.add(LocationManager.GPS_PROVIDER); @@ -110,6 +117,11 @@ public class BackgroundLocalizationService extends Service { @Override public void onCreate() { Log.e(TAG, "onCreate"); + approximatedLocalization = new ApproximatedLocalization(mapUtils.loadJsonFromAsset(getApplicationContext(), "building.geojson")); + + coordinateService = ApiClient.getClient(getApplicationContext()) + .create(CoordinateService.class); + storeBackgroundLocationStatus(getApplication(), true); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) @@ -145,6 +157,7 @@ public class BackgroundLocalizationService extends Service { } if (!stopService) { + mStatusChecker = () -> { try { fn_getlocation(); @@ -155,9 +168,9 @@ public class BackgroundLocalizationService extends Service { AsyncTask.execute(mStatusChecker); } - } + @RequiresApi(api = Build.VERSION_CODES.O) private void startMyOwnForeground() { @@ -218,8 +231,68 @@ public class BackgroundLocalizationService extends Service { }); } + @SuppressLint("LongLogTag") private void fn_update(Location location) { - new Task(location).execute(); + Double latitude = location.getLatitude(); + Double longitude = location.getLongitude(); + Double altitude = location.getAltitude(); + + String locationLevel = PrefUtils.getLocationLevel(getApplicationContext()); + approximatedBuildingPart = approximatedLocalization.getNameOfBuildingPart(Point.fromLngLat(longitude, latitude)); + + if (locationLevel.equals(SharingLevel.PRESENCE.toString())) { + latitude = presenceLatitude; + longitude = presenceLongitude; + approximatedBuildingPart = presenceApproximatedName; + } else if (locationLevel.equals(SharingLevel.APPROXIMATED.toString())) { + List points = approximatedLocalization.getMiddlePointOfBuildingPart(approximatedBuildingPart); + latitude = points.get(0); + longitude = points.get(1); + } else if (locationLevel.equals(SharingLevel.MANUAL.toString())) { + LatLng latLng = PrefUtils.getManualLocation(getApplicationContext()); + latitude = latLng.getLatitude(); + longitude = latLng.getLongitude(); + } + + try { + Coordinate coordinate = new Coordinate( + latitude, + longitude, + altitude, + approximatedBuildingPart, + (PrefUtils.isStatusEnabled(getApplicationContext())) ? PrefUtils.getUserStatus(getApplicationContext()) : "", + PrefUtils.getUserId(getApplicationContext()), + locationLevel + ); + + disposable.add( + coordinateService + .postCoordinate(coordinate) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeWith(new DisposableSingleObserver() { + @SuppressLint("LongLogTag") + @Override + public void onSuccess(Coordinate coord) { + Log.e("CoordinateService onSuccess", String.valueOf(coord)); + } + + @SuppressLint("LongLogTag") + @Override + public void onError(Throwable e) { + + Log.e("CoordinateService onError", e.getMessage()); + + if (e instanceof HttpException) { + ResponseBody responseBody = ((HttpException) e).response().errorBody(); + Log.e("CoordinateService onError", RestApiHelper.getErrorMessage(responseBody)); + + } + } + })); + } catch (IllegalArgumentException e) { + Log.e("CoordinateService onError",e.toString()); + } } @Override @@ -281,81 +354,4 @@ public class BackgroundLocalizationService extends Service { Log.e(TAG, "onStatusChanged: " + provider); } } - - @SuppressLint("StaticFieldLeak") - private class Task extends AsyncTask { - ApproximatedLocalization approximatedLocalization; - private Double latitude; - private Double longitude; - private Double altitude; - private String approximatedBuildingPart = null; - private CompositeDisposable disposable = new CompositeDisposable(); - private CoordinateService coordinateService = ApiClient.getClient(getApplicationContext()) - .create(CoordinateService.class); - - private Task(Location location) { - latitude = location.getLatitude(); - longitude = location.getLongitude(); - altitude = location.getAltitude(); - approximatedLocalization = new ApproximatedLocalization(mapUtils.loadJsonFromAsset(getApplicationContext(), "building.geojson")); - approximatedBuildingPart = approximatedLocalization.getNameOfBuildingPart(Point.fromLngLat(longitude, latitude)); - } - - @Override - protected Object doInBackground(Object[] objects) { - - if (PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.PRESENCE.toString())) { - latitude = presenceLatitude; - longitude = presencelongitude; - approximatedBuildingPart = presenceApproximatedName; - } else if (PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.APPROXIMATED.toString())) { - List points = approximatedLocalization.getMiddlePointOfBuildingPart(approximatedBuildingPart); - - latitude = points.get(0); - longitude = points.get(1); - } - - try { - Coordinate coordinate = new Coordinate( - latitude, - longitude, - altitude, - approximatedBuildingPart, - (PrefUtils.isStatusEnabled(getApplicationContext())) ? PrefUtils.getUserStatus(getApplicationContext()) : "", - PrefUtils.getUserId(getApplicationContext()), - PrefUtils.getLocationLevel(getApplicationContext()) - ); - - disposable.add( - coordinateService - .postCoordinate(coordinate) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeWith(new DisposableSingleObserver() { - @SuppressLint("LongLogTag") - @Override - public void onSuccess(Coordinate coord) { - Log.e("CoordinateService onSuccess", String.valueOf(coord)); - } - - @SuppressLint("LongLogTag") - @Override - public void onError(Throwable e) { - - Log.e("CoordinateService onError", e.getMessage()); - - if (e instanceof HttpException) { - ResponseBody responseBody = ((HttpException) e).response().errorBody(); - Log.e("CoordinateService onError", RestApiHelper.getErrorMessage(responseBody)); - - } - } - })); - } catch (IllegalArgumentException e) { - Timber.e(String.valueOf(e)); - } - - return null; - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/uam/wmi/findmytutor/service/FeedbackService.java b/app/src/main/java/com/uam/wmi/findmytutor/service/FeedbackService.java index a6d166c..6461a19 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/service/FeedbackService.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/service/FeedbackService.java @@ -10,8 +10,8 @@ import retrofit2.http.POST; public interface FeedbackService { @POST("api/Feedback") - Observable> postFeedback(@Body Feedback feedback); + Observable postFeedback(@Body Feedback feedback); @GET("api/Feedback") - Single getFeedback(); + Observable getFeedback(); } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/service/TutorTabApi.java b/app/src/main/java/com/uam/wmi/findmytutor/service/TutorTabApi.java index e2f6d9a..e5ba6b1 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/service/TutorTabApi.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/service/TutorTabApi.java @@ -51,7 +51,7 @@ public interface TutorTabApi { "Content-Type:application/json" }) @PUT("api/users/tutorTab/{tutorId}") - Observable apiUsersTutorTabByTutorIdPut( + Observable apiUsersTutorTabByTutorIdPut( @retrofit2.http.Path("tutorId") String tutorId, @retrofit2.http.Body TutorTabViewModel tutorTab ); diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/Consts.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/Consts.java index bedd885..3a827f2 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/utils/Consts.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/Consts.java @@ -1,7 +1,12 @@ package com.uam.wmi.findmytutor.utils; +import android.util.Range; + public class Consts { - public final static Double presenceLatitude = 65.600244; - public final static Double presencelongitude = 480.032153; + public final static Double presenceLatitude = 52.466365; + public final static Double presenceLongitude = 16.926792; public final static String presenceApproximatedName = "unknown"; + public final static Range latitudeRange = Range.create(52.466709, 52.467007); + public final static Range longtitudeRange = Range.create(16.926159, 16.926976); + } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/FeedbackUtils.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/FeedbackUtils.java index ab12f54..e02f4f3 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/utils/FeedbackUtils.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/FeedbackUtils.java @@ -77,31 +77,42 @@ public class FeedbackUtils { private void sendFeedback(String header, String body, boolean mode) { String appVersion = null; String metadata = null; + Feedback userFeedback= null; try { appVersion = activityContext.getPackageManager().getPackageInfo(activityContext.getPackageName(), 0).versionName; if( !mode ){ - metadata = "\n-----------------------------\n" + - "User ID: " + PrefUtils.getUserId(activityContext) + "\n" + - "Device OS: Android\n" + - "Device OS version: " + Build.VERSION.RELEASE + "\n" + - "App Version: " + appVersion + "\n" + - "Device Model: " + Build.MODEL + "\n" + - "Device Manufacturer: " + Build.MANUFACTURER + "\n" + - "-----------------------------\n"; - body = metadata + body; - header = header + " - " + PrefUtils.getUserFirstName(activityContext) + " " + PrefUtils.getUserLastName(activityContext); + body = PrefUtils.getUserFirstName(activityContext) + " " + PrefUtils.getUserLastName(activityContext) + "\n" + body; + userFeedback = new Feedback(mode, + header, + PrefUtils.getUserId(activityContext), + "Android "+ Build.VERSION.RELEASE, + appVersion, + Build.MODEL, + body); + Log.d("FEEDBACK non anon", userFeedback.toString()); + + }else{ + userFeedback = new Feedback(mode, + header, + "anonymous", + "Android "+ Build.VERSION.RELEASE, + appVersion, + Build.MODEL, + body); + Log.d("FEEDBACK anon",userFeedback.toString()); } } catch (PackageManager.NameNotFoundException e) { + } FeedbackService feedbackService = ApiClient.getClient(activityContext).create(FeedbackService.class); - Feedback userFeedback = new Feedback(mode,header,body); + CompositeDisposable disposable = new CompositeDisposable(); disposable.add(feedbackService.postFeedback(userFeedback) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::handleResponse, this::handleError)); } - private void handleResponse(Response resp) { + private void handleResponse( Void resp) { Toast.makeText(activityContext, activityContext.getString(R.string.modal_feedback_thankyou), Toast.LENGTH_SHORT).show(); } @@ -113,9 +124,9 @@ public class FeedbackUtils { RestApiHelper.getErrorMessage(responseBody), Toast.LENGTH_SHORT).show(); } else { - Toast.makeText(activityContext, - "Network error " + error.getMessage(), Toast.LENGTH_SHORT).show(); - Log.d("FEEDBACK",error.getMessage()); +// Toast.makeText(activityContext, +// "Network error " + error.getMessage(), Toast.LENGTH_SHORT).show(); + Log.d("FEEDBACK handerr ",error.getMessage()); } } } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/ManualLocationUtils.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/ManualLocationUtils.java new file mode 100644 index 0000000..6de0208 --- /dev/null +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/ManualLocationUtils.java @@ -0,0 +1,61 @@ +package com.uam.wmi.findmytutor.utils; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.Fragment; +import android.content.Context; +import android.content.DialogInterface; +import android.preference.PreferenceFragment; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.uam.wmi.findmytutor.R; +import com.uam.wmi.findmytutor.activity.BaseActivity; +import com.uam.wmi.findmytutor.activity.MapActivity; +import com.uam.wmi.findmytutor.model.PredefinedCoordViewModel; +import com.uam.wmi.findmytutor.network.ApiClient; +import com.uam.wmi.findmytutor.service.PredefinedStatusesService; + +import java.util.List; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; +import okhttp3.ResponseBody; + +import static com.mapbox.mapboxsdk.Mapbox.getApplicationContext; +import static java.security.AccessController.getContext; + +@SuppressLint("ValidFragment") +public class ManualLocationUtils { + private Context activityContext; + + public ManualLocationUtils(Context context) { + activityContext = context; + } + + + + private void handleError(Throwable error) { + if (error instanceof HttpException) { + + ResponseBody responseBody = ((HttpException) error).response().errorBody(); + Toast.makeText(activityContext, + RestApiHelper.getErrorMessage(responseBody), Toast.LENGTH_SHORT).show(); + + } else { + Toast.makeText(activityContext, + "Network error " + error.getMessage(), Toast.LENGTH_SHORT).show(); + } + } +} diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/MapMarker.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/MapMarker.java new file mode 100644 index 0000000..fd8a63b --- /dev/null +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/MapMarker.java @@ -0,0 +1,65 @@ +package com.uam.wmi.findmytutor.utils; + +import android.support.annotation.NonNull; +import android.view.View; + +import com.mapbox.mapboxsdk.annotations.Icon; +import com.mapbox.mapboxsdk.annotations.InfoWindow; +import com.mapbox.mapboxsdk.annotations.Marker; +import com.mapbox.mapboxsdk.annotations.MarkerOptions; +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.maps.MapboxMap; + +public class MapMarker{ + + private MarkerOptions markerOptions; + private Marker marker; + private String markerType; + private Icon defaultIcon; + private Icon markerIcon; + + + public MapMarker(Marker marker, MarkerOptions markerOptions, Icon icon, String markerType) { + this.setMarker(marker); + this.setMarkerOptions(markerOptions); + this.defaultIcon = icon; + this.markerType = markerType; + } + + public void restoreDefaultIcon() { + this.marker.setIcon(this.defaultIcon); + } + + public void setDefaultIcon(Icon icon) { + this.defaultIcon = icon; + } + + private void changeMarkerType(String markerType) { + this.markerType = markerType; + } + + public MarkerOptions getMarkerOptions() { + return markerOptions; + } + + private void setMarkerOptions(MarkerOptions marker) { + this.markerOptions = marker; + } + + public Marker getMarker() { + return marker; + } + + public void setMarker(Marker marker) { + this.marker = marker; + } + + public String getMarkerType() { + return markerType; + } + + public void setMarkerType(String markerType) { + this.markerType = markerType; + } + +} diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/PrefUtils.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/PrefUtils.java index 6a8793b..ba253ce 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/utils/PrefUtils.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/PrefUtils.java @@ -5,6 +5,8 @@ import android.content.SharedPreferences; import android.preference.ListPreference; import android.preference.PreferenceFragment; import android.util.Log; + +import com.mapbox.mapboxsdk.geometry.LatLng; import com.uam.wmi.findmytutor.activity.SharingFragment; import com.auth0.android.jwt.Claim; import com.auth0.android.jwt.JWT; @@ -20,11 +22,11 @@ public class PrefUtils { return context.getSharedPreferences("com.uam.wmi.findmytutor_preferences", Context.MODE_PRIVATE); } - public static void getAllKeys(Context context){ - Map keys = getSharedPreferences(context).getAll(); + public static void getAllKeys(Context context) { + Map keys = getSharedPreferences(context).getAll(); - for(Map.Entry entry : keys.entrySet()){ - Log.d("map values",entry.getKey() + ": " + entry.getValue().toString()); + for (Map.Entry entry : keys.entrySet()) { + Log.d("map values", entry.getKey() + ": " + entry.getValue().toString()); } } @@ -54,14 +56,16 @@ public class PrefUtils { return getSharedPreferences(context).getString("USER_ID", null); } - public static boolean isStatusEnabled(Context context){ - return getSharedPreferences(context).getBoolean("key_status_enabled",false); + public static boolean isStatusEnabled(Context context) { + return getSharedPreferences(context).getBoolean("key_status_enabled", false); } + public static String getUserStatus(Context context) { return getSharedPreferences(context).getString("status_entry", "Available"); } - public static void storeStatus(Context context, String status){ + + public static void storeStatus(Context context, String status) { SharedPreferences.Editor editor = getSharedPreferences(context).edit(); editor.putString("status_entry", status); editor.apply(); @@ -91,15 +95,17 @@ public class PrefUtils { return getSharedPreferences(context).getBoolean("key_sharing_enabled", false); } - public static void storeEnableSharingLocalization(Context context,Boolean isChecked) { + public static void storeEnableSharingLocalization(Context context, Boolean isChecked) { SharedPreferences.Editor editor = getSharedPreferences(context).edit(); editor.putBoolean("key_sharing_enabled", isChecked); editor.apply(); } - public static String getLocationLevel(Context context){ + + public static String getLocationLevel(Context context) { return getSharedPreferences(context).getString("location_mode", "exact"); } - public static void storeLocationMode(Context context, String mode){ + + public static void storeLocationMode(Context context, String mode) { SharedPreferences.Editor editor = getSharedPreferences(context).edit(); editor.putString("location_mode", mode); editor.apply(); @@ -150,4 +156,23 @@ public class PrefUtils { editor.putBoolean("BACKGROUND_SERVICE_STATUS", status); editor.apply(); } + + public static void putManualLocation(Context context, LatLng latLng) { + SharedPreferences.Editor editor = getSharedPreferences(context).edit(); + editor.putString("key_location_level","3"); + editor.putString("location_mode", "manual"); + editor.putBoolean("key_sharing_enabled", true); + editor.putLong("longitude_manual_location", Double.doubleToRawLongBits(latLng.getLongitude())); + editor.putLong("latitude_manual_location", Double.doubleToRawLongBits(latLng.getLatitude())); + Log.d("SAVE_COORD","zapisane"); + editor.apply(); + } + + public static LatLng getManualLocation(Context context) { + return new LatLng( + Double.longBitsToDouble(getSharedPreferences(context).getLong("latitude_manual_location", 0)), + Double.longBitsToDouble(getSharedPreferences(context).getLong("longitude_manual_location", 0)) + ); + } + } \ No newline at end of file diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/SharingLevel.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/SharingLevel.java index b9b04f2..0acdb11 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/utils/SharingLevel.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/SharingLevel.java @@ -4,6 +4,7 @@ public enum SharingLevel { PRESENCE("presence"), APPROXIMATED("approximated"), EXACT("exact"), + PREDEFINED("predefined"), MANUAL("manual"); private final String text; diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/mapUtils.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/mapUtils.java index 6d80d3e..12d05ac 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/utils/mapUtils.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/mapUtils.java @@ -3,6 +3,7 @@ package com.uam.wmi.findmytutor.utils; import android.animation.TypeEvaluator; import android.content.Context; import android.graphics.Color; +import android.location.Location; import android.view.Gravity; import android.view.View; import android.widget.FrameLayout; @@ -18,10 +19,14 @@ import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.style.layers.FillLayer; import com.mapbox.mapboxsdk.style.layers.Layer; +import com.uam.wmi.findmytutor.model.Coordinate; import java.io.IOException; import java.io.InputStream; +import static com.uam.wmi.findmytutor.utils.Consts.latitudeRange; +import static com.uam.wmi.findmytutor.utils.Consts.longtitudeRange; + public class mapUtils { // Boundires @@ -36,7 +41,7 @@ public class mapUtils { if (check) { // Set bounds to WMI mapboxMap.setLatLngBoundsForCameraTarget(WMI_BOUNDS); - makeNewCamera(mapboxMap, 52.466799, 16.927002, 17, 0, 0, 4000); + makeNewCamera(mapboxMap, 52.466799, 16.927002, 16, 0, 0, 4000); mapboxMap.setMinZoomPreference(16); // TODO export to map config } else { mapboxMap.setLatLngBoundsForCameraTarget(null); @@ -73,6 +78,10 @@ public class mapUtils { } } + public static Boolean checkIfCoordinateIsValid(Location coordinate){ + return (!latitudeRange.contains(coordinate.getLatitude()) && !longtitudeRange.contains(coordinate.getLongitude())); + } + // Function for marker animation public static class LatLngEvaluator implements TypeEvaluator { // Method is used to interpolate the marker animation. diff --git a/app/src/main/res/drawable-v21/custom_marker.png b/app/src/main/res/drawable-v21/custom_marker.png deleted file mode 100644 index 1df09fd..0000000 Binary files a/app/src/main/res/drawable-v21/custom_marker.png and /dev/null differ diff --git a/app/src/main/res/drawable-v24/custom_marker.png b/app/src/main/res/drawable-v24/custom_marker.png deleted file mode 100644 index 1df09fd..0000000 Binary files a/app/src/main/res/drawable-v24/custom_marker.png and /dev/null differ diff --git a/app/src/main/res/drawable/approximate_localization_marker.png b/app/src/main/res/drawable/approximate_localization_marker.png new file mode 100644 index 0000000..6f35fd3 Binary files /dev/null and b/app/src/main/res/drawable/approximate_localization_marker.png differ diff --git a/app/src/main/res/drawable/blue_marker.png b/app/src/main/res/drawable/blue_marker.png deleted file mode 100644 index 7bbbd9b..0000000 Binary files a/app/src/main/res/drawable/blue_marker.png and /dev/null differ diff --git a/app/src/main/res/drawable/custom_marker.png b/app/src/main/res/drawable/custom_marker.png deleted file mode 100644 index 8b1f284..0000000 Binary files a/app/src/main/res/drawable/custom_marker.png and /dev/null differ diff --git a/app/src/main/res/drawable/exact_localization_marker.png b/app/src/main/res/drawable/exact_localization_marker.png new file mode 100644 index 0000000..be49182 Binary files /dev/null and b/app/src/main/res/drawable/exact_localization_marker.png differ diff --git a/app/src/main/res/drawable/green_marker.png b/app/src/main/res/drawable/green_marker.png deleted file mode 100644 index 0babab0..0000000 Binary files a/app/src/main/res/drawable/green_marker.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_info_black_24dp.xml b/app/src/main/res/drawable/ic_info_black_24dp.xml new file mode 100644 index 0000000..34b8202 --- /dev/null +++ b/app/src/main/res/drawable/ic_info_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_notifications_black_24dp.xml b/app/src/main/res/drawable/ic_notifications_black_24dp.xml new file mode 100644 index 0000000..e3400cf --- /dev/null +++ b/app/src/main/res/drawable/ic_notifications_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_sync_black_24dp.xml b/app/src/main/res/drawable/ic_sync_black_24dp.xml new file mode 100644 index 0000000..5a283aa --- /dev/null +++ b/app/src/main/res/drawable/ic_sync_black_24dp.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/logo_black.xml b/app/src/main/res/drawable/logo_black.xml new file mode 100644 index 0000000..e55f258 --- /dev/null +++ b/app/src/main/res/drawable/logo_black.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/manual_localization_marker.png b/app/src/main/res/drawable/manual_localization_marker.png new file mode 100644 index 0000000..89adebf Binary files /dev/null and b/app/src/main/res/drawable/manual_localization_marker.png differ diff --git a/app/src/main/res/drawable/my_marker.png b/app/src/main/res/drawable/my_marker.png new file mode 100644 index 0000000..f63d50f Binary files /dev/null and b/app/src/main/res/drawable/my_marker.png differ diff --git a/app/src/main/res/drawable/purple_marker.png b/app/src/main/res/drawable/purple_marker.png deleted file mode 100644 index b3cdf26..0000000 Binary files a/app/src/main/res/drawable/purple_marker.png and /dev/null differ diff --git a/app/src/main/res/drawable/red_marker.png b/app/src/main/res/drawable/red_marker.png deleted file mode 100644 index 6b72939..0000000 Binary files a/app/src/main/res/drawable/red_marker.png and /dev/null differ diff --git a/app/src/main/res/drawable/search_marker.png b/app/src/main/res/drawable/search_marker.png new file mode 100644 index 0000000..cc8d803 Binary files /dev/null and b/app/src/main/res/drawable/search_marker.png differ diff --git a/app/src/main/res/drawable/yellow_marker.png b/app/src/main/res/drawable/yellow_marker.png deleted file mode 100644 index 85b97e1..0000000 Binary files a/app/src/main/res/drawable/yellow_marker.png and /dev/null differ diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml index 33c99a8..5e5c5a2 100644 --- a/app/src/main/res/layout/activity_map.xml +++ b/app/src/main/res/layout/activity_map.xml @@ -16,7 +16,7 @@ mapbox:mapbox_cameraTargetLat="52.466799" mapbox:mapbox_cameraTargetLng="16.927002" mapbox:mapbox_cameraZoom="17" - mapbox:mapbox_styleUrl="mapbox://styles/domagalsky/cjiyzrqjp05l72rmj6ntvv2n8"> + mapbox:mapbox_styleUrl="mapbox://styles/domagalsky/cjo8yjhfj0ih02rld5rft5nv7"> diff --git a/app/src/main/res/layout/activity_tutor_tab.xml b/app/src/main/res/layout/activity_tutor_tab.xml new file mode 100644 index 0000000..5c5d96f --- /dev/null +++ b/app/src/main/res/layout/activity_tutor_tab.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_tutor_tab.xml b/app/src/main/res/layout/content_tutor_tab.xml new file mode 100644 index 0000000..8bfd4bf --- /dev/null +++ b/app/src/main/res/layout/content_tutor_tab.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + +