Merge branch 'develop' into blackNwhiteLists

This commit is contained in:
Domagalski 2019-01-02 11:49:55 +01:00
commit c8e68e3bb6
19 changed files with 386 additions and 207 deletions

View File

@ -10,8 +10,8 @@ android {
applicationId "com.uam.wmi.findmytutor"
minSdkVersion 22
targetSdkVersion 27
versionCode 17
versionName "0.9.2-alpha"
versionCode 22
versionName "0.9.5-beta"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}

Binary file not shown.

View File

@ -38,6 +38,7 @@
</intent-filter>
</activity>
<activity
android:windowSoftInputMode="adjustPan"
android:name=".activity.MapActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTop"
@ -59,7 +60,6 @@
android:enabled="true"
android:exported="false"
android:launchMode="singleTop" />
<activity
android:name=".activity.TutorTab"
android:configChanges="keyboardHidden|orientation|screenSize"

View File

@ -8,18 +8,13 @@ import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Adapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
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.adapters.DutyHoursAdapter;
import com.uam.wmi.findmytutor.model.DutyHour;
import com.uam.wmi.findmytutor.model.DutyHourViewModel;
import com.uam.wmi.findmytutor.model.TutorTabViewModel;
import com.uam.wmi.findmytutor.model.User;
@ -36,11 +31,14 @@ import java.util.List;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.observers.DisposableCompletableObserver;
import io.reactivex.observers.DisposableSingleObserver;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
import retrofit2.Response;
import static java.lang.String.valueOf;
public class TutorTab extends AppCompatActivity {
private TutorTabApi tutorTabService;
private UserService userService;
@ -53,6 +51,7 @@ public class TutorTab extends AppCompatActivity {
private TextView department;
private Button addDutyButton;
private Button saveButon;
private Button scrapButton;
private Boolean ifTutorTabExists = true;
private List<DutyHourViewModel> dutyHourList;
private RecyclerView dutyHoursRecycller;
@ -72,69 +71,24 @@ public class TutorTab extends AppCompatActivity {
userEmail = findViewById(R.id.userEmail);
department = findViewById(R.id.userDepartment);
saveButon = findViewById(R.id.saveButon);
scrapButton = findViewById(R.id.scrapTutorTab);
addDutyButton = findViewById(R.id.addDuty);
dutyHoursRecycller = (RecyclerView) findViewById(R.id.dutyHourView);
dutyHoursRecycller = findViewById(R.id.dutyHourView);
dutyHoursLayoutManager = new LinearLayoutManager(this);
dutyHoursRecycller.setLayoutManager(dutyHoursLayoutManager);
tutorTabService = ApiClient.getClient(getApplicationContext())
.create(TutorTabApi.class);
userService = ApiClient.getClient(getApplicationContext())
.create(UserService.class);
disposable.add(
tutorTabService.apiUsersTutorTabByTutorIdGet(PrefUtils.getUserId(getApplicationContext()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<TutorTabViewModel>() {
@Override
public void onSuccess(TutorTabViewModel tutorTabViewModel) {
dutyHourList = tutorTabViewModel.getDutyHours();
if(dutyHourList == null){
}else{
dutyHoursAdapter = new DutyHoursAdapter(getApplicationContext(),dutyHourList);
dutyHoursRecycller.setAdapter(dutyHoursAdapter);
addDutyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addEmptyDuty(dutyHoursAdapter);
}
});
}
userRoom.setText(String.format("%s", tutorTabViewModel.getRoom()));
userEmail.setText(String.format("%s", tutorTabViewModel.getEmailTutorTab()));
if (!tutorTabViewModel.getNote().equals("")) {
userNote.setText(String.format("%s", tutorTabViewModel.getNote()));
}
}
@Override
public void onError(Throwable e) {
int code = ((HttpException) e).response().code();
if( code == 404){
ifTutorTabExists = false;
dutyHoursAdapter = new DutyHoursAdapter(getApplicationContext(),new ArrayList<DutyHourViewModel>());
dutyHoursRecycller.setAdapter(dutyHoursAdapter);
addDutyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addEmptyDuty(dutyHoursAdapter);
}
});
}
showError(e);
}
}));
getTutorTab();
findViewById(R.id.contentTutorTabInfoImageButton).setOnClickListener(v-> InfoHelperUtils.infoPopUp(v,R.layout.info_popup_tutor_tab));
userName.setText(String.format("%s %s", PrefUtils.getUserFirstName(getApplicationContext()), PrefUtils.getUserLastName(getApplicationContext())));
disposable.add(
userService.getUserById(PrefUtils.getUserId(getApplicationContext()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@ -153,7 +107,46 @@ public class TutorTab extends AppCompatActivity {
}
}));
setUpSaveListener(saveButon);
scrapButton.setOnClickListener(view -> scrapTutorTab());
}
private void getTutorTab(){
disposable.add(
tutorTabService.apiUsersTutorTabByTutorIdGet(PrefUtils.getUserId(getApplicationContext()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<TutorTabViewModel>() {
@Override
public void onSuccess(TutorTabViewModel tutorTabViewModel) {
dutyHourList = tutorTabViewModel.getDutyHours();
if(dutyHourList != null){
dutyHoursAdapter = new DutyHoursAdapter(getApplicationContext(),dutyHourList);
dutyHoursRecycller.setAdapter(dutyHoursAdapter);
addDutyButton.setOnClickListener(v -> addEmptyDuty(dutyHoursAdapter));
}
userRoom.setText(String.format("%s", tutorTabViewModel.getRoom()));
userEmail.setText(String.format("%s", tutorTabViewModel.getEmailTutorTab()));
if (!tutorTabViewModel.getNote().equals("")) {
userNote.setText(String.format("%s", tutorTabViewModel.getNote()));
}
}
@Override
public void onError(Throwable e) {
int code = ((HttpException) e).response().code();
if( code == 404){
ifTutorTabExists = false;
dutyHoursAdapter = new DutyHoursAdapter(getApplicationContext(),new ArrayList<DutyHourViewModel>());
dutyHoursRecycller.setAdapter(dutyHoursAdapter);
addDutyButton.setOnClickListener(v -> addEmptyDuty(dutyHoursAdapter));
}
showError(e);
}
}));
}
private void addEmptyDuty(DutyHoursAdapter adapter){
adapter.addDuty(new DutyHourViewModel());
adapter.notifyItemInserted(adapter.getItemCount());
@ -161,9 +154,7 @@ public class TutorTab extends AppCompatActivity {
}
private void setUpSaveListener(Button button) {
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
button.setOnClickListener(view -> {
newTab = new TutorTabViewModel(PrefUtils.getUserId(getApplicationContext()),
userRoom.getText().toString(),
userEmail.getText().toString(),
@ -175,7 +166,6 @@ public class TutorTab extends AppCompatActivity {
postUserTab(newTab);
ifTutorTabExists=true;
}
}
});
}
@ -185,23 +175,35 @@ public class TutorTab extends AppCompatActivity {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::handleResponsePut, this::handleError));
}
private void postUserTab(TutorTabViewModel tutorTabViewModel) {
disposable.add(tutorTabService.apiUsersTutorTabByTutorIdPost(PrefUtils.getUserId(getApplicationContext()), tutorTabViewModel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::handleResponsePost, this::handleError));
}
private void scrapTutorTab() {
disposable.add(tutorTabService.apiUsersScrapTutorTabByTutorIdPost(PrefUtils.getUserId(getApplicationContext()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::handleResponseScrap, this::handleError));
}
private void handleResponseScrap() {
Toast.makeText(getApplicationContext(), getApplicationContext().getString(R.string.scrap_tutor_msg), Toast.LENGTH_SHORT).show();
getTutorTab();
}
private void handleResponsePut(Response<Void> resp) {
Toast.makeText(getApplicationContext(), getApplicationContext().getString(R.string.updateToast), Toast.LENGTH_SHORT).show();
}
private void handleResponsePost(TutorTabViewModel tutorTabViewModel ) {
Toast.makeText(getApplicationContext(), getApplicationContext().getString(R.string.updateToast), Toast.LENGTH_SHORT).show();
}
private void handleError(Throwable error) {
if (error instanceof HttpException) {
@ -212,6 +214,10 @@ public class TutorTab extends AppCompatActivity {
} else {
Toast.makeText(getApplicationContext(),
"Network error " + error.getMessage(), Toast.LENGTH_SHORT).show();
Log.e("WMI SUCC", String.valueOf(error));
}
}

View File

@ -0,0 +1,46 @@
package com.uam.wmi.findmytutor.activity;
//import android.app.Fragment;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.app.FragmentTabHost;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.uam.wmi.findmytutor.R;
public class TutorsListTab extends Fragment {
private FragmentTabHost mTabHost;
public TutorsListTab() {
}
public static TutorsListTab newInstance() {
return new TutorsListTab();
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.tutors_list_tabs, container, false);
mTabHost = rootView.findViewById(android.R.id.tabhost);
mTabHost.setup(getActivity(), getFragmentManager(), R.id.realtabcontent);
mTabHost.addTab(mTabHost.newTabSpec("fragmentb").setIndicator("Fragment B"),
UsersListFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("fragmentc").setIndicator("Fragment C"),
UsersListFragment.class, null);
return rootView;
}
}

View File

@ -9,13 +9,16 @@ 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.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.annimon.stream.Stream;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
@ -28,8 +31,8 @@ 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.InfoHelperUtils;
import com.uam.wmi.findmytutor.utils.MyDividerItemDecoration;
import com.uam.wmi.findmytutor.utils.PrefUtils;
import com.uam.wmi.findmytutor.utils.RecyclerTouchListener;
import com.uam.wmi.findmytutor.utils.RestApiHelper;
@ -66,6 +69,7 @@ public class UsersListFragment extends Fragment {
private List<User> tutorsList = new ArrayList<>();
private List<User> tutorsFiltered = new ArrayList<>();
private Collator plCollator = Collator.getInstance(Locale.forLanguageTag("pl-PL"));
private Boolean fetchOnlyOnlineUsers = PrefUtils.getShowOnlyOnlineUsers(getApplicationContext());
public UsersListFragment() {
}
@ -78,7 +82,7 @@ public class UsersListFragment extends Fragment {
mAdapter = new TutorsListAdapter(getActivity().getApplicationContext(), tutorsFiltered);
View view = inflater.inflate(R.layout.users_list, container, false);
view.setBackgroundColor(getResources().getColor(android.R.color.white));
setHasOptionsMenu(true);
return view;
}
@ -113,6 +117,48 @@ public class UsersListFragment extends Fragment {
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
try {
menu.findItem(R.id.showOnlineUsersOnly).setChecked(fetchOnlyOnlineUsers);
}
catch(Exception e) {
Log.e(TAG, "onPrepareOptionsMenu error");
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
//item.setChecked(fetchOnlyOnlineUsers);
switch (item.getItemId()){
case R.id.showOnlineUsersOnly:
if(item.isChecked()) {
fetchOnlyOnlineUsers = false;
item.setChecked(false);
}else{
item.setChecked(true);
fetchOnlyOnlineUsers = true;
}
PrefUtils.putShowOnlyOnlineUsers(getApplicationContext(), fetchOnlyOnlineUsers);
fetchAllTutors();
break;
}
return false;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.users_list_menu, menu);
menu.getItem(0).setChecked(fetchOnlyOnlineUsers);
super.onCreateOptionsMenu(menu,inflater);
}
public void searchUser(String textToSearch) {
tutorsFiltered.clear();
@ -185,7 +231,9 @@ public class UsersListFragment extends Fragment {
private void fetchAllTutors() {
disposable.add(
userService.getAllTutors()
(fetchOnlyOnlineUsers ?
userService.getAllOnlineTutors() :
userService.getAllOfflineTutors())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(tutors -> {
@ -234,6 +282,7 @@ public class UsersListFragment extends Fragment {
private void showError(Throwable e) {
String message;
Log.e(TAG, String.valueOf(e));
if (e instanceof HttpException) {
ResponseBody responseBody = ((HttpException) e).response().errorBody();
@ -251,6 +300,11 @@ public class UsersListFragment extends Fragment {
noNotesView.setVisibility(View.GONE);
} else {
noNotesView.setVisibility(View.VISIBLE);
if(fetchOnlyOnlineUsers)
noNotesView.setText(R.string.no_online_users);
else{
noNotesView.setText(R.string.no_offline_users);
}
}
}

View File

@ -14,7 +14,6 @@ import android.location.Location;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.RequiresApi;
@ -25,7 +24,6 @@ import android.util.Log;
import com.annimon.stream.Stream;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
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;
@ -33,21 +31,17 @@ import com.uam.wmi.findmytutor.network.ApiClient;
import com.uam.wmi.findmytutor.utils.ApproximatedLocalization;
import com.uam.wmi.findmytutor.utils.MapUtils;
import com.uam.wmi.findmytutor.utils.PrefUtils;
import com.uam.wmi.findmytutor.utils.RestApiHelper;
import com.uam.wmi.findmytutor.utils.SharingLevel;
import org.apache.commons.collections4.queue.CircularFifoQueue;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.observers.DisposableCompletableObserver;
import io.reactivex.observers.DisposableSingleObserver;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
import static com.uam.wmi.findmytutor.utils.Const.offlineBackgroundLocationInterval;
import static com.uam.wmi.findmytutor.utils.Const.onlineBackgroundLocationInterval;
@ -60,32 +54,28 @@ import static java.lang.String.valueOf;
public class BackgroundLocalizationService extends Service {
private static final String TAG = "MyLocationService";
private static final float LOCATION_DISTANCE = 1f;
private static long notify_interval = onlineBackgroundLocationInterval;
private static long notify_interval_inside_building = onlineBackgroundLocationInterval;
private static long notify_interval_outside_building = offlineBackgroundLocationInterval;
private static int coordinatesHistoryLength = 5;
private static final Long LOCATION_INTERVAL = notify_interval;
private Location mLastLocation;
private Boolean stopService = false;
private ArrayList<String> providers = new ArrayList<String>();
private LocationListener[] mLocationListeners;
private CircularFifoQueue<Location> coordinatesHistory = new CircularFifoQueue<Location>(coordinatesHistoryLength);
private LocationManager mLocationManager = null;
private Handler mHandler = new Handler();
private Runnable mStatusChecker;
private FusedLocationProviderClient mFusedLocationClient;
private Location fakeLoc = null;
public BackgroundLocalizationService() {
providers.add(LocationManager.GPS_PROVIDER);
providers.add(LocationManager.NETWORK_PROVIDER);
providers.add(LocationManager.PASSIVE_PROVIDER);
fakeLoc = new Location("");
mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER),
new LocationListener(LocationManager.PASSIVE_PROVIDER)
};
fakeLoc.setLatitude(0);
fakeLoc.setLongitude(0);
fakeLoc.setAltitude(0);
}
@Override
@ -124,36 +114,20 @@ public class BackgroundLocalizationService extends Service {
startForeground(1001, notification);
}
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
initializeLocationManager();
Integer providerIndex = 0;
for (LocationListener listener : mLocationListeners) {
try {
mLocationManager.requestLocationUpdates(
providers.get(providerIndex),
LOCATION_INTERVAL,
LOCATION_DISTANCE,
listener
);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
providerIndex++;
}
if (!stopService) {
mStatusChecker = () -> {
try {
if (PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.MANUAL.toString())) {
sendCoordinateToBackend(fakeLoc);
} else {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
getLocalizationFromListeners();
changeBackgroundMode();
}
} finally {
mFusedLocationClient = null;
destroyLocationListeners();
mHandler.postDelayed(mStatusChecker, notify_interval);
}
};
@ -175,6 +149,7 @@ public class BackgroundLocalizationService extends Service {
} else if (shouldAbbreviateTimeInterval) {
notify_interval = notify_interval_inside_building;
}
}
}
@ -210,10 +185,6 @@ public class BackgroundLocalizationService extends Service {
return;
}
List<String> providers1 = mLocationManager.getProviders(true);
Location bestLocation = null;
AtomicReference<Boolean> triggerAnotherLocationListener = new AtomicReference<>(false);
mFusedLocationClient.getLastLocation().addOnSuccessListener(
location -> {
if (location != null) {
@ -222,24 +193,8 @@ public class BackgroundLocalizationService extends Service {
sendCoordinateToBackend(location);
}
triggerAnotherLocationListener.set(true);
});
if (triggerAnotherLocationListener.get()) {
for (String provider : providers1) {
Location location = mLocationManager.getLastKnownLocation(provider);
if (location == null) {
continue;
}
if (bestLocation == null || location.getAccuracy() < bestLocation.getAccuracy()) {
bestLocation = location;
}
}
coordinatesHistory.add(bestLocation);
}
}
private void sendCoordinateToBackend(Location location) {
@ -252,58 +207,14 @@ public class BackgroundLocalizationService extends Service {
super.onDestroy();
mHandler.removeCallbacks(mStatusChecker);
if (mLocationManager != null) {
for (LocationListener listener : mLocationListeners) {
try {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLocationManager.removeUpdates(listener);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listener, ignore", ex);
}
}
}
destroyLocationListeners();
}
private void initializeLocationManager() {
Log.e(TAG, "initializeLocationManager - LOCATION_INTERVAL: " + LOCATION_INTERVAL + " LOCATION_DISTANCE: " + LOCATION_DISTANCE);
private void destroyLocationListeners() {
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
private class LocationListener implements android.location.LocationListener {
LocationListener(String provider) {
Log.e(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}
@Override
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged: " + location);
mLastLocation.set(location);
}
@Override
public void onProviderDisabled(String provider) {
Log.e(TAG, "onProviderDisabled: " + provider);
}
@Override
public void onProviderEnabled(String provider) {
Log.e(TAG, "onProviderEnabled: " + provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.e(TAG, "onStatusChanged: " + provider);
}
}
@SuppressLint("StaticFieldLeak")
private class Task extends AsyncTask {
@ -331,6 +242,10 @@ public class BackgroundLocalizationService extends Service {
String status = (PrefUtils.isStatusEnabled(getApplicationContext())) ? PrefUtils.getUserStatus(getApplicationContext()) : "";
if (locationLevel.equals(SharingLevel.PRESENCE.toString())) {
if (!MapUtils.checkIfCoordinateIsValid(latitude, longitude)) {
return null;
}
latitude = presenceLatitude;
longitude = presenceLongitude;
approximatedBuildingPart = presenceApproximatedName;
@ -371,7 +286,7 @@ public class BackgroundLocalizationService extends Service {
@Override
public void onError(Throwable e) {
Log.e(TAG,"onErr" + valueOf(e));
Log.e(TAG, "onErr" + valueOf(e));
}
}));

View File

@ -3,6 +3,7 @@ package com.uam.wmi.findmytutor.service;
import com.uam.wmi.findmytutor.model.TutorTabViewModel;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Single;
import retrofit2.Response;
@ -17,7 +18,7 @@ public interface TutorTabApi {
* @return Call&lt;Void&gt;
*/
@POST("api/users/scrapTutorTab/{tutorId}")
Observable<Void> apiUsersScrapTutorTabByTutorIdPost(
Completable apiUsersScrapTutorTabByTutorIdPost(
@retrofit2.http.Path("tutorId") String tutorId
);
@ -27,7 +28,7 @@ public interface TutorTabApi {
* @return Call&lt;Void&gt;
*/
@POST("api/users/scrapTutorTab")
Observable<Void> apiUsersScrapTutorTabPost();
Single<Void> apiUsersScrapTutorTabPost();
/**

View File

@ -31,6 +31,12 @@ public interface UserService {
@GET("api/users/tutors")
Single <List<User>> getAllTutors();
@GET("api/users/tutors/online")
Single <List<User>> getAllOnlineTutors();
@GET("api/users/tutors/offline")
Single <List<User>> getAllOfflineTutors();
@POST("api/users")
Completable createUser(@Body User user);

View File

@ -77,6 +77,10 @@ public class MapUtils {
return outsideLatitudeRange.contains(coordinate.getLatitude()) && outsideLongitudeRange.contains(coordinate.getLongitude());
}
public static Boolean checkIfCoordinateIsValid(Double latitude, Double longitude){
return Const.buildingLatitudeRange.contains(latitude) && Const.buildingLongitudeRange.contains(longitude);
}
// Function for marker animation
public static class LatLngEvaluator implements TypeEvaluator<LatLng> {
// Method is used to interpolate the marker animation.

View File

@ -197,4 +197,15 @@ public class PrefUtils {
return getSharedPreferences(context).getString("current_manual_location_name", null);
}
public static void putShowOnlyOnlineUsers(Context context, Boolean flag) {
SharedPreferences.Editor editor = getSharedPreferences(context).edit();
editor.putBoolean("show_only_online_users_in_list", flag);
editor.apply();
}
public static Boolean getShowOnlyOnlineUsers(Context context) {
return getSharedPreferences(context).getBoolean("show_only_online_users_in_list", true);
}
}

View File

@ -7,6 +7,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
@ -16,14 +18,24 @@
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:paddingTop="@dimen/activity_margin">
<LinearLayout android:layout_width="fill_parent"
android:id="@+id/linearLayout1" android:layout_height="wrap_content">
<Button
android:id="@+id/scrapTutorTab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:text="@string/scrap_tutor_tab" />
<ImageButton
android:id="@+id/contentTutorTabInfoImageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_gravity="end"
mapbox:srcCompat="@drawable/outline_info_24"/>
</LinearLayout>
<TextView
android:id="@+id/userName"
android:layout_width="wrap_content"
@ -122,14 +134,19 @@
android:layout_height="100dp"
android:scrollbars="vertical" />
<LinearLayout android:layout_width="fill_parent"
android:id="@+id/linearLayout1" android:layout_height="wrap_content">
<Button
android:id="@+id/addDuty"
android:layout_width="wrap_content"
android:layout_weight="1.0"
android:layout_height="wrap_content"
android:text="@string/addDuty"
android:layout_gravity="end"/>
android:layout_gravity="end"
android:text="@string/addDuty" />
</LinearLayout>
<TextView
android:textSize="16sp"

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Homw Tab"
android:textAppearance="?android:attr/textAppearanceLarge"/>
</RelativeLayout>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<android.support.v4.app.FragmentTabHost
android:id="@+id/tabHost"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="30dp"/>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/tab1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
<LinearLayout
android:id="@+id/tab2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</FrameLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_below="@+id/tabLinear"/>
</android.support.v4.app.FragmentTabHost>
</RelativeLayout>

View File

@ -10,6 +10,7 @@
<include layout="@layout/users_list_main" />
</android.support.design.widget.CoordinatorLayout>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fontFamily="@font/lato_regular"
tools:context=".activity.UsersListFragment">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</android.support.design.widget.CoordinatorLayout>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/showOnlineUsersOnly"
android:checkable="true"
android:title="@string/only_online_users"
app:actionViewClass="android.widget.CheckBox"
app:showAsAction="never" />
</menu>

View File

@ -29,7 +29,7 @@
<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>
Jesteśmy grupą studentów, która chce pomoć w rozwoju naszego wydziału.\nDziękujemy za używanie naszej aplikacji.\nZespół FMT</string>
<string name="app_version">0.1.0</string>
<string name="summary_support">Masz jakieś pytania? Uwagi? Chętnie odpiszemy!</string>
<string name="title_send_feedback">Skontaktuj się z nami</string>
@ -92,7 +92,7 @@
<string name="title_manual_location">Dodaj ręczną lokalizacje</string>
<string name="assembly_a">Skrzydło A</string>
<string name="assembly_c">Skrzydło C</string>
<string name="passage_d">ŁącznikD</string>
<string name="passage_d">Łącznik D</string>
<string name="key_language">key_language</string>
<string name="title_activity_settings2">Ustawienia</string>
@ -118,7 +118,7 @@
<string name="userDepartment">Zakład</string>
<string name="loading">Ładowanie …</string>
<string name="logo_find_my_tutor">Logo find my tutor</string>
<string name="prompt_login">Login (Ldap)</string>
<string name="prompt_login">Login (LDAP WMI)</string>
<string name="action_log_in">Zaloguj!</string>
<string name="error_invalid_login_name">Niepoprawny format loginu.</string>
<string name="user_list_nav">Kadra</string>
@ -132,14 +132,14 @@
<string name="fab_title_bound_area">Bounds OFF</string>
<string name="email_subject_feedback">Find My Tutor - feedback</string>
<string name="email_subject_bug">Find My Tutor - zgłoszenie błędu</string>
<string name="modal_feedback_hint">Proszę opisz swoje spostrzeżnia.</string>
<string name="modal_feedback_hint">Opisz proszę swoje spostrzeżenia.</string>
<string name="modal_feedback_question">Wyślij anonimowo</string>
<string name="location_level_manual">Manualna</string>
<string name="preference_manual_location_button">Wybierz z mapy</string>
<string name="permission_denied_explanation">Odmowa dostępu</string>
<string name="permission_rationale">Uprawnienia powinny zostać przyznane.</string>
<string name="title_feedback_report_notice">Powiedz nam co myślisz!(max 1000 znaków)</string>
<string name="title_bug_report_notice">Powiedz nam co zauważyłeś!(max 1000 znaków)</string>
<string name="title_feedback_report_notice">Powiedz nam co myślisz! (max 1000 znaków)</string>
<string name="title_bug_report_notice">Powiedz nam co zauważyłeś! (max 1000 znaków)</string>
<string name="title_bug_report">ZGŁOŚ BUG</string>
<string name="title_feedback_report">FEEDBACK</string>
<string name="modal_feedback_send">WYŚLIJ</string>
@ -159,7 +159,7 @@
<string name="network_error">Błąd sieci!</string>
<string name="manual_status_error">Błąd podczas pobierania danych.</string>
<string name="error_status_fetch">Błąd podczas pobierania statusów.</string>
<string name="notification_text">Upss. Coś poszło nie tak. Pracujemy nad tym!</string>
<string name="notification_text">Upss. Coś poszło nie tak!</string>
<string name="lack_duty_hours">Brak informacji o dyżurze.</string>
<string name="lack_note">Brak notatki.</string>
<string name="search">Wyszukiwarka</string>
@ -194,16 +194,16 @@
<!--(PL) Sharing Tab info helper-->
<string name="info_icon_sharing_tab_p1">W tej zakładce możesz włączyć/wyłączyć udostępnianie swojej lokalizacji oraz ją skonfigurować.</string>
<string name="info_icon_sharing_tab_p2">Niektóre zmiany mogą nie być widoczne od razu! Odświeżanie informacji zajmuje do 2 minut.</string>
<string name="info_icon_sharing_tab_p2">Niektóre zmiany mogą nie być widoczne od razu! Wyłączenie wysyłania ma skutek natychmiastowy, lecz odświeżanie informacji zajmuje serwerowi do 2 minut.</string>
<string name="info_icon_sharing_tab_p3">Udostępniać możesz na jednym z 4 poziomów:</string>
<string name="info_icon_sharing_tab_p3_level_exact"><b>dokładny </b> - lokalizacja wyświetlana na mapie na podstawie GPS</string>
<string name="info_icon_sharing_tab_p3_level_approximate"><b>przybliżony</b> - przybliżona lokalizacja wyświetlana na podstawie GPS</string>
<string name="info_icon_sharing_tab_p3_level_manual"><b>manualny</b> - udostępnianie z ręcznie wybranego punktu na mapie</string>
<string name="info_icon_sharing_tab_p3_level_presence"><b>tylko obecność</b> - udostępnianie jedynie informacji o pojawieniu się na wydziale (aktywny na liście), bez udostępniania lokalizacji</string>
<string name="info_icon_sharing_tab_p4">Każdy poziom z wyjątkiem manualnie wybranej lokalizacji automatycznie zaczyna udostępniać po wejściu na wydział i przestaje udostępniać po jego opuszczeniu. Wystarczy włączyć udostępnianie, a lokalizacja nie będzie udostępniana tylko przy obecności na wydziale.</string>
<string name="info_icon_sharing_tab_p4">Każdy poziom z wyjątkiem manualnie wybranej lokalizacji automatycznie zaczyna udostępniać po wejściu na wydział i przestaje udostępniać po jego opuszczeniu. Wystarczy włączyć udostępnianie, a lokalizacja będzie udostępniana tylko przy obecności na wydziale.</string>
<string name="info_icon_sharing_tab_p5">Udostępnianie w dowolnym momencie można wyłączyć za pomocą przełącznika.</string>
<string name="info_icon_sharing_tab_p6">Dodatkowo, do Twojej lokalizacji możesz dodać status opisowy (będzie on widoczny dla użytkowników po kliknięciu w marker).</string>
<string name="info_icon_sharing_tab_p7">Zarówno manualne lokalizacje jak i statusy możesz dodać do listy, które potem możesz wybrać w wygodny sposób.</string>
<string name="info_icon_sharing_tab_p7">Zarówno manualne lokalizacje jak i statusy możesz dodać do listy, z której możesz potem je wybrać w wygodny sposób.</string>
<!--(PL) Userlist Tab info helper-->
<string name="info_icon_userlist_tab_p1">W tym panelu znajduje się lista profesorów.</string>
<string name="info_icon_userlist_tab_p2">Ich status symbolizowany jest przez kolorowe kropki:</string>
@ -223,7 +223,7 @@
<string name="pref_acra_disabled" translatable="false">Pozwól na wysyłanie raportów o błędach.</string>
<string name="pref_acra_enabled" translatable="false">Pozwól na wysyłanie raportów o błędach.</string>
<string name="pref_title_acra" translatable="false">Raportowanie błędów.</string>
<string name="acra_toast_text" translatable="false">Błąd aplikacji. Informacje o błędzie zostanie wysłana do twórców.</string>
<string name="acra_toast_text" translatable="false">Błąd aplikacji. Informacje o błędzie zostaną wysłane do twórców.</string>
<string name="hint_duty_day">Dzień</string>
@ -250,6 +250,13 @@
<string name="on">WŁĄCZONA</string>
<string name="off">WYŁĄCZONA</string>
<string name="title_activity_black_list">Czarna lista</string>
<string name="scrap_tutor_tab">Pobierz dane z WMI</string>
<string name="scrap_tutor_msg">Dane zostały zaktualizwane!</string>
<string name="no_online_users">Brak użytkowników online.</string>
<string name="no_offline_users">Brak użytkowników offline.</string>
<string name="only_online_users">Tylko użytkownicy online</string>
</resources>

View File

@ -254,7 +254,7 @@
<string name="pref_disable_acra" translatable="false">App issues reporting</string>
<!--(ENG) Map Activity info helper-->
<string name="map_info_text_p1">On the map there are markers which represents tutors sharing their location right now.</string>
<string name="map_info_text_p1">On the map there are markers which represent tutors sharing their location right now.</string>
<string name="map_info_text_p2">After clicking on a marker, you can check who is sharing it and the descriptive status (if the tutor have set one).</string>
<string name="map_info_text_p3">In the app there are 3 possible types of localization, represented by various colors.</string>
<string name="map_info_text_marker_exact">exact localization (from mobile GPS)</string>
@ -279,7 +279,7 @@
<!--(ENG) Sharing Tab info helper-->
<string name="info_icon_sharing_tab_p1">In this tab you can turn on/off sharing your localization and configure it.</string>
<string name="info_icon_sharing_tab_p2">Some of the changes may not happen immediately! Refreshing information takes up to 2 minutes.</string>
<string name="info_icon_sharing_tab_p2">Some of the changes may not be visible immediately! Turning sharing off is stopping the sharing immediately, but refreshing information by server takes up to 2 minutes.</string>
<string name="info_icon_sharing_tab_p3">You can share your localization on one of the 4 levels:</string>
<string name="info_icon_sharing_tab_p3_level_exact"><b>exact</b> - localization displayed on a map, based on GPS</string>
<string name="info_icon_sharing_tab_p3_level_approximate"><b>approximated</b> - approximated localization based on GPS</string>
@ -288,7 +288,7 @@
<string name="info_icon_sharing_tab_p4">Each level, except from manual, will be automatically turned on when entering, and turn off when leaving the faculty. You only need to make sure that sharing is on, and the localization will be shared only when on the faculty.</string>
<string name="info_icon_sharing_tab_p5">Sharing can be turned off at any time with the switch.</string>
<string name="info_icon_sharing_tab_p6">Additionally, you can add descriptive status to your localization (visible for users after clicking on a marker).</string>
<string name="info_icon_sharing_tab_p7">Both manual localizations and statuses can be added to a list, and then used them in a convenient way. </string>
<string name="info_icon_sharing_tab_p7">Both manual localizations and statuses can be added to a list, and then used in a convenient way. </string>
<!--(ENG) Userlist tab info helper-->
<string name="info_icon_userlist_tab_p1">This panel contains the list of tutors.</string>
@ -412,11 +412,15 @@
<string name="enable_sharing_question">In order to use this function, you have to enable localization sharing. May I do it for you?</string>
<string name="sharing_modal_title">Sharing</string>
<string name="lack_of_status">The user hasn\'t defined a status.</string>
<string name="blacklist">Blacklist</string>
<string name="can_not_be_empty">Field can not be empty</string>
<string name="user_added">User added</string>
<string name="list_is_empty">The list is empty</string>
<string name="activity_title_home">Map</string>
<string name="on">ON</string>
<string name="off">OFF</string>
<string name="scrap_tutor_tab">Scrap!</string>
<string name="no_online_users">Currently, there are no\nonline users.</string>
<string name="no_offline_users">Currently, there are no\noffline users.</string>
<string name="only_online_users">Only online users</string>
</resources>