diff --git a/.idea/misc.xml b/.idea/misc.xml index dc44dda..b0c7b20 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -29,7 +29,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index d968864..dab6905 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,10 +10,11 @@ android { applicationId "com.uam.wmi.findmytutor" minSdkVersion 22 targetSdkVersion 27 - versionCode 40 + versionCode 64 versionName "1.0.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true + resConfigs "en", "pl" } buildTypes { release { @@ -37,10 +38,8 @@ dependencies { implementation "ch.acra:acra-limiter:$acraVersion" - 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:cardview-v7:27.1.1' implementation 'com.android.support:design:27.1.1' implementation 'com.android.support:support-v4:27.1.1' @@ -72,6 +71,10 @@ dependencies { // FloatingBarMenu implementation 'com.getbase:floatingactionbutton:1.10.1' implementation 'org.apache.commons:commons-collections4:4.0' - implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support:design:27.1.1' + + // spinner loaders library + implementation 'com.github.ybq:Android-SpinKit:1.2.0' + // rx binding + implementation 'com.jakewharton.rxbinding:rxbinding:0.3.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d209b5a..9f3de6a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,10 +4,10 @@ package="com.uam.wmi.findmytutor"> + - @@ -24,6 +24,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" + android:configChanges="locale" tools:ignore="AllowBackup,GoogleAppIndexingWarning"> + android:screenOrientation="portrait" + android:windowSoftInputMode="adjustPan" /> + + \ No newline at end of file diff --git a/app/src/main/java/com/uam/wmi/findmytutor/FindMyTutor.java b/app/src/main/java/com/uam/wmi/findmytutor/FindMyTutor.java index 3c2eabf..2df6238 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/FindMyTutor.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/FindMyTutor.java @@ -6,8 +6,9 @@ import android.content.SharedPreferences; import android.content.res.Configuration; import com.uam.wmi.findmytutor.utils.Const; +import com.uam.wmi.findmytutor.utils.MapUtils; +import com.uam.wmi.findmytutor.utils.PrefUtils; -import static org.acra.ReportField.*; import org.acra.ACRA; import org.acra.annotation.AcraLimiter; import org.acra.annotation.AcraNotification; @@ -16,18 +17,32 @@ import org.acra.config.HttpSenderConfigurationBuilder; import org.acra.config.ToastConfigurationBuilder; import org.acra.data.StringFormat; import org.acra.sender.HttpSender; + import java.util.HashMap; import java.util.Map; +import static org.acra.ReportField.ANDROID_VERSION; +import static org.acra.ReportField.BUILD_CONFIG; +import static org.acra.ReportField.CUSTOM_DATA; +import static org.acra.ReportField.LOGCAT; +import static org.acra.ReportField.PHONE_MODEL; +import static org.acra.ReportField.REPORT_ID; +import static org.acra.ReportField.SHARED_PREFERENCES; +import static org.acra.ReportField.STACK_TRACE; +import static org.acra.ReportField.USER_APP_START_DATE; +import static org.acra.ReportField.USER_CRASH_DATE; + @AcraNotification(resText = R.string.notification_text, resTitle = R.string.notification_title, resChannelName = R.string.notification_channel) @AcraLimiter(failedReportLimit = 2) public class FindMyTutor extends Application { + @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); + //super.attachBaseContext(LocaleHelper.onAttach(base)); // ACRA core CoreConfigurationBuilder builder = new CoreConfigurationBuilder(this) @@ -43,16 +58,17 @@ public class FindMyTutor extends Application { ToastConfigurationBuilder.class ).setResText(R.string.acra_toast_text); + SharedPreferences sharedPreferences = base.getSharedPreferences("com.uam.wmi.findmytutor_preferences", Context.MODE_PRIVATE); Map header = new HashMap(); String token = sharedPreferences.getString("API_KEY", "KEY_EMPTY"); - header.put("Authorization","Bearer " + token); + header.put("Authorization", "Bearer " + token); // Api POST builder.getPluginConfigurationBuilder( HttpSenderConfigurationBuilder.class // ).setUri("http://192.168.0.15:3000/api/acra") - ).setUri(Const.BASE_URL +"api/Feedback/autoFeedback") + ).setUri(Const.BASE_URL + "api/Feedback/autoFeedback") .setHttpMethod(HttpSender.Method.POST) .setHttpHeaders(header) .setEnabled(true); diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/AppCompatPreferenceActivity.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/AppCompatPreferenceActivity.java index 847a6c8..10f860a 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/AppCompatPreferenceActivity.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/AppCompatPreferenceActivity.java @@ -1,5 +1,6 @@ package com.uam.wmi.findmytutor.activity; +import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Bundle; @@ -13,6 +14,8 @@ import android.view.MenuInflater; import android.view.View; import android.view.ViewGroup; +import com.uam.wmi.findmytutor.utils.LocaleHelper; + /** * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls * to be used with AppCompat. diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/BaseActivity.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/BaseActivity.java index 4183098..19a6dac 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/BaseActivity.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/BaseActivity.java @@ -4,6 +4,7 @@ import android.Manifest; import android.annotation.SuppressLint; import android.app.Fragment; import android.app.FragmentTransaction; +import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Configuration; @@ -35,6 +36,9 @@ import com.uam.wmi.findmytutor.R; import com.uam.wmi.findmytutor.service.BackgroundLocalizationService; import com.uam.wmi.findmytutor.utils.ActiveFragment; import com.uam.wmi.findmytutor.utils.FeedbackUtils; +import com.uam.wmi.findmytutor.utils.LocaleHelper; +import com.uam.wmi.findmytutor.utils.LocaleUtils; +import com.uam.wmi.findmytutor.utils.MapUtils; import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.RxSearchObservable; @@ -80,11 +84,16 @@ public abstract class BaseActivity private SharingFragment sharingFragment; private Fragment userListFragment; - private ActiveFragment activeFragment = ActiveFragment.NONE; + public ActiveFragment activeFragment = ActiveFragment.NONE; private Fragment activeBottomMenu = null; - private SearchView searchView; + public SearchView searchView; public MenuItem infoMenuItem; + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(LocaleHelper.onAttach(base)); + } + @SuppressLint("CheckResult") @Override protected void onCreate(Bundle savedInstanceState) { @@ -118,17 +127,9 @@ public abstract class BaseActivity if(PrefUtils.isBackgroundLocationServiceRunning(getApplicationContext())) { stopBackgroundLocalizationTask(); } + logout(); - storeBackgroundLocationStatus(getApplication(), false); - PrefUtils.storeIsLoggedIn(getApplicationContext(), false); - Intent i = getBaseContext().getPackageManager() - .getLaunchIntentForPackage(getBaseContext().getPackageName()); - if (i != null) { - i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - } - startActivity(i); - finish(); } else if (itemName.equals(getResources().getString(R.string.navigation_item_feedback))) { feedbackUtils.showNoteDialog("FEEDBACK"); @@ -157,6 +158,21 @@ public abstract class BaseActivity } } + + protected void logout(){ + storeBackgroundLocationStatus(getApplication(), false); + PrefUtils.storeIsLoggedIn(getApplicationContext(), false); + PrefUtils.setBatteryExlusionInfoStatus(getApplicationContext(), true); + + Intent i = getBaseContext().getPackageManager() + .getLaunchIntentForPackage(getBaseContext().getPackageName()); + if (i != null) { + i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + } + startActivity(i); + finish(); + } + protected void checkPermissions() { final List missingPermissions = new ArrayList(); @@ -199,6 +215,8 @@ public abstract class BaseActivity } public void stopBackgroundLocalizationTask() { + PrefUtils.storeEnableSharingLocalization(getApplicationContext(), false); + Intent stopIntent = new Intent(getApplicationContext(), BackgroundLocalizationService.class); stopIntent.putExtra("request_stop", true); @@ -208,11 +226,12 @@ public abstract class BaseActivity public void startBackgroundLocalizationTask() { checkPermissions(); + PrefUtils.storeEnableSharingLocalization(getApplicationContext(), true); Intent startIntent = new Intent(getApplicationContext(), BackgroundLocalizationService.class); startIntent.putExtra("notify_interval", onlineBackgroundLocationInterval); - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(startIntent); } else { startService(startIntent); @@ -408,8 +427,8 @@ public abstract class BaseActivity sharingFragment = SharingFragment.newInstance(); FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.activity_content, sharingFragment); + //ft.addToBackStack(null); ft.commit(); - } private void loadUserListFragment() { @@ -418,6 +437,7 @@ public abstract class BaseActivity userListFragment = UsersListFragment.newInstance(); FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.activity_content, userListFragment); + //ft.addToBackStack(null); ft.commit(); } @@ -434,4 +454,8 @@ public abstract class BaseActivity abstract int getNavigationMenuItemId(); abstract int getContentViewId(); + + + + } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/BlackList.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/BlackList.java index ce91562..5e833d7 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/BlackList.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/BlackList.java @@ -1,6 +1,7 @@ package com.uam.wmi.findmytutor.activity; import android.annotation.SuppressLint; +import android.content.Context; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.support.design.widget.CoordinatorLayout; @@ -31,6 +32,7 @@ import android.widget.TextView; import android.widget.Toast; import android.widget.ToggleButton; +import com.github.ybq.android.spinkit.SpinKitView; import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; import com.mapbox.geojson.Point; import com.mapbox.mapboxsdk.geometry.LatLng; @@ -44,6 +46,7 @@ import com.uam.wmi.findmytutor.model.UserResponseModel; import com.uam.wmi.findmytutor.network.ApiClient; import com.uam.wmi.findmytutor.service.PredefinedStatusesService; import com.uam.wmi.findmytutor.service.UserService; +import com.uam.wmi.findmytutor.utils.LocaleHelper; import com.uam.wmi.findmytutor.utils.MyDividerItemDecoration; import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.RecyclerTouchListener; @@ -65,6 +68,7 @@ import io.reactivex.Observable; import io.reactivex.ObservableSource; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; import io.reactivex.functions.Function; import io.reactivex.observers.DisposableObserver; import io.reactivex.observers.DisposableSingleObserver; @@ -86,12 +90,20 @@ public class BlackList extends AppCompatActivity { Switch aSwitch; @BindView(R.id.add_to_black_list_fab) FloatingActionButton addToBlackListFab; + @BindView(R.id.loader) + SpinKitView loader; + private Integer prevSize; private BlackListAdapter mAdapter; private List blacklistedUsers = new ArrayList<>(); private Collator plCollator = Collator.getInstance(Locale.forLanguageTag("pl-PL")); + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(LocaleHelper.onAttach(base)); + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -104,11 +116,11 @@ public class BlackList extends AppCompatActivity { .create(UserService.class); if (PrefUtils.isBlackListing(this)){ - aSwitch.setText(getString(R.string.action_black_list) +" ON"); + aSwitch.setText(getString(R.string.action_black_list) + " " +getString(R.string.on)); aSwitch.setChecked(true); handleChangeRequest(true); }else{ - aSwitch.setText(getString(R.string.action_black_list) +" OFF"); + aSwitch.setText(getString(R.string.action_black_list) + " " +getString(R.string.off) ); aSwitch.setChecked(false); handleChangeRequest(false); } @@ -122,6 +134,7 @@ public class BlackList extends AppCompatActivity { recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16)); recyclerView.setAdapter(mAdapter); + noNotesView.setVisibility(View.GONE); fetchBlackListedUsers(); /** @@ -141,7 +154,6 @@ public class BlackList extends AppCompatActivity { })); addToBlackListFab.setOnClickListener(this::showFabDialog); - handleSwitch(); } @@ -161,32 +173,29 @@ public class BlackList extends AppCompatActivity { } private void fetchBlackListedUsers() { - prevSize = blacklistedUsers.size(); - - blacklistedUsers.clear(); - disposable.add(getListOfBlacklistedUsers(tutorId) + .doOnSubscribe(this::handleDoOnSubscribe) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .flatMap((Function, Observable>) Observable::fromIterable) - .flatMap((Function>) this::getUserObservable) - .subscribeWith(new DisposableObserver() { - @Override - public void onNext(User user) { - blacklistedUsers.add(user); - } + .flatMap(Observable::fromIterable) + .flatMap(this::getUserObservable) + .subscribe(user -> blacklistedUsers.add(user), this::handleError,this::handleComplete)); + } - @Override - public void onError(Throwable e) { - showError(e); - } + private void handleDoOnSubscribe(Disposable disposable) { + prevSize = blacklistedUsers.size(); + blacklistedUsers.clear(); + didFetched = false; + } - @Override - public void onComplete() { - Collections.sort(blacklistedUsers, (a, b) -> sortByUserName(a,b)); - refreshUI(); - } - })); + private void handleComplete() { + Collections.sort(blacklistedUsers, this::sortByUserName); + didFetched = true; + refreshUI(); + } + private void handleError(Throwable e){ + showError(e); + didFetched = false; } private void refreshUI(){ @@ -248,10 +257,8 @@ public class BlackList extends AppCompatActivity { ); } - private void handleAddUser(User user) { Toast.makeText(this, R.string.add_user_to_list, Snackbar.LENGTH_LONG).show(); - blacklistedUsers.clear(); fetchBlackListedUsers(); } @@ -273,15 +280,15 @@ public class BlackList extends AppCompatActivity { } private void toggleEmptyNotes() { - if (didFetched && blacklistedUsers.size() == 0) { - noNotesView.setText(R.string.list_is_empty); noNotesView.setVisibility(View.VISIBLE); + noNotesView.setText(R.string.list_is_empty); + loader.setVisibility(View.GONE); }else if (blacklistedUsers.size() > 0) { noNotesView.setVisibility(View.GONE); + loader.setVisibility(View.GONE); } else { - noNotesView.setText(getString(R.string.loading)); - noNotesView.setVisibility(View.VISIBLE); + loader.setVisibility(View.VISIBLE); } } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/LoginActivity.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/LoginActivity.java index fda30bf..d49dc60 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/LoginActivity.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/LoginActivity.java @@ -27,6 +27,7 @@ import com.uam.wmi.findmytutor.model.ValidateUser; import com.uam.wmi.findmytutor.network.ApiClient; import com.uam.wmi.findmytutor.service.LdapService; import com.uam.wmi.findmytutor.service.UserService; +import com.uam.wmi.findmytutor.utils.MapUtils; import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.RestApiHelper; @@ -149,9 +150,9 @@ public class LoginActivity extends AppCompatActivity { private void loginProcess(String email, String password) { ValidateUser user = new ValidateUser(email, password); - // LdapUser fakeUser = new LdapUser(email, password,"wmi","tutor",email,"Fałszywy",email); + // LdapUser fakeUser = new LdapUser(email, password,"wmi","tutor",email,"Fałszywy",email); disposable.add(ldapService.validate(user) - //disposable.add(ldapService.fakeValidate(fakeUser) + //disposable.add(ldapService.fakeValidate(fakeUser) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::handleResponse, this::handleError)); @@ -190,6 +191,7 @@ public class LoginActivity extends AppCompatActivity { getUserProfile(userId.asString()); + Intent data = new Intent(); String txt = "Main Activity"; data.setData(Uri.parse(txt)); diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/MapActivity.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/MapActivity.java index 2822ed9..b321ad0 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/MapActivity.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/MapActivity.java @@ -4,9 +4,11 @@ import android.Manifest; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; +import android.content.Context; import android.location.Location; import android.os.Bundle; import android.os.Handler; +import android.os.PowerManager; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; import android.text.TextUtils; @@ -45,12 +47,11 @@ 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.PredefinedCoordinatesService; -import com.uam.wmi.findmytutor.service.PredefinedStatusesService; import com.uam.wmi.findmytutor.service.UserService; import com.uam.wmi.findmytutor.utils.ApproximatedLocalization; - import com.uam.wmi.findmytutor.utils.EnableSharingDialog; - +import com.uam.wmi.findmytutor.utils.LocaleHelper; +import com.uam.wmi.findmytutor.utils.LocaleUtils; import com.uam.wmi.findmytutor.utils.ManualLocationUtils; import com.uam.wmi.findmytutor.utils.MapMarker; import com.uam.wmi.findmytutor.utils.MapUtils; @@ -76,12 +77,12 @@ import static com.uam.wmi.findmytutor.utils.Const.mapRefreshInterval; public class MapActivity extends BaseActivity implements PermissionsListener, OnMapReadyCallback { + private HashMap markerUserHash = new HashMap<>(); private String tag = getClass().getName(); private PermissionsManager permissionsManager; private LocationComponent locationComponent; private CoordinateService coordinateService; private UserService userService; - private CompositeDisposable disposable = new CompositeDisposable(); private int mInterval = mapRefreshInterval; private Handler mHandler = new Handler(); @@ -92,9 +93,8 @@ public class MapActivity extends BaseActivity private Button removeLocationButton; private Marker tmpLocalMarker; private Coordinate droppedMarkercoordinate; - private HashMap coordsMap = new HashMap<>(); + public HashMap coordsMap = new HashMap<>(); private HashMap markerHash = new HashMap<>(); - public HashMap markerUserHash = new HashMap<>(); private Set previousCoordsIds = new HashSet<>(); private ManualLocationUtils manualLocationUtils; // Camera Animation params @@ -106,6 +106,11 @@ public class MapActivity extends BaseActivity private ApproximatedLocalization approximatedLocalization; private boolean shouldFetchNewCoords = true; + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(LocaleHelper.onAttach(base)); + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -122,6 +127,7 @@ public class MapActivity extends BaseActivity mStatusChecker = () -> { try { if (shouldFetchNewCoords) { + checkIfUsesCanBeTutor(); fetchTopCoords(); } } finally { @@ -130,7 +136,6 @@ public class MapActivity extends BaseActivity }; - selectLocationButton = findViewById(R.id.select_location_button); removeLocationButton = findViewById(R.id.remove_location_button); mapView = findViewById(R.id.mapView); @@ -141,6 +146,7 @@ public class MapActivity extends BaseActivity handleBackgroundTaskLifeCycle(); manualLocationUtils = new ManualLocationUtils(MapActivity.this); approximatedLocalization = new ApproximatedLocalization(MapUtils.loadJsonFromAsset(getApplicationContext(), "building.geojson")); + MapUtils.BatteryOptimizationsExceptionCheck(this); } @Override @@ -204,13 +210,28 @@ public class MapActivity extends BaseActivity userName.setText(String.format("%s %s", user.getFirstName(), user.getLastName())); - if(cordStatus.equals("")){ + if (cordStatus.equals("")) { status.setText(String.format("%s: %s", getResources().getString(R.string.status_switch_title), getString(R.string.lack_of_status))); - }else{ + } else { 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)); + String sharingLevelToRender = sharingLevel; +Log.e("LOCALE",PrefUtils.getLocale(getApplicationContext())); + + if (PrefUtils.getLocale(getApplicationContext()).equals("pl") || + PrefUtils.getLocale(getApplicationContext()).equals("pl-PL") || + PrefUtils.getLocale(getApplicationContext()).equals("[pl-PL]")) { + if (sharingLevel.equals(SharingLevel.MANUAL.toString())) { + sharingLevelToRender = getString(R.string.manual_mode); + } else if (sharingLevel.equals(SharingLevel.EXACT.toString())) { + sharingLevelToRender = getString(R.string.exact_mode); + } else if (sharingLevel.equals(SharingLevel.APPROXIMATED.toString())) { + sharingLevelToRender = getString(R.string.approx_mode); + } + } + + sharingLevelView.setText(String.format("%s: %s", getResources().getString(R.string.settings_location_level), sharingLevelToRender)); final AlertDialog alertDialog = alertDialogBuilderUserInput.create(); alertDialog.show(); @@ -238,6 +259,7 @@ public class MapActivity extends BaseActivity mapboxMap.addOnMapClickListener(e -> { removeLocationButton.setVisibility(View.GONE); selectLocationButton.setVisibility(View.GONE); + restoreMapMarkers(); }); } @@ -332,7 +354,7 @@ public class MapActivity extends BaseActivity Button dismissButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE); dismissButton.setOnClickListener(view1 -> { - PrefUtils.putCurrentManualLocationName(getApplicationContext(), "Inne"); + PrefUtils.putCurrentManualLocationName(getApplicationContext(), getString(R.string.other_location)); PrefUtils.putCurrentManualLocation(getApplicationContext(), "-1"); alertDialog.dismiss(); @@ -383,6 +405,30 @@ public class MapActivity extends BaseActivity PrefUtils.putCurrentManualLocation(getApplicationContext(), resp.getPredefinedCoordinateId()); } + + private void checkIfUsesCanBeTutor(){ + disposable.add( + userService.getSelf(myId) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeWith(new DisposableSingleObserver() { + @Override + public void onSuccess(User user) { + boolean tutorFromBackend = user.getTitle().equals("tutor"); + + if(tutorFromBackend != PrefUtils.getIsTutor(getApplicationContext())){ + logout(); + } + } + + @Override + public void onError(Throwable e) { + showError(e); + } + })); + + } + private void fetchTopCoords() { disposable.add( @@ -595,47 +641,6 @@ public class MapActivity extends BaseActivity } } - @Override - public void onResume() { - super.onResume(); - mapView.onResume(); - shouldFetchNewCoords = true; - } - - @Override - protected void onStart() { - super.onStart(); - mapView.onStart(); - shouldFetchNewCoords = true; - } - - @Override - protected void onStop() { - super.onStop(); - mapView.onStop(); - shouldFetchNewCoords = false; - } - - @Override - public void onPause() { - super.onPause(); - mapView.onPause(); - shouldFetchNewCoords = false; - } - - @Override - public void onLowMemory() { - super.onLowMemory(); - mapView.onLowMemory(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - mapView.onDestroy(); - mHandler.removeCallbacks(mStatusChecker); - disposable.dispose(); - } @Override protected void onSaveInstanceState(Bundle outState) { @@ -678,11 +683,13 @@ public class MapActivity extends BaseActivity @Override public void searchUser(String textToSearch) { getUserFromApi(textToSearch); + + Log.e("LOCALE", LocaleUtils.getCurrentLocale()); } private void getUserFromApi(String userNameToSearch) { disposable.add( - userService.getAllTutors() + userService.getAllOnlineTutors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map(tutors -> Stream.of(tutors).filter(t -> @@ -690,6 +697,7 @@ public class MapActivity extends BaseActivity .subscribeWith(new DisposableSingleObserver>() { @Override public void onSuccess(List users) { + Log.e("USERS", String.valueOf(users)); filterMarkers(users); } @@ -721,19 +729,65 @@ public class MapActivity extends BaseActivity } public void restoreMapMarkers() { + try { + for (Marker marker : mapboxMap.getMarkers()) { + MapMarker markerMap = markerHash.get(markerUserHash.get(marker.getId())); - for (Marker marker : mapboxMap.getMarkers()) { - MapMarker markerMap = markerHash.get(markerUserHash.get(marker.getId())); + markerMap.restoreDefaultIcon(); + mapboxMap.deselectMarker(marker); + } - markerMap.restoreDefaultIcon(); - mapboxMap.deselectMarker(marker); + mapboxMap.getMarkerViewManager().update(); + } catch (Exception e) { + Log.e("MAP", String.valueOf(e)); } - - mapboxMap.getMarkerViewManager().update(); } public void adjustMapToSearch(Integer zoom) { MapUtils.setZoom(mapboxMap, zoom); } + + @Override + public void onResume() { + super.onResume(); + mapView.onResume(); + shouldFetchNewCoords = true; + } + + @Override + protected void onStart() { + super.onStart(); + mapView.onStart(); + shouldFetchNewCoords = true; + } + + @Override + protected void onStop() { + super.onStop(); + mapView.onStop(); + shouldFetchNewCoords = false; + } + + @Override + public void onPause() { + super.onPause(); + mapView.onPause(); + shouldFetchNewCoords = false; + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapView.onLowMemory(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mapView.onDestroy(); + mHandler.removeCallbacks(mStatusChecker); + disposable.dispose(); + } + } \ No newline at end of file diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/SettingsActivity.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/SettingsActivity.java index fa54e0f..f77be00 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/SettingsActivity.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/SettingsActivity.java @@ -1,6 +1,7 @@ package com.uam.wmi.findmytutor.activity; import android.annotation.SuppressLint; +import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; @@ -15,12 +16,15 @@ import android.util.Log; import android.view.MenuItem; import com.uam.wmi.findmytutor.R; +import com.uam.wmi.findmytutor.utils.LocaleHelper; +import com.uam.wmi.findmytutor.utils.LocaleUtils; import com.uam.wmi.findmytutor.utils.PrefUtils; import java.util.Locale; + public class SettingsActivity extends AppCompatPreferenceActivity { private static final String TAG = SettingsActivity.class.getSimpleName(); @@ -33,9 +37,15 @@ public class SettingsActivity extends AppCompatPreferenceActivity { getFragmentManager().beginTransaction().replace(android.R.id.content, new MainPreferenceFragment()).commit(); } + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(LocaleHelper.onAttach(base)); + } + public void setLocale(String localeName) { + Context context = LocaleHelper.setLocale(this, localeName); + Resources res = context.getResources(); Locale myLocale = new Locale(localeName); - Resources res = getResources(); DisplayMetrics dm = res.getDisplayMetrics(); Configuration conf = res.getConfiguration(); conf.locale = myLocale; @@ -62,9 +72,12 @@ public class SettingsActivity extends AppCompatPreferenceActivity { languagesList.setOnPreferenceChangeListener((preference, newValue) -> { if (!newValue.toString().equals("0")){ + LocaleHelper.setLocale(getActivity(), "pl"); ((SettingsActivity)getActivity()).setLocale("pl"); PrefUtils.storeLocale(getActivity(),"pl"); + LocaleHelper.setLocale(getActivity(), "pl"); }else{ + LocaleHelper.setLocale(getActivity(), "en"); ((SettingsActivity)getActivity()).setLocale("en"); PrefUtils.storeLocale(getActivity(),"en"); } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/SharingFragment.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/SharingFragment.java index a6b41f8..fa4ee6b 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/SharingFragment.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/SharingFragment.java @@ -3,16 +3,15 @@ package com.uam.wmi.findmytutor.activity; import android.annotation.SuppressLint; import android.app.AlertDialog; import android.app.FragmentTransaction; +import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; -import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceCategory; import android.preference.PreferenceFragment; import android.preference.SwitchPreference; -import android.support.annotation.NonNull; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -23,19 +22,17 @@ import com.annimon.stream.IntPair; import com.annimon.stream.Stream; import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; import com.uam.wmi.findmytutor.R; -import com.uam.wmi.findmytutor.adapters.TutorsListAdapter; import com.uam.wmi.findmytutor.model.PredefinedCoordViewModel; import com.uam.wmi.findmytutor.network.ApiClient; import com.uam.wmi.findmytutor.service.PredefinedCoordinatesService; import com.uam.wmi.findmytutor.service.PredefinedStatusesService; import com.uam.wmi.findmytutor.utils.EnableSharingDialog; +import com.uam.wmi.findmytutor.utils.LocaleHelper; 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 org.apache.commons.collections4.BidiMap; - import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -47,6 +44,7 @@ import io.reactivex.disposables.CompositeDisposable; import io.reactivex.observers.DisposableSingleObserver; import io.reactivex.schedulers.Schedulers; import okhttp3.ResponseBody; + import static com.mapbox.mapboxsdk.Mapbox.getApplicationContext; @@ -61,9 +59,9 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere protected RightButtonPreference removeManualStatus; protected Preference manualStatus; protected ListPreference statusList; - private HashMap locationMap; - private ArrayList locationUUIDs; protected List predefinedCoordsList = new ArrayList<>(); + private HashMap locationMap; + private ArrayList locationUUIDs; private HashMap locationLevelMapping; private HashMap statusMapping; private PredefinedStatusesService statusesService; @@ -72,9 +70,9 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere private AlertDialog.Builder builder; private String[] statusesArray; private boolean statusSwitchFlag; - private ArrayList predefinedLocationsList; + private ArrayList predefinedLocationsList; - public static SharingFragment newInstance() { + public static SharingFragment newInstance() { return new SharingFragment(); } @@ -86,12 +84,12 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere .subscribeWith(new DisposableSingleObserver>() { @Override public void onSuccess(List strings) { - statusesArray = strings.toArray(new String[strings.size()]); - if(strings.isEmpty()){ - disableStatusPreferences(); - }else{ - enableStatusPreferences(); - } + statusesArray = strings.toArray(new String[strings.size()]); + if (strings.isEmpty()) { + disableStatusPreferences(); + } else { + enableStatusPreferences(); + } // Log.d("STATUSES",Integer.toString(statusesArray.length )); setListPreferenceData(statusList, statusesArray, null); } @@ -114,45 +112,36 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere public void onSuccess(List coords) { String currentCoordId = PrefUtils.getCurrentManualLocation(getApplicationContext()); - locationMap = new HashMap(); - locationUUIDs = new ArrayList(); - for (PredefinedCoordViewModel i : coords) locationMap.put(i.getPredefinedCoordinateId(),i.getName()); - for (PredefinedCoordViewModel i : coords) locationUUIDs.add(i.getPredefinedCoordinateId()); - List predefinedLocationsNames = Stream.of(coords).map(PredefinedCoordViewModel::getName).toList(); - List predefinedLocationsUUIDs = Stream.of(coords).map(PredefinedCoordViewModel::getPredefinedCoordinateId).toList(); + locationMap = new HashMap(); + locationUUIDs = new ArrayList(); + for (PredefinedCoordViewModel i : coords) + locationMap.put(i.getPredefinedCoordinateId(), i.getName()); + for (PredefinedCoordViewModel i : coords) + locationUUIDs.add(i.getPredefinedCoordinateId()); + List predefinedLocationsNames = Stream.of(coords).map(PredefinedCoordViewModel::getName).toList(); + List predefinedLocationsUUIDs = Stream.of(coords).map(PredefinedCoordViewModel::getPredefinedCoordinateId).toList(); predefinedCoordsList.addAll(coords); + if (!PrefUtils.getLocationLevel(getApplicationContext()).equals("manual")) { + preferenceCategory.removePreference(manualLocationList); + preferenceCategory.removePreference(removeManualLocation); + preferenceCategory.removePreference(manualLocationButton); + } else { + if (!predefinedCoordsList.isEmpty()) { + manualLocationList.setEnabled(true); + manualLocationList.setSummary(PrefUtils.getCurrentManualLocationName(getApplicationContext())); + removeManualLocation.setEnabled(true); + locationSharing.setEnabled(true); + } + } String[] stringnames = predefinedLocationsNames.toArray(new String[0]); - predefinedLocationsList = new ArrayList<>(Arrays.asList(stringnames)); - if (!PrefUtils.getLocationLevel(getApplicationContext()).equals("manual")) { - preferenceCategory.removePreference(manualLocationList); - preferenceCategory.removePreference(removeManualLocation); - preferenceCategory.removePreference(manualLocationButton); - }else{ - if(predefinedCoordsList.isEmpty()){ - locationSharing.setEnabled(false); - locationSharing.setChecked(false); - PrefUtils.disableSharing(getApplicationContext()); - ((MapActivity) getActivity()).handleBackgroundTaskLifeCycle(); - removeManualLocation.setEnabled(false); - manualLocationList.setEnabled(false); - manualLocationList.setSummary(""); - }else{ - manualLocationList.setEnabled(true); - manualLocationList.setSummary(PrefUtils.getCurrentManualLocationName(getApplicationContext())); - removeManualLocation.setEnabled(true); - locationSharing.setEnabled(true); - - - } - } + predefinedLocationsList = new ArrayList<>(Arrays.asList(stringnames)); List activesId = Stream.of(coords).indexed() .filter(v -> v.getSecond().getPredefinedCoordinateId().equals(currentCoordId)).map(IntPair::getFirst).toList(); - if( activesId.size() == 0){ + if (activesId.size() == 0) { setListPreferenceData(manualLocationList, stringnames, null); - } - else { + } else { setListPreferenceData(manualLocationList, stringnames, activesId.get(0)); } @@ -162,7 +151,6 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere public void onError(Throwable e) { Toast.makeText(getApplicationContext(), R.string.error_location_fetch, Toast.LENGTH_SHORT).show(); } - })); } @@ -183,11 +171,11 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere removeManualStatus = (RightButtonPreference) findPreference("remove_manual_status"); manualStatus = findPreference("key_manual_status"); statusList = (ListPreference) findPreference("key_status_value"); - statusesService = ApiClient.getClient(getApplicationContext()).create(PredefinedStatusesService.class); - locationService = ApiClient.getClient(getApplicationContext()).create(PredefinedCoordinatesService.class); + statusesService = ApiClient.getClient(getApplicationContext()).create(PredefinedStatusesService.class); + locationService = ApiClient.getClient(getApplicationContext()).create(PredefinedCoordinatesService.class); disposable = new CompositeDisposable(); statusesArray = new String[0]; - predefinedLocationsList = new ArrayList(); + predefinedLocationsList = new ArrayList(); getStatuses(disposable); getLocations(disposable); locationLevelMapping = new HashMap(); @@ -204,6 +192,7 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere statusList.setSummary(PrefUtils.getUserStatus(getApplicationContext())); manualLocationList.setSummary(PrefUtils.getCurrentManualLocationName(getApplicationContext())); + /** Main sharing switch**/ locationSharing.setOnPreferenceChangeListener((buttonView, newValue) -> { PrefUtils.storeEnableSharingLocalization(getApplicationContext(), (Boolean) newValue); @@ -215,25 +204,19 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere locationMode.setOnPreferenceChangeListener((preference, newValue) -> { ((MapActivity) getActivity()).stopBackgroundLocalizationTask(); ((MapActivity) getActivity()).startBackgroundLocalizationTask(); - PrefUtils.storeLocationMode(getApplicationContext(), locationLevelMapping.get(Integer.parseInt((String) newValue))); + if (PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.MANUAL.toString())) { if (!predefinedCoordsList.isEmpty()) { - preferenceCategory.addPreference(manualLocationList); - preferenceCategory.addPreference(removeManualLocation); - }else{ - locationSharing.setEnabled(false); - locationSharing.setChecked(false); - PrefUtils.disableSharing(getApplicationContext()); - ((MapActivity) getActivity()).handleBackgroundTaskLifeCycle(); - + preferenceCategory.addPreference(manualLocationList); + preferenceCategory.addPreference(removeManualLocation); } preferenceCategory.addPreference(manualLocationButton); } else { - locationSharing.setEnabled(true); + locationSharing.setEnabled(true); preferenceCategory.removePreference(manualLocationList); preferenceCategory.removePreference(manualLocationButton); - preferenceCategory.removePreference(removeManualLocation); + preferenceCategory.removePreference(removeManualLocation); } return true; }); @@ -262,9 +245,6 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere return true; }); - - - /** Button 'choose from map' button listener **/ manualLocationButton.setOnPreferenceChangeListener((preference, o) -> { FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); @@ -282,7 +262,16 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere lp.setSummary(entries[Integer.parseInt((String) newValue)]); return true; }); + statusList.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + if (statusesArray.length == 0) { + builder.setTitle("nie ma wody na pustyni"); + } + return true; + } + }); /** Custom status edittext change listener **/ manualStatus.setOnPreferenceChangeListener((preference, newValue) -> { @@ -293,39 +282,40 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere return true; }); - removeManualStatus.setOnPreferenceChangeListener((preference, newValue) -> { - showRemoveDialog(statusList.getEntries(),"status"); - return true; - }); + removeManualStatus.setOnPreferenceChangeListener((preference, newValue) -> { + showRemoveDialog(statusList.getEntries(), "status"); + return true; + }); - removeManualLocation.setOnPreferenceChangeListener(((preference, newValue) -> { - showRemoveDialog(manualLocationList.getEntries(),"location"); - return true; + removeManualLocation.setOnPreferenceChangeListener(((preference, newValue) -> { + showRemoveDialog(manualLocationList.getEntries(), "location"); + return true; - })); + })); } - public void showRemoveDialog(CharSequence[] entries, String service){ - boolean [] checked = new boolean[entries.length]; + + public void showRemoveDialog(CharSequence[] entries, String service) { + boolean[] checked = new boolean[entries.length]; ArrayList tobeDeleted = new ArrayList(); // Log.d("sharingDialog", "no to siup"); - builder.setPositiveButton("DELETE", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - for (int i=0; i< entries.length; i++){ - if(checked[i] == true) { - tobeDeleted.add((String) entries[i]); - } - } - removeEntries(service,tobeDeleted); + builder.setPositiveButton("DELETE", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + for (int i = 0; i < entries.length; i++) { + if (checked[i] == true) { + tobeDeleted.add((String) entries[i]); + } + } + removeEntries(service, tobeDeleted); // Log.d("MANAGE-PREF",tobeDeleted.toString()); - } - }); - builder.setMultiChoiceItems(entries, checked, new DialogInterface.OnMultiChoiceClickListener() { - @Override - public void onClick(DialogInterface dialog, int which, boolean isChecked) { + } + }); + builder.setMultiChoiceItems(entries, checked, new DialogInterface.OnMultiChoiceClickListener() { + @Override + public void onClick(DialogInterface dialog, int which, boolean isChecked) { - } - }); + } + }); builder.create().show(); } @@ -337,34 +327,34 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere return view; } - protected void removeEntries(String service, ArrayList toBeDeleted){ + protected void removeEntries(String service, ArrayList toBeDeleted) { // Log.d("MANAGE-PREF", toBeDeleted.toString()); - if(service.equals("status")){ - for (String uuid:toBeDeleted) { - disposable.add(statusesService.deleteUserPredefinedStatus(PrefUtils.getUserId(getApplicationContext()), uuid) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::handleDeleteStatuses, this::handleError)); - } - }else { - ArrayList uuidsToBeDeleted = new ArrayList(); - for (String name:toBeDeleted) { - for (String uuid:locationUUIDs) { - if(locationMap.get(uuid).equals(name)){ - uuidsToBeDeleted.add(uuid); + if (service.equals("status")) { + for (String uuid : toBeDeleted) { + disposable.add(statusesService.deleteUserPredefinedStatus(PrefUtils.getUserId(getApplicationContext()), uuid) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::handleDeleteStatuses, this::handleError)); + } + } else { + ArrayList uuidsToBeDeleted = new ArrayList(); + for (String name : toBeDeleted) { + for (String uuid : locationUUIDs) { + if (locationMap.get(uuid).equals(name)) { + uuidsToBeDeleted.add(uuid); + } } - } - } - for (String uuid : uuidsToBeDeleted) { + } + for (String uuid : uuidsToBeDeleted) { // predefinedCoordsList.removeIf(x -> x.getPredefinedCoordinateId().equals(uuid)); - predefinedCoordsList.removeAll(Stream.of(predefinedCoordsList).filter(x -> x.getPredefinedCoordinateId().equals(uuid)).toList()); - disposable.add(locationService.deleteUserPredefinedCoord(PrefUtils.getUserId(getApplicationContext()), uuid) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::handleDeleteLocations, this::handleError)); - } - } + predefinedCoordsList.removeAll(Stream.of(predefinedCoordsList).filter(x -> x.getPredefinedCoordinateId().equals(uuid)).toList()); + disposable.add(locationService.deleteUserPredefinedCoord(PrefUtils.getUserId(getApplicationContext()), uuid) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::handleDeleteLocations, this::handleError)); + } + } } protected void setListPreferenceData(ListPreference lp, String[] entries, Integer activeId) { @@ -392,13 +382,13 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere ; private void handleResponse(List resp) { - if(resp.size() == 1){ - enableStatusPreferences(); - if(PrefUtils.isStatusEnabled(getApplicationContext()) == false){ - PrefUtils.enableStatus(getApplicationContext()); - statusSwitch.setChecked(true); - } - } + if (resp.size() == 1) { + enableStatusPreferences(); + if (PrefUtils.isStatusEnabled(getApplicationContext()) == false) { + PrefUtils.enableStatus(getApplicationContext()); + statusSwitch.setChecked(true); + } + } String[] statusesArray = resp.toArray(new String[resp.size()]); setListPreferenceData(statusList, statusesArray, resp.size() - 1); statusList.setValueIndex(resp.size() - 1); @@ -417,79 +407,84 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere "Network error " + error.getMessage(), Toast.LENGTH_SHORT).show(); } } - private void handleDeleteStatuses(List resp){ - if(resp.isEmpty()){ - disableStatusPreferences(); - }else{ - String[] statusesArray = resp.toArray(new String[resp.size()]); - setListPreferenceData(statusList, statusesArray, null); - String currentEntry = PrefUtils.getUserStatus(getApplicationContext()); - if(resp.contains(currentEntry)){ - statusList.setValueIndex(resp.indexOf(currentEntry)); - }else{ - statusList.setValueIndex(0); - statusList.setSummary(resp.get(0)); - } - } - } - private void handleDeleteLocations(List resp){ - getLocations(disposable); - String currentEntry = PrefUtils.getCurrentManualLocation(getApplicationContext()); - if(resp.isEmpty()){ - disableManualLocationPreferences(); - }else{ - if(!Stream.of(resp).filter(x -> x.getName().equals(currentEntry)).toList().isEmpty()) - { - for (PredefinedCoordViewModel location: resp) { - if(location.getName().equals(currentEntry)){ - manualLocationList.setValueIndex(resp.indexOf(location)); - break; - } + private void handleDeleteStatuses(List resp) { + if (resp.isEmpty()) { + disableStatusPreferences(); + } else { + String[] statusesArray = resp.toArray(new String[resp.size()]); + setListPreferenceData(statusList, statusesArray, null); + String currentEntry = PrefUtils.getUserStatus(getApplicationContext()); + if (resp.contains(currentEntry)) { + statusList.setValueIndex(resp.indexOf(currentEntry)); + } else { + statusList.setValueIndex(0); + statusList.setSummary(resp.get(0)); } - }else{ - manualLocationList.setValueIndex(0); - manualLocationList.setSummary(resp.get(0).getName()); - //todo czy na pewno w shared pref sa dobre wartosci - } + } - } - } - private void disableStatusPreferences(){ - removeManualStatus.setEnabled(false); - statusList.setEnabled(false); - statusSwitch.setEnabled(false); - statusList.setSummary(""); - PrefUtils.disableStatus(getApplicationContext()); + } - } - private void enableStatusPreferences(){ - removeManualStatus.setEnabled(true); - statusList.setEnabled(true); - statusSwitch.setEnabled(true); - statusList.setSummary(PrefUtils.getUserStatus(getApplicationContext())); - } - private void disableManualLocationPreferences(){ - removeManualLocation.setEnabled(false); - manualLocationList.setEnabled(false); - manualLocationList.setSummary(""); - locationSharing.setChecked(false); - locationSharing.setEnabled(false); - PrefUtils.disableSharing(getApplicationContext()); - ((MapActivity) getActivity()).handleBackgroundTaskLifeCycle(); - - } - private void enableManualLocationPreferences(){ - removeManualLocation.setEnabled(true); - manualLocationList.setEnabled(true); - - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - locationSharing.setChecked(PrefUtils.isEnableSharingLocalization(getApplicationContext())); + private void handleDeleteLocations(List resp) { + getLocations(disposable); + String currentEntry = PrefUtils.getCurrentManualLocation(getApplicationContext()); + if (resp.isEmpty()) { + disableManualLocationPreferences(); + } else { + if (!Stream.of(resp).filter(x -> x.getName().equals(currentEntry)).toList().isEmpty()) { + for (PredefinedCoordViewModel location : resp) { + if (location.getName().equals(currentEntry)) { + manualLocationList.setValueIndex(resp.indexOf(location)); + break; + } + } + } else { + manualLocationList.setValueIndex(0); + manualLocationList.setSummary(resp.get(0).getName()); + //todo czy na pewno w shared pref sa dobre wartosci + } } + } + + private void disableStatusPreferences() { + removeManualStatus.setEnabled(false); + statusList.setEnabled(false); + statusSwitch.setEnabled(false); + statusList.setSummary(""); + PrefUtils.disableStatus(getApplicationContext()); + + } + + private void enableStatusPreferences() { + removeManualStatus.setEnabled(true); + statusList.setEnabled(true); + statusSwitch.setEnabled(true); + statusList.setSummary(PrefUtils.getUserStatus(getApplicationContext())); + } + + private void disableManualLocationPreferences() { + removeManualLocation.setEnabled(false); + manualLocationList.setEnabled(false); + manualLocationList.setSummary(""); + locationSharing.setChecked(false); + locationSharing.setEnabled(false); + PrefUtils.disableSharing(getApplicationContext()); + ((MapActivity) getActivity()).handleBackgroundTaskLifeCycle(); + + } + + private void enableManualLocationPreferences() { + removeManualLocation.setEnabled(true); + manualLocationList.setEnabled(true); + + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + locationSharing.setChecked(PrefUtils.isEnableSharingLocalization(getApplicationContext())); + + } @Override public void onResume() { @@ -509,4 +504,5 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere super.onDestroy(); disposable.dispose(); } + } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/StartupActivity.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/StartupActivity.java index 9f6e086..855f0cb 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/StartupActivity.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/StartupActivity.java @@ -1,15 +1,29 @@ package com.uam.wmi.findmytutor.activity; import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; +import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.os.PowerManager; +import android.provider.Settings; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentManager; import android.support.v7.app.AppCompatActivity; import android.util.DisplayMetrics; +import android.widget.ScrollView; import android.widget.Toast; +import com.uam.wmi.findmytutor.R; +import com.uam.wmi.findmytutor.utils.LocaleHelper; +import com.uam.wmi.findmytutor.utils.MapUtils; import com.uam.wmi.findmytutor.utils.PrefUtils; import java.util.Locale; @@ -18,6 +32,11 @@ public class StartupActivity extends AppCompatActivity { private static final int AUTHENTICATION_REQUEST_CODE = 666; String currentLang; + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(LocaleHelper.onAttach(base)); + } + @Override protected void onCreate(Bundle savedInstanceState) { @@ -31,10 +50,10 @@ public class StartupActivity extends AppCompatActivity { } else { Intent loginIntent = new Intent(this, LoginActivity.class); startActivityForResult(loginIntent, AUTHENTICATION_REQUEST_CODE); + } super.onCreate(savedInstanceState); - } @Override @@ -47,4 +66,8 @@ public class StartupActivity extends AppCompatActivity { finish(); } + + } + + diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/TimePickerFragment.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/TimePickerFragment.java new file mode 100644 index 0000000..eecf03a --- /dev/null +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/TimePickerFragment.java @@ -0,0 +1,49 @@ +package com.uam.wmi.findmytutor.activity; +import android.annotation.SuppressLint; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.TimePickerDialog; +import android.os.Bundle; +import android.text.format.DateFormat; +import android.widget.TextView; +import android.widget.TimePicker; + +import com.uam.wmi.findmytutor.model.DutyHourViewModel; + +import java.util.Calendar; + +@SuppressLint("ValidFragment") +public class TimePickerFragment extends DialogFragment + implements TimePickerDialog.OnTimeSetListener { + private TextView textView; + private String field; + private DutyHourViewModel duty; + @SuppressLint("ValidFragment") + public TimePickerFragment(TextView view, DutyHourViewModel duty, String field){ + this.textView = view; + this.duty=duty; + this.field=field; + } + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + // Use the current time as the default values for the picker + final Calendar c = Calendar.getInstance(); + int hour = c.get(Calendar.HOUR_OF_DAY); + int minute = c.get(Calendar.MINUTE); + + // Create a new instance of TimePickerDialog and return it + return new TimePickerDialog(getActivity(), this, hour, minute, + DateFormat.is24HourFormat(getActivity())); + } + + public void onTimeSet(TimePicker view, int hourOfDay, int minute) { + String time = String.format("%d:%02d",hourOfDay,minute); + textView.setText(time); + if(field.equals("start")){ + duty.setStart(time); + }else{ + duty.setEnd(time); + } + // Do something with the time chosen by the user + } +} diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/TutorTab.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/TutorTab.java index 575ff5d..7ab81f7 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/TutorTab.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/TutorTab.java @@ -1,14 +1,21 @@ package com.uam.wmi.findmytutor.activity; +import android.content.Context; +import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.support.design.widget.TextInputEditText; -import android.support.design.widget.TextInputLayout; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; import android.util.Log; +import android.view.Gravity; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.PopupWindow; import android.widget.TextView; import android.widget.Toast; @@ -21,23 +28,22 @@ 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.LocaleHelper; import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.RestApiHelper; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import butterknife.ButterKnife; 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 { @@ -67,12 +73,16 @@ public class TutorTab extends AppCompatActivity { setContentView(R.layout.content_tutor_tab); ButterKnife.bind(this); + Toolbar toolbar = findViewById(R.id.toolbar); + toolbar.setTitle(R.string.profile_activity_title); + setSupportActionBar(toolbar); + userName = findViewById(R.id.userName); - userNote = (TextInputEditText) findViewById(R.id.userNote); + userNote = findViewById(R.id.userNote); userRoom = findViewById(R.id.userRoom); userEmail = findViewById(R.id.userEmail); department = findViewById(R.id.userDepartment); - saveButon = findViewById(R.id.saveButon); + saveButon = findViewById(R.id.saveButton); scrapButton = findViewById(R.id.scrapTutorTab); addDutyButton = findViewById(R.id.addDuty); dutyHoursRecycller = findViewById(R.id.dutyHourView); @@ -86,8 +96,6 @@ public class TutorTab extends AppCompatActivity { 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( @@ -112,6 +120,34 @@ public class TutorTab extends AppCompatActivity { scrapButton.setOnClickListener(view -> scrapTutorTab()); } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_profile, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + if (item.getItemId()==R.id.action_profile_info_popup){ + int layoutID = R.layout.info_popup_tutor_tab; + + View popupView = getLayoutInflater().inflate(layoutID,null); + + PopupWindow popupWindow = new PopupWindow(popupView, + LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); + // If the PopupWindow should be focusable + popupWindow.setFocusable(true); + // If you need the PopupWindow to dismiss when when touched outside + popupWindow.setBackgroundDrawable(new ColorDrawable()); + // Get the View's(the one that was clicked in the Fragment) location + View anchorView= getWindow().getDecorView().findViewById(android.R.id.content); + popupWindow.showAtLocation(anchorView,Gravity.TOP|Gravity.END, 0, 0); + } + + return super.onOptionsItemSelected(item); + } + private void getTutorTab(){ disposable.add( tutorTabService.apiUsersTutorTabByTutorIdGet(PrefUtils.getUserId(getApplicationContext())) @@ -123,7 +159,7 @@ public class TutorTab extends AppCompatActivity { dutyHourList = tutorTabViewModel.getDutyHours(); if(dutyHourList != null){ - dutyHoursAdapter = new DutyHoursAdapter(getApplicationContext(),dutyHourList); + dutyHoursAdapter = new DutyHoursAdapter(getApplicationContext(),dutyHourList, getFragmentManager()); dutyHoursRecycller.setAdapter(dutyHoursAdapter); addDutyButton.setOnClickListener(v -> addEmptyDuty(dutyHoursAdapter)); } @@ -144,7 +180,7 @@ public class TutorTab extends AppCompatActivity { if( code == 404){ ifTutorTabExists = false; - dutyHoursAdapter = new DutyHoursAdapter(getApplicationContext(),new ArrayList()); + dutyHoursAdapter = new DutyHoursAdapter(getApplicationContext(),new ArrayList(), getFragmentManager()); dutyHoursRecycller.setAdapter(dutyHoursAdapter); addDutyButton.setOnClickListener(v -> addEmptyDuty(dutyHoursAdapter)); } @@ -161,16 +197,20 @@ public class TutorTab extends AppCompatActivity { private void setUpSaveListener(Button button) { button.setOnClickListener(view -> { - newTab = new TutorTabViewModel(PrefUtils.getUserId(getApplicationContext()), - userRoom.getText().toString(), - userEmail.getText().toString(), - userNote.getText().toString(), - dutyHoursAdapter.getDutyList()); - if(ifTutorTabExists){ - putUserTab(newTab); + if( isEmailValid(userEmail.getText().toString())){ + newTab = new TutorTabViewModel(PrefUtils.getUserId(getApplicationContext()), + userRoom.getText().toString(), + userEmail.getText().toString(), + userNote.getText().toString(), + dutyHoursAdapter.getDutyList()); + if(ifTutorTabExists){ + putUserTab(newTab); + }else{ + postUserTab(newTab); + ifTutorTabExists=true; + } }else{ - postUserTab(newTab); - ifTutorTabExists=true; + userEmail.setError(getString(R.string.error_invalid_email)); } }); } @@ -221,7 +261,6 @@ public class TutorTab extends AppCompatActivity { Toast.makeText(getApplicationContext(), "Network error " + error.getMessage(), Toast.LENGTH_SHORT).show(); - Log.e("WMI SUCC", String.valueOf(error)); } @@ -239,4 +278,26 @@ public class TutorTab extends AppCompatActivity { Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show(); } + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(LocaleHelper.onAttach(base)); + } + + public boolean isEmailValid(String email) + { + String regExpn = + "^(([\\w-]+\\.)+[\\w-]+|([a-zA-Z]{1}|[\\w-]{2,}))@" + +"((([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\\.([0-1]?" + +"[0-9]{1,2}|25[0-5]|2[0-4][0-9])\\." + +"([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\\.([0-1]?" + +"[0-9]{1,2}|25[0-5]|2[0-4][0-9])){1}|" + +"([a-zA-Z]+[\\w-]+\\.)+[a-zA-Z]{2,4})$"; + + CharSequence inputStr = email; + + Pattern pattern = Pattern.compile(regExpn,Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(inputStr); + + return matcher.matches(); + } } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/UsersListFragment.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/UsersListFragment.java index 3c7028a..3788485 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/UsersListFragment.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/UsersListFragment.java @@ -4,6 +4,7 @@ import android.app.Fragment; import android.app.FragmentTransaction; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.os.SystemClock; import android.support.annotation.NonNull; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.Snackbar; @@ -14,6 +15,7 @@ import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; import android.text.Spannable; import android.text.SpannableString; +import android.text.format.DateFormat; import android.text.style.ImageSpan; import android.util.Log; import android.view.Gravity; @@ -24,21 +26,24 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import com.annimon.stream.Stream; +import com.github.ybq.android.spinkit.SpinKitView; import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; import com.uam.wmi.findmytutor.R; import com.uam.wmi.findmytutor.adapters.TutorsListAdapter; +import com.uam.wmi.findmytutor.model.Coordinate; 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.CoordinateService; import com.uam.wmi.findmytutor.service.TutorTabApi; import com.uam.wmi.findmytutor.service.UserService; +import com.uam.wmi.findmytutor.utils.ActiveFragment; import com.uam.wmi.findmytutor.utils.MyDividerItemDecoration; import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.RecyclerTouchListener; @@ -46,14 +51,21 @@ import com.uam.wmi.findmytutor.utils.RestApiHelper; import java.text.Collator; import java.util.ArrayList; +import java.util.Calendar; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Locale; import butterknife.BindView; import butterknife.ButterKnife; +import io.reactivex.Observable; +import io.reactivex.ObservableSource; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Function; +import io.reactivex.observers.DisposableObserver; import io.reactivex.observers.DisposableSingleObserver; import io.reactivex.schedulers.Schedulers; import okhttp3.ResponseBody; @@ -69,13 +81,18 @@ public class UsersListFragment extends Fragment { RecyclerView recyclerView; @BindView(R.id.txt_empty_notes_view) TextView noNotesView; + @BindView(R.id.loader) + SpinKitView loader; private SearchView searchView; private UserService userService; private TutorTabApi tutorTabService; + private CoordinateService coordinateService; private CompositeDisposable disposable = new CompositeDisposable(); private TutorsListAdapter mAdapter; private List tutorsList = new ArrayList<>(); + private HashMap tutorsTimeStamps = new HashMap<>(); + private Collator plCollator = Collator.getInstance(Locale.forLanguageTag("pl-PL")); private Boolean fetchOnlyOnlineUsers = PrefUtils.getShowOnlyOnlineUsers(getApplicationContext()); @@ -87,7 +104,7 @@ public class UsersListFragment extends Fragment { } public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - mAdapter = new TutorsListAdapter(getActivity().getApplicationContext(), tutorsList); + mAdapter = new TutorsListAdapter(getActivity().getApplicationContext(), tutorsList, tutorsTimeStamps); View view = inflater.inflate(R.layout.users_list, container, false); view.setBackgroundColor(getResources().getColor(android.R.color.white)); setHasOptionsMenu(true); @@ -99,9 +116,10 @@ public class UsersListFragment extends Fragment { userService = ApiClient.getClient(getApplicationContext()) .create(UserService.class); - tutorTabService = ApiClient.getClient(getActivity().getApplicationContext()) .create(TutorTabApi.class); + coordinateService = ApiClient.getClient(getApplicationContext()) + .create(CoordinateService.class); RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity()); recyclerView.setLayoutManager(mLayoutManager); @@ -109,8 +127,10 @@ public class UsersListFragment extends Fragment { recyclerView.setVerticalScrollBarEnabled(true); recyclerView.addItemDecoration(new MyDividerItemDecoration(getActivity(), LinearLayoutManager.VERTICAL, 16)); recyclerView.setAdapter(mAdapter); + noNotesView.setVisibility(View.GONE); fetchAllTutors(); + fetchTopCords(); recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity().getApplicationContext(), recyclerView, new RecyclerTouchListener.ClickListener() { @@ -193,6 +213,9 @@ public class UsersListFragment extends Fragment { TextView userRoom = view.findViewById(R.id.userRoom); TextView userEmail = view.findViewById(R.id.userEmail); TextView department = view.findViewById(R.id.userDepartment); + TextView userStatusLabel = view.findViewById(R.id.user_status_label); + LinearLayout userStatusLabelLL = view.findViewById(R.id.user_status_label_linearLayout); + userName.setText(String.format("%s %s", user.getFirstName(), user.getLastName())); @@ -222,15 +245,15 @@ public class UsersListFragment extends Fragment { @Override public void onSuccess(TutorTabViewModel tutorTabViewModel) { final AlertDialog alertDialog; - if (((MapActivity) getActivity()).markerUserHash.containsValue(user.getId())) { + if (((MapActivity) getActivity()).coordsMap.containsKey(user.getId())) { + alertDialogBuilderUserInput.setPositiveButton(R.string.show_on_map, (dialog, id) -> { // User cancelled the dialog + ((MapActivity) getActivity()).activeFragment = ActiveFragment.NONE; FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); fragmentTransaction.hide(usersListFragment); fragmentTransaction.commit(); - List list = new ArrayList(); - list.add(user); - ((MapActivity) getActivity()).filterMarkers(list); + ((MapActivity) getActivity()).searchUser(user.getFirstName()); ((MapActivity) getActivity()).updateNavigationBarState(); }); } @@ -254,6 +277,16 @@ public class UsersListFragment extends Fragment { department.setText(String.format("%s: %s", getString(R.string.userDepartment), user.getDepartment())); userDutyHoursTitle.setText(String.format("%s:", getString(R.string.userDutyHoursHeader))); + Coordinate coordinate = ((MapActivity) getActivity()).coordsMap.get(user.getId()); + if (coordinate != null){ + String label = coordinate.getLabel(); + if (!label.isEmpty()) { + userStatusLabelLL.setVisibility(View.VISIBLE); + userStatusLabel.setText(String.format("%s: %s", getString(R.string.user_status_label),label)); + } + } + + final ArrayAdapter arrayAdapter = new ArrayAdapter<>(getActivity(), R.layout.duty_hours_item, dutyHoursList); @@ -273,27 +306,10 @@ public class UsersListFragment extends Fragment { disposable.add( (fetchOnlyOnlineUsers ? userService.getAllActiveTutors() : - userService.getAllOfflineTutors()) + userService.getAllTutors()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .map(tutors -> { - List tutorsList = new ArrayList<>(tutors); - List onlineTutors = Stream.of(tutorsList).filter(User::isIsOnline).toList(); - List activeNotOnlineTutors = Stream.of(tutorsList) - .filter(t -> t.isIsActive() && !onlineTutors.contains(t)).toList(); - List notActiveTutors = Stream.of(tutorsList) - .filterNot(User::isIsActive).toList(); - - Collections.sort(onlineTutors, this::sortByUserName); - Collections.sort(activeNotOnlineTutors, this::sortByUserName); - Collections.sort(notActiveTutors, this::sortByUserName); - - List sortedUserList = new ArrayList<>(onlineTutors); - sortedUserList.addAll(activeNotOnlineTutors); - sortedUserList.addAll(notActiveTutors); - - return sortedUserList; - }) + .map(this::mapUsersToSortedList) .subscribeWith(new DisposableSingleObserver>() { @Override public void onSuccess(List users) { @@ -301,6 +317,7 @@ public class UsersListFragment extends Fragment { tutorsList.addAll(users); mAdapter.notifyDataSetChanged(); toggleEmptyNotes(); + fetchTopCords(); } @Override @@ -310,6 +327,24 @@ public class UsersListFragment extends Fragment { })); } + private List mapUsersToSortedList(List tutors) { + List tutorsList = new ArrayList<>(tutors); + List onlineTutors = Stream.of(tutorsList).filter(User::isIsOnline).toList(); + List activeNotOnlineTutors = Stream.of(tutorsList) + .filter(t -> t.isIsActive() && !onlineTutors.contains(t)).toList(); + List notActiveTutors = Stream.of(tutorsList) + .filterNot(User::isIsActive).toList(); + + Collections.sort(onlineTutors, this::sortByUserName); + Collections.sort(activeNotOnlineTutors, this::sortByUserName); + Collections.sort(notActiveTutors, this::sortByUserName); + + List sortedUserList = new ArrayList<>(onlineTutors); + sortedUserList.addAll(activeNotOnlineTutors); + sortedUserList.addAll(notActiveTutors); + + return sortedUserList; + } private void searchTutorInBackend(String searchString) { disposable.add( @@ -334,6 +369,7 @@ public class UsersListFragment extends Fragment { public void restoreUsersList() { fetchAllTutors(); + fetchTopCords(); } private int sortByUserName(User t1, User t2) { @@ -378,9 +414,10 @@ public class UsersListFragment extends Fragment { } private void toggleEmptyNotes() { - if (tutorsList.size() > 0) { - noNotesView.setVisibility(View.GONE); - } else { + loader.setVisibility(View.GONE); + noNotesView.setVisibility(View.GONE); + + if (tutorsList.size() == 0) { noNotesView.setVisibility(View.VISIBLE); if (fetchOnlyOnlineUsers) noNotesView.setText(R.string.no_online_users); @@ -390,6 +427,35 @@ public class UsersListFragment extends Fragment { } } + + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } + + private void fetchTopCords(){ + disposable.add( + coordinateService.getTopCoordinates() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::addTimestamps,this::showError)); + } + + private void addTimestamps(List coordinates) { + for (Coordinate crd : + coordinates) { + Long ts = crd.getTimeStamp(); + tutorsTimeStamps.put(crd.getUserId(), getDate(ts)); + } + + mAdapter.notifyDataSetChanged(); + } + + private String getDate(long time) { + Calendar cal = Calendar.getInstance(Locale.ENGLISH); + cal.setTimeInMillis(time); + return DateFormat.format("HH:mm dd/MM", cal).toString(); + } + @Override public void onDestroy() { super.onDestroy(); @@ -412,7 +478,4 @@ public class UsersListFragment extends Fragment { super.onStop(); } - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/WhiteList.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/WhiteList.java index aad7e70..7490af9 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/WhiteList.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/WhiteList.java @@ -1,8 +1,11 @@ package com.uam.wmi.findmytutor.activity; import android.annotation.SuppressLint; +import android.content.Context; import android.graphics.drawable.ColorDrawable; +import android.os.Build; import android.os.Bundle; +import android.support.annotation.RequiresApi; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AlertDialog; @@ -27,6 +30,7 @@ import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; +import com.github.ybq.android.spinkit.SpinKitView; import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; import com.uam.wmi.findmytutor.R; import com.uam.wmi.findmytutor.adapters.WhiteListAdapter; @@ -35,6 +39,7 @@ import com.uam.wmi.findmytutor.model.StudentIdModel; import com.uam.wmi.findmytutor.model.User; import com.uam.wmi.findmytutor.network.ApiClient; import com.uam.wmi.findmytutor.service.UserService; +import com.uam.wmi.findmytutor.utils.LocaleHelper; import com.uam.wmi.findmytutor.utils.MyDividerItemDecoration; import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.RecyclerTouchListener; @@ -44,7 +49,6 @@ import com.uam.wmi.findmytutor.utils.WrapContentLinearLayoutManager; import java.text.Collator; import java.util.ArrayList; import java.util.Collections; - import java.util.List; import java.util.Locale; @@ -54,6 +58,7 @@ import io.reactivex.Observable; import io.reactivex.ObservableSource; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; import io.reactivex.functions.Function; import io.reactivex.observers.DisposableObserver; import io.reactivex.schedulers.Schedulers; @@ -61,11 +66,6 @@ import okhttp3.ResponseBody; public class WhiteList extends AppCompatActivity { - private CompositeDisposable disposable = new CompositeDisposable(); - private UserService userService; - private boolean didFetched = false; - private String tutorId; - @BindView(R.id.recycler_view_whitelist) RecyclerView recyclerView; @BindView(R.id.white_list_empty_text_view) @@ -75,27 +75,42 @@ public class WhiteList extends AppCompatActivity { @BindView(R.id.add_to_white_list_fab) FloatingActionButton addToWhiteListFab; + @BindView(R.id.loader) + SpinKitView loader; + + + private CompositeDisposable disposable = new CompositeDisposable(); + private UserService userService; + private boolean didFetched = false; + private String tutorId; private WhiteListAdapter mAdapter; private Integer prevSize; private List whitelistedUsers = new ArrayList<>(); private Collator plCollator = Collator.getInstance(Locale.forLanguageTag("pl-PL")); + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(LocaleHelper.onAttach(base)); + } + + @RequiresApi(api = Build.VERSION_CODES.M) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); setContentView(R.layout.activity_white_list); ButterKnife.bind(this); + tutorId = PrefUtils.getUserId(getApplicationContext()); userService = ApiClient.getClient(getApplicationContext()) .create(UserService.class); - if (PrefUtils.isWhiteListing(this)){ - aSwitch.setText(getString(R.string.action_white_list) +" ON"); + if (PrefUtils.isWhiteListing(this)) { + aSwitch.setText(getString(R.string.action_white_list) +" "+getString(R.string.on) ); aSwitch.setChecked(true); handleChangeRequest(true); - }else{ - aSwitch.setText(getString(R.string.action_white_list) +" OFF"); + } else { + aSwitch.setText(getString(R.string.action_white_list) +" "+getString(R.string.off) ); aSwitch.setChecked(false); handleChangeRequest(false); } @@ -109,6 +124,7 @@ public class WhiteList extends AppCompatActivity { recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16)); recyclerView.setAdapter(mAdapter); + noNotesView.setVisibility(View.GONE); /** * On long press on RecyclerView item, open alert dialog @@ -132,7 +148,7 @@ public class WhiteList extends AppCompatActivity { } private Observable> getListOfWhitelistedUsers(String userId) { - return userService.getTutorWhitelistedByID(userId) + return userService.getTutorWhitelistedByID(userId) .toObservable() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); @@ -147,34 +163,32 @@ public class WhiteList extends AppCompatActivity { } private void fetchWhiteListedUsers() { - prevSize = whitelistedUsers.size(); - whitelistedUsers.clear(); - disposable.add(getListOfWhitelistedUsers(tutorId) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .flatMap((Function, Observable>) Observable::fromIterable) - .flatMap((Function>) this::getUserObservable) - .subscribeWith(new DisposableObserver() { - @Override - public void onNext(User user) { - whitelistedUsers.add(user); - } - - @Override - public void onError(Throwable e) { - showError(e); - } - - @Override - public void onComplete() { - Collections.sort(whitelistedUsers, (a, b) -> sortByUserName(a,b)); - refreshUI(); - } - })); + .doOnSubscribe(this::handleDoOnSubscribe) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .flatMap(Observable::fromIterable) + .flatMap(this::getUserObservable) + .subscribe(user -> whitelistedUsers.add(user), this::handleError,this::handleComplete)); } - private void refreshUI(){ + private void handleDoOnSubscribe(Disposable disposable) { + prevSize = whitelistedUsers.size(); + whitelistedUsers.clear(); + didFetched = false; + } + + private void handleComplete() { + Collections.sort(whitelistedUsers, this::sortByUserName); + didFetched = true; + refreshUI(); + } + private void handleError(Throwable e){ + showError(e); + didFetched = false; + } + + private void refreshUI() { toggleEmptyNotes(); mAdapter.notifyItemRangeInserted(prevSize, whitelistedUsers.size() - prevSize); mAdapter.notifyDataSetChanged(); @@ -184,7 +198,7 @@ public class WhiteList extends AppCompatActivity { return plCollator.compare(t1.getLastName(), t2.getLastName()); } - private void showFabDialog(View v){ + private void showFabDialog(View v) { LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext()); @SuppressLint("InflateParams") View view = layoutInflaterAndroid.inflate(R.layout.white_list_fab_modal, null); AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(this); @@ -230,7 +244,7 @@ public class WhiteList extends AppCompatActivity { userService.addStudentToWhitelist(tutorId, studentIdModel) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::handleAddUser,this::showError) + .subscribe(this::handleAddUser, this::showError) ); } @@ -251,30 +265,34 @@ public class WhiteList extends AppCompatActivity { } else { message = "Network Error !"; } - Log.e("ERR",message); + Log.e("ERR", message); Toast.makeText(this, message, Snackbar.LENGTH_LONG).show(); } private void toggleEmptyNotes() { + if (didFetched && whitelistedUsers.size() == 0) { + noNotesView.setVisibility(View.VISIBLE); noNotesView.setText(R.string.list_is_empty); - noNotesView.setVisibility(View.VISIBLE); - }else if (whitelistedUsers.size() > 0) { + loader.setVisibility(View.GONE); + } else if (whitelistedUsers.size() > 0) { noNotesView.setVisibility(View.GONE); + loader.setVisibility(View.GONE); } else { - noNotesView.setText(getString(R.string.loading)); - noNotesView.setVisibility(View.VISIBLE); + loader.setVisibility(View.VISIBLE); } } + + @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId()==R.id.action_whitelist_info_popup){ + if (item.getItemId() == R.id.action_whitelist_info_popup) { int layoutID = R.layout.info_popup_whitelist; - View popupView = getLayoutInflater().inflate(layoutID,null); + View popupView = getLayoutInflater().inflate(layoutID, null); PopupWindow popupWindow = new PopupWindow(popupView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); @@ -283,36 +301,36 @@ public class WhiteList extends AppCompatActivity { // If you need the PopupWindow to dismiss when when touched outside popupWindow.setBackgroundDrawable(new ColorDrawable()); // Get the View's(the one that was clicked in the Fragment) location - View anchorView= getWindow().getDecorView().findViewById(android.R.id.content); - popupWindow.showAtLocation(anchorView,Gravity.TOP|Gravity.END, 0, 0); + View anchorView = getWindow().getDecorView().findViewById(android.R.id.content); + popupWindow.showAtLocation(anchorView, Gravity.TOP | Gravity.END, 0, 0); } return super.onOptionsItemSelected(item); } - private void handleSwitch(){ + private void handleSwitch() { aSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { - if (isChecked){ - aSwitch.setText(getString(R.string.action_white_list) + " "+ getString(R.string.on)); + if (isChecked) { + aSwitch.setText(getString(R.string.action_white_list) + " " + getString(R.string.on)); handleChangeRequest(true); PrefUtils.useWhitelist(this, true); - }else { - aSwitch.setText(getString(R.string.action_white_list) + " "+getString(R.string.off)); + } else { + aSwitch.setText(getString(R.string.action_white_list) + " " + getString(R.string.off)); handleChangeRequest(false); PrefUtils.useWhitelist(this, false); } }); } - private void handleChangeRequest(boolean value){ + private void handleChangeRequest(boolean value) { IsUsingListBool isUsingListBool = new IsUsingListBool(); isUsingListBool.setIsUsing(value); disposable.add( userService.setTutorWhitelist(tutorId, isUsingListBool) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(()->{ - },this::showError) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(() -> { + }, this::showError) ); } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/adapters/DutyHoursAdapter.java b/app/src/main/java/com/uam/wmi/findmytutor/adapters/DutyHoursAdapter.java index eaa95f1..c0f23b1 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/adapters/DutyHoursAdapter.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/adapters/DutyHoursAdapter.java @@ -1,6 +1,9 @@ package com.uam.wmi.findmytutor.adapters; +import android.app.DialogFragment; +import android.app.FragmentManager; import android.content.Context; +import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.text.Editable; @@ -14,6 +17,7 @@ import android.widget.TextView; import com.annimon.stream.Collectors; import com.annimon.stream.Stream; import com.uam.wmi.findmytutor.R; +import com.uam.wmi.findmytutor.activity.TimePickerFragment; import com.uam.wmi.findmytutor.model.DutyHourViewModel; import java.util.ArrayList; import java.util.List; @@ -24,10 +28,12 @@ import butterknife.ButterKnife; public class DutyHoursAdapter extends RecyclerView.Adapter { private Context context; private List hours; + private FragmentManager fragmentManager; - public DutyHoursAdapter(Context context, List hours) { + public DutyHoursAdapter(Context context, List hours, FragmentManager fragmentManager) { this.context = context; - this.hours = new ArrayList<>(hours); + this.hours = new ArrayList(hours); + this.fragmentManager = fragmentManager; } @@ -75,7 +81,7 @@ public class DutyHoursAdapter extends RecyclerView.Adapter tutorsList; + private HashMap tutorsTimeStamps; - public TutorsListAdapter(Context context, List tutors) { + public TutorsListAdapter(Context context, List tutors, HashMap tutorsTimeStamps) { this.context = context; this.tutorsList = tutors; + this.tutorsTimeStamps = tutorsTimeStamps; } @NonNull @Override @@ -41,17 +46,32 @@ public class TutorsListAdapter extends RecyclerView.Adapter { + + private Context context; + private List tutorsList; + private HashMap tutorsTimeStamps; + + public TutorsListAdapter(Context context, List tutors, HashMap tutorsTimeStamps) { + this.context = context; + this.tutorsList = tutors; + this.tutorsTimeStamps = tutorsTimeStamps; + } + @NonNull + @Override + public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View itemView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.tutor_list_row, parent, false); + + return new MyViewHolder(itemView); + } + + @Override + public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { + Drawable image = null; + User tutor = tutorsList.get(position); + + holder.firstName.setText(String.format("%s %s", tutor.getFirstName(), tutor.getLastName())); + String ts = tutorsTimeStamps.get(tutor.getId()); + + if (tutor.isIsOnline()) { + image = context.getResources().getDrawable(R.drawable.user_list_online); + holder.lastSeen.setText(R.string.available_now); + holder.lastSeen.setVisibility(View.VISIBLE); + holder.loader.setVisibility(View.GONE); + } else if(tutor.isIsActive()){ + image = context.getResources().getDrawable(R.drawable.user_list_offline); + + if (ts != null){ + holder.lastSeen.setText(R.string.last_sign); + holder.lastSeen.append(String.format(": %s", ts)); + holder.loader.setVisibility(View.GONE); + } + } else { + image = context.getResources().getDrawable(R.drawable.user_list_off); + + if(ts == null){ + holder.lastSeen.setText(R.string.never_logged_in); + }else{ + holder.lastSeen.setText(R.string.last_sign); + holder.lastSeen.append(String.format(": %s", ts)); + } + holder.loader.setVisibility(View.GONE); + } + + image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight()); + holder.isOnline.setCompoundDrawables(image, null, null, null); + } + + @Override + public int getItemCount() { + return tutorsList.size(); + } + + class MyViewHolder extends RecyclerView.ViewHolder { + + @BindView(R.id.firstName) + TextView firstName; + + @BindView(R.id.lastSeen) + TextView lastSeen; + + @BindView(R.id.isOnline) + TextView isOnline; + + @BindView(R.id.loader) + SpinKitView loader; + + MyViewHolder(View view) { + super(view); + ButterKnife.bind(this, view); + } + } +} + -} \ No newline at end of file diff --git a/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundLocalizationService.java b/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundLocalizationService.java index 81fecf3..a374c44 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundLocalizationService.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/service/BackgroundLocalizationService.java @@ -34,9 +34,11 @@ 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.Const; import com.uam.wmi.findmytutor.utils.MapUtils; import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.SharingLevel; +import com.uam.wmi.findmytutor.utils.WifiUtils; import org.apache.commons.collections4.queue.CircularFifoQueue; @@ -122,6 +124,12 @@ public class BackgroundLocalizationService extends Service { mCurrentLocation = locationResult.getLastLocation(); sendCoordinateToBackend(mCurrentLocation); changeBackgroundMode(); + + //Restart service when a user started using presence in GPS mode and wmi is currently available + if (WifiUtils.checkIfUserIsInRangeOfWmiWifi(getApplicationContext()) + && PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.PRESENCE.toString())) { + restartService(); + } } } }; @@ -140,22 +148,60 @@ public class BackgroundLocalizationService extends Service { startForeground(1001, notification); } - if (!stopService && !PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.MANUAL.toString())) { - createFusedLocationClient(); - } else if (!stopService && - PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.MANUAL.toString())) { - mStatusChecker = () -> { - try { - sendCoordinateToBackend(fakeLoc); - } finally { - mHandler.postDelayed(mStatusChecker, notify_interval); - } - }; + if (!stopService) { + if (PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.PRESENCE.toString())) { + if (WifiUtils.checkIfUserIsInRangeOfWmiWifi(getApplicationContext())) { + Location presenceFakeLoc = new Location(""); - AsyncTask.execute(mStatusChecker); + presenceFakeLoc.setLatitude(Const.presenceLatitude); + presenceFakeLoc.setLongitude(Const.presenceLongitude); + presenceFakeLoc.setAltitude(0); + createPresenceLooper(presenceFakeLoc); + } else { + createFusedLocationClient(); + } + } else if (PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.EXACT.toString()) + || PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.APPROXIMATED.toString()) + ) { + createFusedLocationClient(); + } else if (PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.MANUAL.toString())) { + Location manualFakeLoc = new Location(""); + + manualFakeLoc.setLatitude(0); + manualFakeLoc.setLongitude(0); + manualFakeLoc.setAltitude(0); + createLowBatteryLooper(manualFakeLoc); + } } } + private void createLowBatteryLooper(Location fakeLoc) { + mStatusChecker = () -> { + try { + sendCoordinateToBackend(fakeLoc); + } finally { + mHandler.postDelayed(mStatusChecker, notify_interval); + } + }; + AsyncTask.execute(mStatusChecker); + } + + private void createPresenceLooper(Location fakeLoc) { + mStatusChecker = () -> { + try { + if (WifiUtils.checkIfUserIsInRangeOfWmiWifi(getApplicationContext())) { + sendCoordinateToBackend(fakeLoc); + } else { + restartService(); + } + } finally { + mHandler.postDelayed(mStatusChecker, notify_interval); + } + }; + AsyncTask.execute(mStatusChecker); + } + + private void createFusedLocationClient() { Integer saveMode = Long.valueOf(notify_interval).compareTo(Long.valueOf(offlineBackgroundLocationInterval)); @@ -168,7 +214,7 @@ public class BackgroundLocalizationService extends Service { if (saveMode != 0) { mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); } else { - mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); + mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER); } mLocationRequest.setFastestInterval(notify_interval); @@ -186,18 +232,19 @@ public class BackgroundLocalizationService extends Service { private void changeBackgroundMode() { Integer prevInterval = notify_interval; Boolean shouldExtendTimeInterval = Stream.of(coordinatesHistory) - .map(MapUtils::checkIfCoordinateIsValid).takeWhile(s -> !s).toList().size() == coordinatesHistory.size(); + .map(MapUtils::checkIfCoordinateIsValid).takeWhile(s -> !s).toList().size() == coordinatesHistoryLength; Boolean shouldAbbreviateTimeInterval = Stream.of(coordinatesHistory). map(MapUtils::checkIfCoordinateIsValid).filter(x -> x).toList().size() > 0; + if (shouldExtendTimeInterval) { + notify_interval = notify_interval_outside_building; + } + if (shouldAbbreviateTimeInterval) { notify_interval = notify_interval_inside_building; } - if (coordinatesHistory.size() > coordinatesHistoryLength && shouldExtendTimeInterval) { - notify_interval = notify_interval_outside_building; - } Integer changedMode = Long.valueOf(prevInterval).compareTo(Long.valueOf(notify_interval)); if (changedMode != 0) { @@ -293,7 +340,7 @@ public class BackgroundLocalizationService extends Service { latitude = location.getLatitude(); longitude = location.getLongitude(); altitude = location.getAltitude(); - + Log.e(TAG, "TASK" + latitude + " " + longitude); approximatedLocalization = new ApproximatedLocalization(MapUtils.loadJsonFromAsset(getApplicationContext(), "building.geojson")); approximatedBuildingPart = approximatedLocalization.getNameOfBuildingPart(Point.fromLngLat(longitude, latitude)); } @@ -306,6 +353,7 @@ public class BackgroundLocalizationService extends Service { if (locationLevel.equals(SharingLevel.PRESENCE.toString())) { if (!MapUtils.checkIfCoordinateIsValid(latitude, longitude)) { + coordinatesHistory.add(fakeLoc); return null; } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/service/CoordinateService.java b/app/src/main/java/com/uam/wmi/findmytutor/service/CoordinateService.java index d49dded..d4e6d0f 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/service/CoordinateService.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/service/CoordinateService.java @@ -25,7 +25,7 @@ public interface CoordinateService { Single> getCoordinatesByUserId(@Path("userId") String userId); @GET("api/coordinates/userTop/{userId}") - Single> getTopCoordinatesByUserId(@Path("userId") String userId); + Single getTopCoordinateByUserId(@Path("userId") String userId); @GET("api/coordinates/top") Single> getTopCoordinates(); @@ -42,4 +42,6 @@ public interface CoordinateService { @DELETE("api/coordinates/{id}") Completable deleteCoordinatesById(@Path("id") String id); + + } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/service/UserService.java b/app/src/main/java/com/uam/wmi/findmytutor/service/UserService.java index f4092b4..afe0b2c 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/service/UserService.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/service/UserService.java @@ -39,6 +39,9 @@ public interface UserService { @GET("api/users/tutors/active") Single > getAllActiveTutors(); + + + @GET("api/users/tutors/offline") Single > getAllOfflineTutors(); @@ -60,6 +63,9 @@ public interface UserService { @GET("api/users/{id}") Single getUserById(@Path("id") String userID); + @GET("api/users/self/{id}") + Single getSelf(@Path("id") String userID); + @PUT("api/users/{id}") Completable updateUserByID(@Path("id") String userID, @Body User user); diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/Const.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/Const.java index b6c0dab..cf4abe9 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/utils/Const.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/Const.java @@ -17,8 +17,10 @@ public class Const { public final static String presenceApproximatedName = "Unknown"; public final static Range buildingLatitudeRange = Range.create(52.466092, 52.467529); public final static Range buildingLongitudeRange = Range.create(16.926159, 16.927759); - public final static Range outsideLatitudeRange = Range.create(52.463512, 52.468837); - public final static Range outsideLongitudeRange = Range.create(16.922372, 16.936004); + public final static Range outsideLatitudeRange = Range.create(52.4651, 52.468837); + public final static Range outsideLongitudeRange = Range.create(16.9186, 16.936004); public final static List validApproximatedLocations = Arrays.asList("Skrzydło B", "Skrzydło A", "Aule", "Łącznik", "Biblioteka", "Hol", "Unknown"); + public final static String WMI_SSID_NAME = "wmi"; } + diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/LocaleHelper.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/LocaleHelper.java new file mode 100644 index 0000000..1eba814 --- /dev/null +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/LocaleHelper.java @@ -0,0 +1,80 @@ +package com.uam.wmi.findmytutor.utils; + + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.preference.PreferenceManager; + +import java.util.Locale; + +public class LocaleHelper { + + private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language"; + + public static Context onAttach(Context context) { + String lang = getPersistedData(context, Locale.getDefault().getLanguage()); + return setLocale(context, lang); + } + + public static Context onAttach(Context context, String defaultLanguage) { + String lang = getPersistedData(context, defaultLanguage); + return setLocale(context, lang); + } + + public static String getLanguage(Context context) { + return getPersistedData(context, Locale.getDefault().getLanguage()); + } + + public static Context setLocale(Context context, String language) { + persist(context, language); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + return updateResources(context, language); + } + + return updateResourcesLegacy(context, language); + } + + private static String getPersistedData(Context context, String defaultLanguage) { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + return preferences.getString(SELECTED_LANGUAGE, defaultLanguage); + } + + private static void persist(Context context, String language) { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + SharedPreferences.Editor editor = preferences.edit(); + + editor.putString(SELECTED_LANGUAGE, language); + editor.apply(); + } + + @TargetApi(Build.VERSION_CODES.N) + private static Context updateResources(Context context, String language) { + Locale locale = new Locale(language); + Locale.setDefault(locale); + + Configuration configuration = context.getResources().getConfiguration(); + configuration.setLocale(locale); + + return context.createConfigurationContext(configuration); + } + + @SuppressWarnings("deprecation") + private static Context updateResourcesLegacy(Context context, String language) { + Locale locale = new Locale(language); + Locale.setDefault(locale); + + Resources resources = context.getResources(); + + Configuration configuration = resources.getConfiguration(); + configuration.locale = locale; + + resources.updateConfiguration(configuration, resources.getDisplayMetrics()); + + return context; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/LocaleUtils.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/LocaleUtils.java index 7046b83..c33b194 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/utils/LocaleUtils.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/LocaleUtils.java @@ -1,10 +1,32 @@ package com.uam.wmi.findmytutor.utils; +import android.content.Context; +import android.content.res.Configuration; import android.content.res.Resources; +import android.os.Build; import android.support.v4.os.ConfigurationCompat; +import java.util.Locale; + public class LocaleUtils { - public static String getCurrentLocale(){ - return String.valueOf(ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration())); + public static String getCurrentLocale() { + return String.valueOf(ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration())); + } + + private static Context updateResources(Context context, String language) { + Locale locale = new Locale(language); + Locale.setDefault(locale); + + Resources res = context.getResources(); + Configuration config = new Configuration(res.getConfiguration()); + if (Build.VERSION.SDK_INT >= 22) { + config.setLocale(locale); + context = context.createConfigurationContext(config); + } else { + config.locale = locale; + res.updateConfiguration(config, res.getDisplayMetrics()); + } + return context; } } + diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/MapUtils.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/MapUtils.java index cabb845..0ff9d2b 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/utils/MapUtils.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/MapUtils.java @@ -1,8 +1,13 @@ package com.uam.wmi.findmytutor.utils; import android.animation.TypeEvaluator; +import android.app.AlertDialog; import android.content.Context; +import android.content.Intent; import android.location.Location; +import android.net.Uri; +import android.os.Build; +import android.provider.Settings; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; @@ -10,12 +15,15 @@ import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.uam.wmi.findmytutor.R; import java.io.IOException; import java.io.InputStream; -import static com.uam.wmi.findmytutor.utils.Const.outsideLongitudeRange; +import static com.mapbox.mapboxsdk.Mapbox.getApplicationContext; import static com.uam.wmi.findmytutor.utils.Const.outsideLatitudeRange; +import static com.uam.wmi.findmytutor.utils.Const.outsideLongitudeRange; +import static com.uam.wmi.findmytutor.utils.PrefUtils.shouldBatteryExclusionBeShown; public class MapUtils { @@ -41,8 +49,8 @@ public class MapUtils { // Map Bounds Area public static void setZoom(MapboxMap mapboxMap, Integer zoom) { - makeNewCamera(mapboxMap, 52.466799, 16.927002, zoom, 0, 0, 1000); - mapboxMap.setMinZoomPreference(16); // TODO export to map config + makeNewCamera(mapboxMap, 52.466799, 16.927002, zoom, 0, 0, 1000); + mapboxMap.setMinZoomPreference(16); // TODO export to map config } public static void makeNewCamera(MapboxMap mapboxMap, double lat, double lon, int zoomParam, int bearingParam, int tiltParam, int duration) { @@ -73,14 +81,35 @@ public class MapUtils { } } - public static Boolean checkIfCoordinateIsValid(Location coordinate){ - return outsideLatitudeRange.contains(coordinate.getLatitude()) && outsideLongitudeRange.contains(coordinate.getLongitude()); + public static Boolean checkIfCoordinateIsValid(Location coordinate) { + return outsideLatitudeRange.contains(coordinate.getLatitude()) && outsideLongitudeRange.contains(coordinate.getLongitude()); } - public static Boolean checkIfCoordinateIsValid(Double latitude, Double longitude){ + public static Boolean checkIfCoordinateIsValid(Double latitude, Double longitude) { return Const.buildingLatitudeRange.contains(latitude) && Const.buildingLongitudeRange.contains(longitude); } + public static void BatteryOptimizationsExceptionCheck(Context context) { + if (shouldBatteryExclusionBeShown(getApplicationContext())) { + PrefUtils.setBatteryExlusionInfoStatus(getApplicationContext(), false); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.batter_exclusions_title); + builder.setMessage(R.string.batter_exclusions_message) + .setPositiveButton(R.string.ok, (dialog, id) -> { + Intent intent = new Intent(); + intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + Uri uri = Uri.fromParts("package", getApplicationContext().getPackageName(), null); + intent.setData(uri); + context.startActivity(intent); + }) + .setNegativeButton(R.string.cancel, (dialog, id) -> { + + }).show(); + } + } + } + // Function for marker animation public static class LatLngEvaluator implements TypeEvaluator { // Method is used to interpolate the marker animation. diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/PrefUtils.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/PrefUtils.java index 2ae7c57..131227c 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/utils/PrefUtils.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/PrefUtils.java @@ -243,4 +243,13 @@ public class PrefUtils { return getSharedPreferences(context).getBoolean("whitelisting", false); } + public static Boolean shouldBatteryExclusionBeShown(Context context) { + return getSharedPreferences(context).getBoolean("show_battery_exclusion", false); + } + + public static void setBatteryExlusionInfoStatus(Context context, Boolean flag) { + SharedPreferences.Editor editor = getSharedPreferences(context).edit(); + editor.putBoolean("show_battery_exclusion", flag); + editor.apply(); + } } \ No newline at end of file diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/RxSearchObservable.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/RxSearchObservable.java index 5d0d5b4..d7f890a 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/utils/RxSearchObservable.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/RxSearchObservable.java @@ -1,16 +1,13 @@ package com.uam.wmi.findmytutor.utils; - import android.support.v7.widget.SearchView; import io.reactivex.Observable; import io.reactivex.subjects.PublishSubject; - public class RxSearchObservable { private RxSearchObservable() { - // no instance } public static Observable fromView(SearchView searchView) { @@ -30,13 +27,8 @@ public class RxSearchObservable { subject.onNext(text); return false; } - - - - }); - return subject; } } diff --git a/app/src/main/java/com/uam/wmi/findmytutor/utils/WifiUtils.java b/app/src/main/java/com/uam/wmi/findmytutor/utils/WifiUtils.java new file mode 100644 index 0000000..ae02ba6 --- /dev/null +++ b/app/src/main/java/com/uam/wmi/findmytutor/utils/WifiUtils.java @@ -0,0 +1,30 @@ +package com.uam.wmi.findmytutor.utils; + +import android.content.Context; +import android.net.NetworkInfo; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.util.Log; + +import java.util.Objects; + +public class WifiUtils { + + public static String getWifiName(Context context) { + WifiManager manager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); + if (Objects.requireNonNull(manager).isWifiEnabled()) { + WifiInfo wifiInfo = manager.getConnectionInfo(); + if (wifiInfo != null) { + NetworkInfo.DetailedState state = WifiInfo.getDetailedStateOf(wifiInfo.getSupplicantState()); + if (state == NetworkInfo.DetailedState.CONNECTED || state == NetworkInfo.DetailedState.OBTAINING_IPADDR) { + return wifiInfo.getSSID(); + } + } + } + return null; + } + + public static Boolean checkIfUserIsInRangeOfWmiWifi(Context context) { + return Objects.equals(getWifiName(context), Const.WMI_SSID_NAME); + } +} diff --git a/app/src/main/res/drawable/user_modal_title.xml b/app/src/main/res/drawable/user_modal_title.xml new file mode 100644 index 0000000..42e9b61 --- /dev/null +++ b/app/src/main/res/drawable/user_modal_title.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_black_list.xml b/app/src/main/res/layout/activity_black_list.xml index b4c9188..60c0e30 100644 --- a/app/src/main/res/layout/activity_black_list.xml +++ b/app/src/main/res/layout/activity_black_list.xml @@ -40,7 +40,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" - android:text="Block the users" + android:text="@string/block_the_users" android:textSize="15sp"/> @@ -58,6 +58,7 @@ -