Merge branch 'developMieszko27nov' of s416084/find-my-tutor-android into master

This commit is contained in:
Mieszko Wrzeszczyński 2018-11-29 21:35:16 +00:00 committed by Gogs
commit a7ba5bf27c
73 changed files with 1243 additions and 492 deletions

View File

@ -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'
}

View File

@ -25,7 +25,6 @@
android:theme="@style/AppTheme">
<activity
android:name=".activity.StartupActivity"
android:label="@string/title_activity_startup"
android:launchMode="singleInstance"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
@ -36,17 +35,14 @@
</activity>
<activity
android:name=".activity.MapActivity"
android:label="@string/map_activity_label"
android:launchMode="singleTop" />
<activity
android:name=".activity.LoginActivity"
android:excludeFromRecents="true"
android:label="@string/title_activity_login"
android:launchMode="singleTask"
android:noHistory="true" />
<activity
android:name=".activity.SettingsActivity"
android:label="@string/title_activity_settings" />
android:name=".activity.SettingsActivity" />
<service
android:name=".service.BackgroundLocalizationService"
@ -54,6 +50,9 @@
android:exported="false"
android:launchMode="singleTop" />
<activity
android:name=".activity.TutorTab"
android:theme="@style/AppTheme"></activity>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -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<String, ObservableSource<String>>) 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) {

View File

@ -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());
}
}

View File

@ -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<String, Coordinate> coordsMap = new HashMap<>();
private HashMap<String, Marker> markerHash = new HashMap<>();
private HashMap<String, MapMarker> markerHash = new HashMap<>();
private HashMap<Long, String> markerUserHash = new HashMap<>();
private Set<String> 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<Coordinate>() {
@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<PredefinedCoordViewModel> 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<List<Coordinate>>() {
@Override
public void onSuccess(List<Coordinate> coordsList) {
if (coordsList.isEmpty() && tmpLocalMarker != null) {
if (tmpLocalMarker != null && coordsList.isEmpty()) {
Timber.e("200 empty []");
mapboxMap.clear();
return;
}
ArrayList<String> 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<User> users) {
restoreMapMarkers();
Icon icon1 = IconFactory.getInstance(MapActivity.this).fromResource(R.drawable.custom_marker);
List<Marker> 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<MapMarker> 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();
}
}

View File

@ -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<Integer, String> locationLevelMapping;
private HashMap<Integer, String> 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<PredefinedCoordViewModel> predefinedCoordsList = new ArrayList<>();
private HashMap<Integer, String> locationLevelMapping;
private HashMap<Integer, String> 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<List<String>>() {
@Override
public void onSuccess(List<String> 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<List<PredefinedCoordViewModel>>() {
@Override
public void onSuccess(List<PredefinedCoordViewModel> coords) {
List<String> 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<Integer, String>();
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<Integer, String>();
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<String> defaultEntries = new HashSet(Arrays.asList(entries));
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
Set <String> 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<String> 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<String> 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());
}
}

View File

@ -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<TutorTabViewModel>() {
@Override
public void onSuccess(TutorTabViewModel tutorTabViewModel) {
List<String> 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<User>() {
@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();
}
}

View File

@ -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<User> tutorsList = new ArrayList<>();
private List<User> 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) {

View File

@ -14,8 +14,8 @@ import io.swagger.annotations.ApiModelProperty;
*/
public class Coordinate extends BaseResponse {
Range<Double> latitudeRange = Range.create(52.466709, 52.467007);
Range<Double> longtitudeRange = Range.create(16.926159, 16.926976);
Range<Double> latitudeRange = Range.create(52.46598, 52.467545);
Range<Double> 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;

View File

@ -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;
}
}
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;

View File

@ -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);
}
}

View File

@ -33,11 +33,19 @@ public class TutorTabViewModel {
@SerializedName("dutyHours")
private List<DutyHourViewModel> 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

View File

@ -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();
}

View File

@ -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) {

View File

@ -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> S createService(Class<S> serviceClass) {
if (!httpClient.interceptors().contains(logging)) {
httpClient.addInterceptor(logging);
builder.client(httpClient.build());
retrofit = builder.build();
}
return retrofit.create(serviceClass);
}
public static <S> S createService(Class<S> 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);
}
}

View File

@ -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<String> providers = new ArrayList<String>();
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<String> providers = new ArrayList<String>();
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<Double> 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<Coordinate>() {
@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<Double> 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<Coordinate>() {
@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;
}
}
}

View File

@ -10,8 +10,8 @@ import retrofit2.http.POST;
public interface FeedbackService {
@POST("api/Feedback")
Observable<Response<Void>> postFeedback(@Body Feedback feedback);
Observable<Void> postFeedback(@Body Feedback feedback);
@GET("api/Feedback")
Single<Feedback> getFeedback();
Observable<Void> getFeedback();
}

View File

@ -51,7 +51,7 @@ public interface TutorTabApi {
"Content-Type:application/json"
})
@PUT("api/users/tutorTab/{tutorId}")
Observable<Void> apiUsersTutorTabByTutorIdPut(
Observable<TutorTabViewModel> apiUsersTutorTabByTutorIdPut(
@retrofit2.http.Path("tutorId") String tutorId, @retrofit2.http.Body TutorTabViewModel tutorTab
);

View File

@ -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<Double> latitudeRange = Range.create(52.466709, 52.467007);
public final static Range<Double> longtitudeRange = Range.create(16.926159, 16.926976);
}

View File

@ -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<Void> 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());
}
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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<String,?> keys = getSharedPreferences(context).getAll();
public static void getAllKeys(Context context) {
Map<String, ?> keys = getSharedPreferences(context).getAll();
for(Map.Entry<String,?> entry : keys.entrySet()){
Log.d("map values",entry.getKey() + ": " + entry.getValue().toString());
for (Map.Entry<String, ?> 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))
);
}
}

View File

@ -4,6 +4,7 @@ public enum SharingLevel {
PRESENCE("presence"),
APPROXIMATED("approximated"),
EXACT("exact"),
PREDEFINED("predefined"),
MANUAL("manual");
private final String text;

View File

@ -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<LatLng> {
// Method is used to interpolate the marker animation.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zm1,15h-2v-6h2v6zm0,-8h-2V7h2v2z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M11.5,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zm6.5,-6v-5.5c0,-3.07 -2.13,-5.64 -5,-6.32V3.5c0,-0.83 -0.67,-1.5 -1.5,-1.5S10,2.67 10,3.5v0.68c-2.87,0.68 -5,3.25 -5,6.32V16l-2,2v1h17v-1l-2,-2z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01,-.25 1.97,-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0,-4.42,-3.58,-8,-8,-8zm0 14c-3.31 0,-6,-2.69,-6,-6 0,-1.01.25,-1.97.7,-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4,-4,-4,-4v3z" />
</vector>

View File

@ -0,0 +1,16 @@
<vector android:height="24dp" android:viewportHeight="61.7"
android:viewportWidth="61.34" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M52.65,41.79A25.13,25.13 0,0 1,45.36 46.96c-1.49,0.71 -29,8.51 -40.74,11.82 -1,0.27 -1.86,0.52 -2.58,0.73 0.18,-0.73 0.39,-1.61 0.66,-2.6C5.68,45.29 12.62,17.99 13.28,16.5a24.77,24.77 0,0 1,5 -7.31A25.57,25.57 0,0 1,52.02 6.72c0.35,0.27 0.7,0.56 1.05,0.86s0.61,0.65 0.9,1A24.48,24.48 0,0 1,52.65 41.79Z"/>
<path android:fillColor="#FF000000" android:pathData="M43.05,45.73"/>
<path android:fillColor="#FF000000" android:pathData="M21.13,27.35l1,1.75 3.54,-2 1.51,2.65 -3.54,2L25.81,35.6l-3.06,1.73 -6.24,-11 7,-4 1.56,2.74Z"/>
<path android:fillColor="#FF000000" android:pathData="M24.36,20.54l1.41,2.49 2.88,-1.64 -1.41,-2.48ZM26.36,24.1L31.14,32.6 32.36,27.81l-3,-5.37Z"/>
<path android:fillColor="#FF000000" android:pathData="M41.36,19.96 L44.36,25.14 41.36,26.8l-2.7,-4.78c-0.56,-1 -1.21,-1.27 -2,-0.85 -0.91,0.52 -1.07,1.45 -0.46,2.53l2.57,4.54L35.91,29.9l-4.81,-8.5 2,-1.16 0.9,0.65a4.07,4.07 0,0 1,2 -2.65C38.06,17.13 40.15,17.79 41.36,19.96Z"/>
<path android:fillColor="#FF000000" android:pathData="M48.48,7.5l6.55,11.57L52.86,20.29l-0.63,-0.47a4.51,4.51 0,0 1,-2 2.37,5 5,0 0,1 -7,-2 5,5 0,0 1,1.89 -7,4.58 4.58,0 0,1 2.45,-0.61l-1.91,-3.38ZM49.91,16.35a2.19,2.19 0,1 0,-0.8 3A2.16,2.16 0,0 0,49.91 16.35Z"/>
<path android:fillColor="#FF000000" android:pathData="M20.42,39.69l-3,1.7 4.69,8.28 -3,1.72L14.36,43.11l-3,1.7 -1.54,-2.73 9,-5.12Z"/>
<path android:fillColor="#FF000000" android:pathData="M23.58,44.03l-2.75,-4.85 2.93,-1.66 2.67,4.72a1.43,1.43 0,0 0,2.07 0.71,1.41 1.41,0 0,0 0.45,-2.13l-2.67,-4.73 2.93,-1.65 2.74,4.84c1.35,2.38 0.55,4.88 -2,6.3S24.93,46.4 23.58,44.03Z"/>
<path android:fillColor="#FF000000" android:pathData="M40.02,36.15l1.45,2.56 -2,1.14a3.21,3.21 0,0 1,-4.74 -1.33l-1.82,-3.2L31.36,36.2l-0.39,-0.68 1.51,-6.21 0.6,-0.34 1.41,2.48 2.13,-1.21 1.28,2.25 -2.06,1.17L37.36,36.37a1,1 0,0 0,1.54 0.41Z"/>
<path android:fillColor="#FF000000" android:pathData="M39.91,33.95a5.15,5.15 0,0 1,2.2 -7.22,5.21 5.21,0 1,1 5.13,9.05A5.16,5.16 0,0 1,39.91 33.95ZM45.75,33.15a2.18,2.18 0,1 0,-2.91 -0.86,2 2,0 0,0 2.91,0.86Z"/>
<path android:fillColor="#FF000000" android:pathData="M53.83,20.43 L55.36,23.11l-1.14,0.64a1.49,1.49 0,0 0,-0.6 2.37l2.45,4.33L53.13,32.1 48.36,23.6l2,-1.11 1,0.68a3.28,3.28 0,0 1,1.79 -2.31Z"/>
<path android:fillColor="#FF000000" android:pathData="M17.17,35.42l0.94,1.67 -0.91,0.52L16.36,36.06c-0.16,-0.28 -0.34,-0.36 -0.53,-0.25s-0.28,0.39 -0.09,0.73l0.82,1.45 -0.89,0.51 -0.88,-1.56c-0.15,-0.26 -0.33,-0.35 -0.53,-0.24s-0.28,0.39 -0.09,0.72l0.82,1.46 -0.91,0.52 -1.51,-2.66 0.65,-0.36 0.29,0.21a1.14,1.14 0,0 1,0.57 -0.8,1 1,0 0,1 1,0 1.23,1.23 0,0 1,0.6 -0.86A1.11,1.11 0,0 1,17.17 35.42Z"/>
<path android:fillColor="#FF000000" android:pathData="M18.69,33.26l0.3,1.75 -1.39,-1.13 -1,0.56 2.47,1.82a0.61,0.61 0,0 1,0 0.48l0.47,0.84c0.48,-0.36 0.58,-0.84 0.49,-1.71l-0.31,-3.17Z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -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">
</com.mapbox.mapboxsdk.maps.MapView>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.TutorTab">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_tutor_tab" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:paddingTop="@dimen/activity_margin">
<TextView android:id="@+id/userName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen_10"
android:fontFamily="sans-serif-medium"
android:lineSpacingExtra="8sp"
android:textColor="@color/colorAccent"
android:textSize="@dimen/lbl_new_note_title"
android:textStyle="normal" />
<TextView
android:id="@+id/userDepartment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="8sp"
android:paddingTop="5dp"
android:textColor="@color/note_list_text"
/>
<TextView
android:id="@+id/userRoom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="8sp"
android:paddingTop="5dp"
android:textColor="@color/note_list_text"
/>
<TextView
android:id="@+id/userEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="8sp"
android:paddingTop="5dp"
android:textColor="@color/note_list_text" />
<TextView
android:id="@+id/userDutyHours"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="8sp"
android:paddingTop="5dp"
android:textColor="@color/note_list_text"
tools:text="@string/dutyHours" />
<TextView
android:id="@+id/userNoteTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:paddingStart="@dimen/activity_margin"
android:textColor="@color/note_list_text" />
<EditText
android:id="@+id/userNote"
android:layout_width="match_parent"
android:layout_height="150dp"
android:lineSpacingExtra="8sp"
android:paddingTop="5dp"
android:textColor="@color/note_list_text"
android:hint="@string/tutorTabHint"
android:inputType="textMultiLine"
android:maxLength="1000"
android:maxLines="7"
android:requiresFadingEdge="vertical"
android:scrollbars="vertical"/>
<Button
android:id="@+id/saveButon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/saveButton" />
</LinearLayout>

View File

@ -15,21 +15,30 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/feedback_input"
android:layout_marginBottom="@dimen/dimen_10"
android:layout_marginBottom="15dp"
android:fontFamily="sans-serif-medium"
android:lineSpacingExtra="8sp"
android:lineSpacingExtra="10sp"
android:text="placeholder"
android:textColor="@color/colorAccent"
android:textSize="@dimen/lbl_new_note_title"
android:textStyle="normal" />
<TextView
android:id="@+id/feedback_modal_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:text="placeholder"
android:textColor="@color/note_list_text"
android:textSize="14sp" />
<EditText
android:id="@+id/feedback_input"
android:layout_width="315dp"
android:layout_height="150dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:layout_marginTop="70dp"
android:ems="10"
android:hint="@string/modal_feedback_hint"
android:inputType="textMultiLine"
@ -55,13 +64,5 @@
android:layout_alignEnd="@+id/feedback_input"
android:textSize="14sp" />
<TextView
android:id="@+id/feedback_modal_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/feedback_input"
android:layout_alignEnd="@+id/feedback_input"
android:layout_marginEnd="0dp"
android:layout_marginBottom="-50dp"
android:textSize="14sp" />
</RelativeLayout>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<TextView
android:id="@+id/feedback_modal_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/feedback_input"
android:layout_marginBottom="@dimen/dimen_10"
android:fontFamily="sans-serif-medium"
android:lineSpacingExtra="8sp"
android:text="@string/manual_modal_title"
android:textColor="@color/colorAccent"
android:textSize="@dimen/lbl_new_note_title"
android:textStyle="normal" />
<EditText
android:id="@+id/feedback_input"
android:layout_width="315dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:ems="10"
android:hint="@string/modal_feedback_hint"
android:maxLength="30"
android:maxLines="1"
android:textColor="@color/note_list_text"
android:requiresFadingEdge="vertical"
android:scrollbars="vertical" />
</RelativeLayout>

View File

@ -27,4 +27,14 @@
android:textColor="@color/note_list_text"
/>
<TextView
android:id="@+id/sharing_level"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="8sp"
android:paddingTop="5dp"
android:textColor="@color/note_list_text"
/>
</LinearLayout>

View File

@ -4,10 +4,6 @@
android:layout_height="match_parent">
<PreferenceCategory android:title="@string/settings_category_general">
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_notifications_enabled"
android:title="@string/title_notification" />
<ListPreference
android:defaultValue="0"

View File

@ -24,7 +24,6 @@
android:summary="%s"
android:title="@string/title_location_level" />
<ListPreference
android:defaultValue="1"
android:key="key_manual_location_value"
android:entries="@array/manual_location_entries"
android:entryValues="@array/manual_location_values"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/drawer_group_tutor">
<item
<!-- <item
android:id="@+id/nav_item_one"
android:icon="@drawable/ic_people_white"
android:title="@string/navigation_item_whitelist" />
<item
android:id="@+id/nav_item_two"
android:icon="@drawable/ic_people_black"
android:title="@string/navigation_item_blacklist" />
android:title="@string/navigation_item_blacklist" />-->
<item
android:id="@+id/nav_item_three"
android:icon="@drawable/outline_person_white_24dp"

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -26,7 +26,7 @@
<string name="lang_eng">Angielski</string>
<string name="lang_pol">Polski</string>
<string name="settings_language">Wybierz język</string>
<string name="mockup_location_string">\"\"</string>
<string name="pref_header_about">O aplikacji</string>
<string name="summary_about">
Jesteśmy grupą studentów, która chce pomoć w rozwoju naszego wydziału.\nDziękujemy za używanie naszej aplikacji.\nZespół FMT.!</string>
@ -144,6 +144,12 @@
<string name="title_feedback_report">FEEDBACK</string>
<string name="modal_feedback_send">WYŚLIJ</string>
<string name="modal_feedback_thankyou">Dziękujemy za przesłanie feedbacku.</string>
<string name="remove_manual_location">Usuń manualną lokację</string>
<string name="title_activity_tutor_tab">Profil</string>
<string name="saveButton">Zapisz</string>
<string name="tutorTabHint">Tutaj możesz dodać swoją notatkę. Będzie widoczna dla innych użytkowników.</string>
<string name="modal_location_send">WYŚLIJ</string>
<string name="modal_location_hint">Proszę nazwać wybraną lokację.</string>
</resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#A62613</color>
</resources>

View File

@ -82,6 +82,9 @@
<string name="settings_description">Descrition</string>
<string name="saveButton">Save</string>
<string name="tutorTabHint">Here you can add your note. It will be visible to the other users.</string>
<string name="key_description">key_description</string>
@ -117,7 +120,9 @@
<string name="title_version">Version</string>
<string name="choose_email_client">Choose email client</string>
<string name="title_activity_settings2">Settings</string>
<string name="modal_location_send">SEND</string>
<string name="modal_location_hint">Please name choosen location.</string>
modal_feedback_send
<!-- Strings related to Settings -->
<!-- Example General settings -->
@ -213,6 +218,10 @@
<string name="map_activity_label" translatable="false">MapActivity</string>
<string name="nav_profile">User profile</string>
<string name="remove_manual_location">Remove Manual location</string>
<string name="title_activity_tutor_tab">TutorTab</string>
<string name="manual_modal_title">Do you want to save this localization?</string>
<string name="lbl_ok">Save!</string>
<string name="lbl_cancel">Cancel!</string>
</resources>