merge develop

This commit is contained in:
marcin.jedynski 2019-01-04 08:46:20 +01:00
commit 9e32a909d9
54 changed files with 3003 additions and 296 deletions

View File

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

Binary file not shown.

Binary file not shown.

View File

@ -27,10 +27,10 @@
tools:ignore="AllowBackup,GoogleAppIndexingWarning"> tools:ignore="AllowBackup,GoogleAppIndexingWarning">
<activity <activity
android:name=".activity.StartupActivity" android:name=".activity.StartupActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleInstance" android:launchMode="singleInstance"
android:theme="@style/AppTheme.NoActionBar"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:configChanges="keyboardHidden|orientation|screenSize"> android:theme="@style/AppTheme.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -38,33 +38,43 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:windowSoftInputMode="adjustPan"
android:name=".activity.MapActivity" android:name=".activity.MapActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTop" android:launchMode="singleTop"
android:screenOrientation="portrait" android:screenOrientation="portrait" />
android:configChanges="keyboardHidden|orientation|screenSize"/>
<activity <activity
android:name=".activity.LoginActivity" android:name=".activity.LoginActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:launchMode="singleTask" android:launchMode="singleTask"
android:noHistory="true" android:noHistory="true"
android:screenOrientation="portrait" android:screenOrientation="portrait" />
android:configChanges="keyboardHidden|orientation|screenSize"/>
<activity <activity
android:name=".activity.SettingsActivity" android:name=".activity.SettingsActivity"
android:screenOrientation="portrait" android:configChanges="keyboardHidden|orientation|screenSize"
android:configChanges="keyboardHidden|orientation|screenSize"/> android:screenOrientation="portrait" />
<service <service
android:name=".service.BackgroundLocalizationService" android:name=".service.BackgroundLocalizationService"
android:enabled="true" android:enabled="true"
android:exported="false" android:exported="false"
android:launchMode="singleTop" /> android:launchMode="singleTop" />
<activity <activity
android:name=".activity.TutorTab" android:name=".activity.TutorTab"
android:theme="@style/AppTheme" android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:configChanges="keyboardHidden|orientation|screenSize"/> android:theme="@style/AppTheme" />
<activity
android:name=".activity.WhiteList"
android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait"
android:theme="@style/AppTheme" />
<activity
android:name=".activity.BlackList"
android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait"
android:theme="@style/AppTheme" />
</application> </application>
</manifest> </manifest>

View File

@ -0,0 +1,727 @@
{
"features": [
{
"type": "Feature",
"properties": {
"name": "Pokoje profesorskie"
},
"geometry": {
"coordinates": [
[
[
16.926707,
52.46657
],
[
16.92652,
52.466244
],
[
16.926459,
52.466255
],
[
16.926645,
52.466582
],
[
16.926707,
52.46657
]
]
],
"type": "Polygon"
},
"id": "07f45cd94d45bb5ad0b6b285b0f6fbbb"
},
{
"type": "Feature",
"properties": {
"name": "Skrzydło B"
},
"geometry": {
"coordinates": [
[
[
16.926961,
52.467026
],
[
16.92677,
52.466682
],
[
16.92652,
52.466244
],
[
16.926459,
52.466255
],
[
16.926428,
52.466203
],
[
16.926175,
52.46625
],
[
16.92621,
52.466306
],
[
16.926323,
52.466282
],
[
16.926515,
52.466632
],
[
16.926408,
52.466654
],
[
16.92644,
52.466712
],
[
16.926543,
52.46669
],
[
16.926754,
52.467067
],
[
16.926961,
52.467026
]
]
],
"type": "Polygon"
},
"id": "143facf35f322434cfc5776f70f1db36"
},
{
"type": "Feature",
"properties": {
"name": "Winda"
},
"geometry": {
"coordinates": [
[
[
16.92669,
52.467141
],
[
16.92666,
52.467089
],
[
16.926755,
52.46707
],
[
16.926786,
52.467121
],
[
16.92669,
52.467141
]
]
],
"type": "Polygon"
},
"id": "1a35bfafd619b80ffb8b36f03549e9e3"
},
{
"type": "Feature",
"properties": {
"name": "D2"
},
"geometry": {
"coordinates": [
[
[
16.926876,
52.466659
],
[
16.926984,
52.466635
],
[
16.92694,
52.466557
],
[
16.926831,
52.46658
],
[
16.926876,
52.466659
]
]
],
"type": "Polygon"
},
"id": "3e0a32a0583254e9e7c47fea1f402472"
},
{
"type": "Feature",
"properties": {
"name": "Sale A"
},
"geometry": {
"coordinates": [
[
[
16.92714,
52.466489
],
[
16.926925,
52.466127
],
[
16.927027,
52.466106
],
[
16.927232,
52.466472
],
[
16.92714,
52.466489
]
]
],
"type": "Polygon"
},
"id": "3e56cb54baf90049a3ce2f16577c2cd8"
},
{
"type": "Feature",
"properties": {
"name": "D1"
},
"geometry": {
"coordinates": [
[
[
16.926984,
52.466635
],
[
16.927084,
52.466614
],
[
16.92704,
52.466536
],
[
16.92694,
52.466557
],
[
16.926984,
52.466635
]
]
],
"type": "Polygon"
},
"id": "56c2a7ab4e4d2ac14a46448d523470dc"
},
{
"type": "Feature",
"properties": {
"name": "Hol"
},
"geometry": {
"coordinates": [
[
[
16.927104,
52.467081
],
[
16.927039,
52.467095
],
[
16.9268,
52.467145
],
[
16.926754,
52.467067
],
[
16.926961,
52.467026
],
[
16.927277,
52.46696
],
[
16.927272,
52.466951
],
[
16.927451,
52.466918
],
[
16.927494,
52.467002
],
[
16.927278,
52.467047
],
[
16.927144,
52.467073
],
[
16.927104,
52.467081
]
]
],
"type": "Polygon"
},
"id": "6f1db27a4df5a46f7a6913556b01effe"
},
{
"type": "Feature",
"properties": {
"name": "Pokoje profesorskie"
},
"geometry": {
"coordinates": [
[
[
16.92677,
52.466683
],
[
16.926961,
52.467026
],
[
16.926887,
52.467041
],
[
16.926695,
52.466699
],
[
16.92677,
52.466683
]
]
],
"type": "Polygon"
},
"id": "94f310dcaa6cee75d9e7800bf8d94155"
},
{
"type": "Feature",
"properties": {
"name": "Biblioteka"
},
"geometry": {
"coordinates": [
[
[
16.926801,
52.467144
],
[
16.926971,
52.467424
],
[
16.926956,
52.46743
],
[
16.926944,
52.467436
],
[
16.92693,
52.467441
],
[
16.926903,
52.467452
],
[
16.926861,
52.467464
],
[
16.926778,
52.467476
],
[
16.926731,
52.467485
],
[
16.926567,
52.467194
],
[
16.926801,
52.467144
]
]
],
"type": "Polygon"
},
"id": "aadab5775bdeb4eaf82c940255ddadd7"
},
{
"type": "Feature",
"properties": {
"name": "Sale A"
},
"geometry": {
"coordinates": [
[
[
16.927082,
52.466492
],
[
16.926999,
52.466509
],
[
16.926771,
52.466109
],
[
16.926857,
52.466088
],
[
16.927082,
52.466492
]
]
],
"type": "Polygon"
},
"id": "b39857ed605e5794fa6c9cdee5d7d6cf"
},
{
"type": "Feature",
"properties": {
"name": "Pokoje profesorskie"
},
"geometry": {
"coordinates": [
[
[
16.926754,
52.467066
],
[
16.926814,
52.467054
],
[
16.926605,
52.466676
],
[
16.926542,
52.46669
],
[
16.926564,
52.466728
],
[
16.926754,
52.467066
]
]
],
"type": "Polygon"
},
"id": "b754d867fde3826e72fe8c243399ff26"
},
{
"type": "Feature",
"properties": {
"name": "Sale A"
},
"geometry": {
"coordinates": [
[
[
16.927272,
52.46695
],
[
16.927083,
52.466613
],
[
16.927167,
52.466595
],
[
16.92735,
52.466936
],
[
16.927272,
52.46695
]
]
],
"type": "Polygon"
},
"id": "c3726b2a2b3a589995fd3f17eecd1f53"
},
{
"type": "Feature",
"properties": {
"name": "D3"
},
"geometry": {
"coordinates": [
[
[
16.92677,
52.466682
],
[
16.926876,
52.466659
],
[
16.926832,
52.46658
],
[
16.926725,
52.466604
],
[
16.92677,
52.466682
]
]
],
"type": "Polygon"
},
"id": "c73d9bdbccc15d9907e24b8bb731118a"
},
{
"type": "Feature",
"properties": {
"name": "Pokoje profesorskie"
},
"geometry": {
"coordinates": [
[
[
16.926324,
52.466282
],
[
16.926503,
52.46661
],
[
16.926579,
52.466595
],
[
16.926398,
52.466268
],
[
16.926324,
52.466282
]
]
],
"type": "Polygon"
},
"id": "d54475cedfa0a866e13933c56bf35d76"
},
{
"type": "Feature",
"properties": {
"name": "Sale A"
},
"geometry": {
"coordinates": [
[
[
16.927607,
52.466891
],
[
16.92734,
52.466562
],
[
16.927242,
52.466585
],
[
16.927451,
52.466918
],
[
16.927607,
52.466891
]
]
],
"type": "Polygon"
},
"id": "d97989e446002de50bc8844d2d9cdf5c"
},
{
"type": "Feature",
"properties": {
"name": "Winda"
},
"geometry": {
"coordinates": [
[
[
16.92669,
52.467141
],
[
16.92666,
52.467089
],
[
16.926755,
52.46707
],
[
16.926786,
52.467121
],
[
16.92669,
52.467141
]
]
],
"type": "Polygon"
},
"id": "dfdba4ee1ee0c55193b8dd04f8b00f6c"
},
{
"type": "Feature",
"properties": {
"name": "Skrzydło A"
},
"geometry": {
"coordinates": [
[
[
16.927606,
52.466891
],
[
16.927339,
52.466562
],
[
16.927242,
52.466585
],
[
16.92718,
52.466482
],
[
16.927232,
52.466473
],
[
16.927025,
52.466105
],
[
16.926924,
52.466126
],
[
16.926896,
52.466078
],
[
16.92677,
52.466108
],
[
16.926998,
52.466509
],
[
16.927041,
52.466537
],
[
16.927075,
52.466595
],
[
16.927082,
52.466614
],
[
16.927277,
52.46696
],
[
16.927358,
52.466942
],
[
16.927354,
52.466935
],
[
16.92745,
52.466918
],
[
16.927606,
52.466891
]
]
],
"type": "Polygon"
},
"id": "faaa569e3642a741f70a77071f19f131"
}
],
"type": "FeatureCollection"
}

View File

@ -53,6 +53,7 @@ import io.reactivex.schedulers.Schedulers;
import static com.mapbox.mapboxsdk.Mapbox.getApplicationContext; import static com.mapbox.mapboxsdk.Mapbox.getApplicationContext;
import static com.uam.wmi.findmytutor.utils.Const.defaultMapZoom; import static com.uam.wmi.findmytutor.utils.Const.defaultMapZoom;
import static com.uam.wmi.findmytutor.utils.Const.onlineBackgroundLocationInterval;
import static com.uam.wmi.findmytutor.utils.Const.searchMapZoom; import static com.uam.wmi.findmytutor.utils.Const.searchMapZoom;
import static com.uam.wmi.findmytutor.utils.PrefUtils.storeBackgroundLocationStatus; import static com.uam.wmi.findmytutor.utils.PrefUtils.storeBackgroundLocationStatus;
@ -99,11 +100,11 @@ public abstract class BaseActivity
String itemName = (String) item.getTitle(); String itemName = (String) item.getTitle();
Intent launchIntent; Intent launchIntent;
if (itemName.equals(getResources().getString(R.string.navigation_item_whitelist))) { if (itemName.equals(getResources().getString(R.string.navigation_item_whitelist))) {
/* launchIntent = new Intent(getApplicationContext(), WhitelistActivity.class); launchIntent = new Intent(getApplicationContext(), WhiteList.class);
startActivity(launchIntent);*/ startActivity(launchIntent);
} else if (itemName.equals(getResources().getString(R.string.navigation_item_blacklist))) { } else if (itemName.equals(getResources().getString(R.string.navigation_item_blacklist))) {
/* launchIntent = new Intent(getApplicationContext(), BlacklistActivity.class); launchIntent = new Intent(getApplicationContext(),BlackList.class);
startActivity(launchIntent);*/ startActivity(launchIntent);
} else if (itemName.equals(getResources().getString(R.string.navigation_item_profile))) { } else if (itemName.equals(getResources().getString(R.string.navigation_item_profile))) {
@ -200,7 +201,6 @@ public abstract class BaseActivity
public void stopBackgroundLocalizationTask() { public void stopBackgroundLocalizationTask() {
Intent stopIntent = new Intent(getApplicationContext(), BackgroundLocalizationService.class); Intent stopIntent = new Intent(getApplicationContext(), BackgroundLocalizationService.class);
stopIntent.putExtra("request_stop", true); stopIntent.putExtra("request_stop", true);
Log.e("Localization", "JEstem w stop BG");
stopService(stopIntent); stopService(stopIntent);
@ -210,6 +210,7 @@ public abstract class BaseActivity
checkPermissions(); checkPermissions();
Intent startIntent = new Intent(getApplicationContext(), BackgroundLocalizationService.class); 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); startForegroundService(startIntent);
@ -219,17 +220,12 @@ public abstract class BaseActivity
} }
public void handleBackgroundTaskLifeCycle() { public void handleBackgroundTaskLifeCycle() {
Log.e("Localization", String.valueOf(PrefUtils.isEnableSharingLocalization(getApplicationContext())));
Boolean shouldServiceRun = PrefUtils.isEnableSharingLocalization(getApplicationContext()) && isTutor; Boolean shouldServiceRun = PrefUtils.isEnableSharingLocalization(getApplicationContext()) && isTutor;
Log.e("Localization", String.valueOf(shouldServiceRun));
if (shouldServiceRun) { if (shouldServiceRun) {
startBackgroundLocalizationTask(); startBackgroundLocalizationTask();
Log.e("Localization", "JEstem i odpalam");
} else { } else {
stopBackgroundLocalizationTask(); stopBackgroundLocalizationTask();
Log.e("Localization", "JEstem i nie odpalam");
} }
} }
@ -285,7 +281,6 @@ public abstract class BaseActivity
getMenuInflater().inflate(R.menu.menu_main, menu); getMenuInflater().inflate(R.menu.menu_main, menu);
infoMenuItem = menu.findItem(R.id.action_info); infoMenuItem = menu.findItem(R.id.action_info);
MenuItem myActionMenuItem = menu.findItem(R.id.action_search); MenuItem myActionMenuItem = menu.findItem(R.id.action_search);
searchView = (SearchView) myActionMenuItem.getActionView(); searchView = (SearchView) myActionMenuItem.getActionView();
@ -295,6 +290,10 @@ public abstract class BaseActivity
adjustMapToSearch(defaultMapZoom); adjustMapToSearch(defaultMapZoom);
} }
if (!hasFocus && activeFragment.equals(ActiveFragment.USER_LIST)) {
((UsersListFragment) userListFragment).restoreUsersList();
}
if(hasFocus && activeFragment.equals(ActiveFragment.NONE)){ if(hasFocus && activeFragment.equals(ActiveFragment.NONE)){
adjustMapToSearch(searchMapZoom); adjustMapToSearch(searchMapZoom);
} }
@ -303,6 +302,7 @@ public abstract class BaseActivity
RxSearchObservable.fromView(searchView) RxSearchObservable.fromView(searchView)
.skip(0) .skip(0)
.map(String::toLowerCase) .map(String::toLowerCase)
.filter(t -> !t.isEmpty())
.debounce(250, TimeUnit.MILLISECONDS) .debounce(250, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())

View File

@ -0,0 +1,348 @@
package com.uam.wmi.findmytutor.activity;
import android.annotation.SuppressLint;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.uam.wmi.findmytutor.R;
import com.uam.wmi.findmytutor.adapters.BlackListAdapter;
import com.uam.wmi.findmytutor.model.IsUsingListBool;
import com.uam.wmi.findmytutor.model.PredefinedCoordViewModel;
import com.uam.wmi.findmytutor.model.StudentIdModel;
import com.uam.wmi.findmytutor.model.User;
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.MyDividerItemDecoration;
import com.uam.wmi.findmytutor.utils.PrefUtils;
import com.uam.wmi.findmytutor.utils.RecyclerTouchListener;
import com.uam.wmi.findmytutor.utils.RestApiHelper;
import com.uam.wmi.findmytutor.utils.SharingLevel;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.observers.DisposableSingleObserver;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
public class BlackList extends AppCompatActivity {
private CompositeDisposable disposable = new CompositeDisposable();
private UserService userService;
private boolean didFetched = false;
private String tutorId;
@BindView(R.id.recycler_view_blacklist)
RecyclerView recyclerView;
@BindView(R.id.black_list_empty_text_view)
TextView noNotesView;
@BindView(R.id.switch_blacklist_toggle)
Switch aSwitch;
@BindView(R.id.add_to_black_list_fab)
FloatingActionButton addToBlackListFab;
private BlackListAdapter mAdapter;
private List<User> blacklistedUsers = new ArrayList<>();
private HashSet<String> blacklistedUsersIDs = new HashSet<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
setContentView(R.layout.activity_black_list);
ButterKnife.bind(this);
tutorId = PrefUtils.getUserId(getApplicationContext());
userService = ApiClient.getClient(getApplicationContext())
.create(UserService.class);
if (PrefUtils.isBlackListing(this)){
aSwitch.setText(getString(R.string.action_black_list) +" ON");
aSwitch.setChecked(true);
handleChangeRequest(true);
}else{
aSwitch.setText(getString(R.string.action_black_list) +" OFF");
aSwitch.setChecked(false);
handleChangeRequest(false);
}
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setTitle(getString(R.string.activity_title_blacklist));
setSupportActionBar(toolbar);
mAdapter = new BlackListAdapter(this, blacklistedUsers);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16));
recyclerView.setAdapter(mAdapter);
/**
* On long press on RecyclerView item, open alert dialog
* with options to choose
* Edit and Delete
* */
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(this,
recyclerView, new RecyclerTouchListener.ClickListener() {
@Override
public void onClick(View view, final int position) {
}
@Override
public void onLongClick(View view, int position) {
}
}));
addToBlackListFab.setOnClickListener(this::showFabDialog);
fetchBlackListedUsersIDs(PrefUtils.getUserId(getApplicationContext()));
handleSwitch();
}
private void fetchBlackListedUsersIDs(String userId) {
disposable.add(
userService.getTutorBlacklistedByID(userId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<List<String>>() {
@Override
public void onSuccess(List<String> users) {
blacklistedUsersIDs.addAll(users);
didFetched = true;
fetchBlackListedUsers();
toggleEmptyNotes();
}
@Override
public void onError(Throwable e) {
showError(e);
}
})
);
}
private void fetchBlackListedUsers() {
for (String GUID : blacklistedUsersIDs){
disposable.add(
userService.getUserById(GUID)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<User>() {
@Override
public void onSuccess(User user) {
blacklistedUsers.add(user);
toggleEmptyNotes();
if (blacklistedUsers.size() == blacklistedUsersIDs.size()) {
mAdapter.notifyDataSetChanged();
}
}
@Override
public void onError(Throwable e) {
showError(e);
}
})
);
}
}
private void showFabDialog(View v){
LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext());
@SuppressLint("InflateParams") View view = layoutInflaterAndroid.inflate(R.layout.black_list_fab_modal, null);
AlertDialog.Builder alertDialogBuilderUserInput = new android.support.v7.app.AlertDialog.Builder(this);
alertDialogBuilderUserInput.setView(view).setPositiveButton(getApplicationContext().getString(R.string.modal_location_send), null);
alertDialogBuilderUserInput
.setPositiveButton(R.string.add, null)
.setNegativeButton(R.string.cancel, null);
final AlertDialog alertDialog = alertDialogBuilderUserInput.create();
alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
EditText modalUserInput = view.findViewById(R.id.black_list_modal_input);
alertDialog.setOnShowListener(dialogInterface -> {
Button sendButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
Button dismissButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
dismissButton.setOnClickListener(view1 -> alertDialog.dismiss());
sendButton.setOnClickListener(view1 -> {
String body = modalUserInput.getText().toString();
if (TextUtils.isEmpty(body)) {
Toast.makeText(getApplicationContext(), R.string.can_not_be_empty, Toast.LENGTH_SHORT).show();
modalUserInput.requestFocus();
} else {
sendUserToBlacklist(body);
alertDialog.dismiss();
}
});
});
alertDialog.show();
}
private void sendUserToBlacklist(String body) {
StudentIdModel studentIdModel = new StudentIdModel(body);
disposable.add(
userService.addStudentToBlacklist(PrefUtils.getUserId(getApplicationContext()), studentIdModel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::handleAddUser,this::showError)
);
}
private void handleAddUser(User user) {
blacklistedUsersIDs.clear();
blacklistedUsers.clear();
blacklistedUsersIDs.addAll(user.getBlacklist());
fetchBlackListedUsers();
}
private void showError(Throwable e) {
String message;
if (e instanceof HttpException) {
ResponseBody responseBody = ((HttpException) e).response().errorBody();
message = RestApiHelper.getErrorMessage(responseBody);
if (((HttpException) e).response().code() == 404) {
message = getString(R.string.no_such_a_user);
}
} else {
message = "Network Error !";
}
Toast.makeText(this, message, Snackbar.LENGTH_LONG).show();
}
private void toggleEmptyNotes() {
if (didFetched && blacklistedUsers.size() == 0) {
noNotesView.setText(R.string.list_is_empty);
noNotesView.setVisibility(View.VISIBLE);
}else if (blacklistedUsers.size() > 0) {
noNotesView.setVisibility(View.GONE);
} else {
noNotesView.setText(getString(R.string.loading));
noNotesView.setVisibility(View.VISIBLE);
}
}
@Override
public void onDestroy() {
super.onDestroy();
disposable.dispose();
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onStop() {
super.onStop();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_black_list, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId()==R.id.action_blacklist_info_popup){
int layoutID = R.layout.info_popup_blacklist;
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 handleSwitch(){
aSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked){
aSwitch.setText(getString(R.string.action_black_list) + " "+ getString(R.string.on));
handleChangeRequest(true);
PrefUtils.useBlacklist(this,true);
}else {
aSwitch.setText(getString(R.string.action_black_list) + " "+getString(R.string.off));
handleChangeRequest(false);
PrefUtils.useBlacklist(this,false);
}
});
}
private void handleChangeRequest(boolean value){
IsUsingListBool isUsingListBool = new IsUsingListBool();
isUsingListBool.setIsUsing(value);
disposable.add(
userService.setTutorBlacklist(tutorId, isUsingListBool)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(()->{
},this::showError)
);
}
}

View File

@ -334,7 +334,7 @@ public class MapActivity extends BaseActivity
final AlertDialog alertDialog = alertDialogBuilderUserInput.create(); final AlertDialog alertDialog = alertDialogBuilderUserInput.create();
EditText modalUserInput = view.findViewById(R.id.feedback_input); EditText modalUserInput = view.findViewById(R.id.manual_input);
alertDialog.setOnShowListener(dialogInterface -> { alertDialog.setOnShowListener(dialogInterface -> {
Button sendButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); Button sendButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);

View File

@ -213,6 +213,8 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere
/** Sharing level list **/ /** Sharing level list **/
locationMode.setOnPreferenceChangeListener((preference, newValue) -> { locationMode.setOnPreferenceChangeListener((preference, newValue) -> {
((MapActivity) getActivity()).stopBackgroundLocalizationTask();
((MapActivity) getActivity()).startBackgroundLocalizationTask();
PrefUtils.storeLocationMode(getApplicationContext(), locationLevelMapping.get(Integer.parseInt((String) newValue))); PrefUtils.storeLocationMode(getApplicationContext(), locationLevelMapping.get(Integer.parseInt((String) newValue)));
if (PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.MANUAL.toString())) { if (PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.MANUAL.toString())) {

View File

@ -0,0 +1,19 @@
package com.uam.wmi.findmytutor.activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.uam.wmi.findmytutor.R;
public abstract class SpecialList extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(getContentViewId());
}
abstract int getContentViewId();
}

View File

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

View File

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

View File

@ -9,13 +9,17 @@ import android.support.v7.app.AlertDialog;
import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import com.annimon.stream.Stream; import com.annimon.stream.Stream;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
@ -28,8 +32,8 @@ import com.uam.wmi.findmytutor.model.User;
import com.uam.wmi.findmytutor.network.ApiClient; import com.uam.wmi.findmytutor.network.ApiClient;
import com.uam.wmi.findmytutor.service.TutorTabApi; import com.uam.wmi.findmytutor.service.TutorTabApi;
import com.uam.wmi.findmytutor.service.UserService; import com.uam.wmi.findmytutor.service.UserService;
import com.uam.wmi.findmytutor.utils.InfoHelperUtils;
import com.uam.wmi.findmytutor.utils.MyDividerItemDecoration; import com.uam.wmi.findmytutor.utils.MyDividerItemDecoration;
import com.uam.wmi.findmytutor.utils.PrefUtils;
import com.uam.wmi.findmytutor.utils.RecyclerTouchListener; import com.uam.wmi.findmytutor.utils.RecyclerTouchListener;
import com.uam.wmi.findmytutor.utils.RestApiHelper; import com.uam.wmi.findmytutor.utils.RestApiHelper;
@ -66,6 +70,7 @@ public class UsersListFragment extends Fragment {
private List<User> tutorsList = new ArrayList<>(); private List<User> tutorsList = new ArrayList<>();
private List<User> tutorsFiltered = new ArrayList<>(); private List<User> tutorsFiltered = new ArrayList<>();
private Collator plCollator = Collator.getInstance(Locale.forLanguageTag("pl-PL")); private Collator plCollator = Collator.getInstance(Locale.forLanguageTag("pl-PL"));
private Boolean fetchOnlyOnlineUsers = PrefUtils.getShowOnlyOnlineUsers(getApplicationContext());
public UsersListFragment() { public UsersListFragment() {
} }
@ -78,7 +83,7 @@ public class UsersListFragment extends Fragment {
mAdapter = new TutorsListAdapter(getActivity().getApplicationContext(), tutorsFiltered); mAdapter = new TutorsListAdapter(getActivity().getApplicationContext(), tutorsFiltered);
View view = inflater.inflate(R.layout.users_list, container, false); View view = inflater.inflate(R.layout.users_list, container, false);
view.setBackgroundColor(getResources().getColor(android.R.color.white)); view.setBackgroundColor(getResources().getColor(android.R.color.white));
setHasOptionsMenu(true);
return view; return view;
} }
@ -94,6 +99,7 @@ public class UsersListFragment extends Fragment {
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity()); RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(mLayoutManager); recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setVerticalScrollBarEnabled(true);
recyclerView.addItemDecoration(new MyDividerItemDecoration(getActivity(), LinearLayoutManager.VERTICAL, 16)); recyclerView.addItemDecoration(new MyDividerItemDecoration(getActivity(), LinearLayoutManager.VERTICAL, 16));
recyclerView.setAdapter(mAdapter); recyclerView.setAdapter(mAdapter);
@ -113,12 +119,50 @@ public class UsersListFragment extends Fragment {
} }
public void searchUser(String textToSearch) {
tutorsFiltered.clear();
tutorsFiltered.addAll(Stream.of(tutorsList).filter(t -> @Override
t.toSearchAbleString().toLowerCase().contains(textToSearch.toLowerCase())).toList()); public void onPrepareOptionsMenu(Menu menu) {
mAdapter.notifyDataSetChanged(); super.onPrepareOptionsMenu(menu);
try {
menu.findItem(R.id.showOnlineUsersOnly).setChecked(fetchOnlyOnlineUsers);
}
catch(Exception e) {
Log.e(TAG, "onPrepareOptionsMenu error");
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
//item.setChecked(fetchOnlyOnlineUsers);
switch (item.getItemId()){
case R.id.showOnlineUsersOnly:
if(item.isChecked()) {
fetchOnlyOnlineUsers = false;
item.setChecked(false);
}else{
item.setChecked(true);
fetchOnlyOnlineUsers = true;
}
PrefUtils.putShowOnlyOnlineUsers(getApplicationContext(), fetchOnlyOnlineUsers);
fetchAllTutors();
break;
}
return false;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.users_list_menu, menu);
menu.getItem(0).setChecked(fetchOnlyOnlineUsers);
super.onCreateOptionsMenu(menu,inflater);
}
public void searchUser(String textToSearch) {
searchTutorInBackend(textToSearch);
} }
private void showNoteDialog(final User user) { private void showNoteDialog(final User user) {
@ -185,7 +229,9 @@ public class UsersListFragment extends Fragment {
private void fetchAllTutors() { private void fetchAllTutors() {
disposable.add( disposable.add(
userService.getAllTutors() (fetchOnlyOnlineUsers ?
userService.getAllActiveTutors() :
userService.getAllOfflineTutors())
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.map(tutors -> { .map(tutors -> {
@ -228,22 +274,70 @@ public class UsersListFragment extends Fragment {
} }
private void searchTutorInBackend(String searchString) {
disposable.add(
userService.searchUser(searchString)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<List<User>>() {
@Override
public void onSuccess(List<User> users) {
tutorsFiltered.clear();
tutorsFiltered.addAll(users);
mAdapter.notifyDataSetChanged();
}
@Override
public void onError(Throwable e) {
showSearchError(e);
}
}));
}
public void restoreUsersList(){
fetchAllTutors();
}
private int sortByUserName(User t1, User t2) { private int sortByUserName(User t1, User t2) {
return plCollator.compare(t1.getLastName(), t2.getLastName()); return plCollator.compare(t1.getLastName(), t2.getLastName());
} }
private void showError(Throwable e) { private void showError(Throwable e) {
String message; String message;
Log.e(TAG, String.valueOf(e));
if (e instanceof HttpException) { if (e instanceof HttpException) {
ResponseBody responseBody = ((HttpException) e).response().errorBody(); ResponseBody responseBody = ((HttpException) e).response().errorBody();
message = RestApiHelper.getErrorMessage(responseBody); message = RestApiHelper.getErrorMessage(responseBody);
} else { } else {
message = "Network Error !"; message = getString(R.string.network_err);
} }
Snackbar.make(coordinatorLayout, message, Snackbar.LENGTH_LONG) createSnackbar(message);
.show(); }
private void showSearchError(Throwable e) {
String message;
Log.e(TAG, String.valueOf(e));
if (e instanceof HttpException) {
ResponseBody responseBody = ((HttpException) e).response().errorBody();
message = RestApiHelper.getErrorMessage(responseBody);
} else {
message = getString(R.string.search_null);
}
createSnackbar(message);
}
private void createSnackbar(String msg){
Snackbar snackbar = Snackbar.make(coordinatorLayout, msg, Snackbar.LENGTH_LONG);
View view = snackbar.getView();
CoordinatorLayout.LayoutParams params=(CoordinatorLayout.LayoutParams)view.getLayoutParams();
params.gravity = Gravity.TOP;
view.setLayoutParams(params);
snackbar.show();
} }
private void toggleEmptyNotes() { private void toggleEmptyNotes() {
@ -251,6 +345,11 @@ public class UsersListFragment extends Fragment {
noNotesView.setVisibility(View.GONE); noNotesView.setVisibility(View.GONE);
} else { } else {
noNotesView.setVisibility(View.VISIBLE); noNotesView.setVisibility(View.VISIBLE);
if(fetchOnlyOnlineUsers)
noNotesView.setText(R.string.no_online_users);
else{
noNotesView.setText(R.string.no_offline_users);
}
} }
} }

View File

@ -0,0 +1,335 @@
package com.uam.wmi.findmytutor.activity;
import android.annotation.SuppressLint;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
import com.uam.wmi.findmytutor.R;
import com.uam.wmi.findmytutor.adapters.WhiteListAdapter;
import com.uam.wmi.findmytutor.model.IsUsingListBool;
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.MyDividerItemDecoration;
import com.uam.wmi.findmytutor.utils.PrefUtils;
import com.uam.wmi.findmytutor.utils.RecyclerTouchListener;
import com.uam.wmi.findmytutor.utils.RestApiHelper;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.observers.DisposableSingleObserver;
import io.reactivex.schedulers.Schedulers;
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)
TextView noNotesView;
@BindView(R.id.switch_whitelist_toggle)
Switch aSwitch;
@BindView(R.id.add_to_white_list_fab)
FloatingActionButton addToWhiteListFab;
private WhiteListAdapter mAdapter;
private List<User> whitelistedUsers = new ArrayList<>();
private HashSet<String> whitelistedUsersIDs = new HashSet<>();
@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");
aSwitch.setChecked(true);
handleChangeRequest(true);
}else{
aSwitch.setText(getString(R.string.action_white_list) +" OFF");
aSwitch.setChecked(false);
handleChangeRequest(false);
}
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setTitle(getString(R.string.activity_title_whitelist));
setSupportActionBar(toolbar);
mAdapter = new WhiteListAdapter(this, whitelistedUsers);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16));
recyclerView.setAdapter(mAdapter);
/**
* On long press on RecyclerView item, open alert dialog
* with options to choose
* Edit and Delete
* */
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(this,
recyclerView, new RecyclerTouchListener.ClickListener() {
@Override
public void onClick(View view, final int position) {
}
@Override
public void onLongClick(View view, int position) {
}
}));
addToWhiteListFab.setOnClickListener(this::showFabDialog);
fetchWhiteListedUsersIDs(PrefUtils.getUserId(getApplicationContext()));
handleSwitch();
}
private void fetchWhiteListedUsersIDs(String userId) {
disposable.add(
userService.getTutorWhitelistedByID(userId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<List<String>>() {
@Override
public void onSuccess(List<String> users) {
whitelistedUsersIDs.addAll(users);
didFetched = true;
fetchWhiteListedUsers();
toggleEmptyNotes();
}
@Override
public void onError(Throwable e) {
showError(e);
}
})
);
}
private void fetchWhiteListedUsers() {
for (String GUID : whitelistedUsersIDs){
disposable.add(
userService.getUserById(GUID)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<User>() {
@Override
public void onSuccess(User user) {
whitelistedUsers.add(user);
toggleEmptyNotes();
if (whitelistedUsers.size() == whitelistedUsersIDs.size()) {
mAdapter.notifyDataSetChanged();
}
}
@Override
public void onError(Throwable e) {
showError(e);
}
})
);
}
}
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);
alertDialogBuilderUserInput.setView(view).setPositiveButton(getApplicationContext().getString(R.string.modal_location_send), null);
alertDialogBuilderUserInput
.setPositiveButton(R.string.add, null)
.setNegativeButton(R.string.cancel, null);
final AlertDialog alertDialog = alertDialogBuilderUserInput.create();
alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
EditText modalUserInput = view.findViewById(R.id.white_list_modal_input);
alertDialog.setOnShowListener(dialogInterface -> {
Button sendButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
Button dismissButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
dismissButton.setOnClickListener(view1 -> alertDialog.dismiss());
sendButton.setOnClickListener(view1 -> {
String body = modalUserInput.getText().toString();
if (TextUtils.isEmpty(body)) {
Toast.makeText(getApplicationContext(), R.string.can_not_be_empty, Toast.LENGTH_SHORT).show();
modalUserInput.requestFocus();
} else {
sendUserToWhitelist(body);
alertDialog.dismiss();
}
});
});
alertDialog.show();
}
private void sendUserToWhitelist(String body) {
StudentIdModel studentIdModel = new StudentIdModel(body);
disposable.add(
userService.addStudentToWhitelist(PrefUtils.getUserId(getApplicationContext()), studentIdModel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::handleAddUser,this::showError)
);
}
private void handleAddUser(User user) {
whitelistedUsersIDs.clear();
whitelistedUsers.clear();
whitelistedUsersIDs.addAll(user.getWhitelist());
fetchWhiteListedUsers();
}
private void showError(Throwable e) {
String message;
if (e instanceof HttpException) {
ResponseBody responseBody = ((HttpException) e).response().errorBody();
message = RestApiHelper.getErrorMessage(responseBody);
if (((HttpException) e).response().code() == 404) {
message = getString(R.string.no_such_a_user);
}
} else {
message = "Network Error !";
}
Toast.makeText(this, message, Snackbar.LENGTH_LONG).show();
}
private void toggleEmptyNotes() {
if (didFetched && whitelistedUsers.size() == 0) {
noNotesView.setText(R.string.list_is_empty);
noNotesView.setVisibility(View.VISIBLE);
}else if (whitelistedUsers.size() > 0) {
noNotesView.setVisibility(View.GONE);
} else {
noNotesView.setText(getString(R.string.loading));
noNotesView.setVisibility(View.VISIBLE);
}
}
@Override
public void onDestroy() {
super.onDestroy();
disposable.dispose();
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onStop() {
super.onStop();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_white_list, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId()==R.id.action_whitelist_info_popup){
int layoutID = R.layout.info_popup_whitelist;
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 handleSwitch(){
aSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
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));
handleChangeRequest(false);
PrefUtils.useWhitelist(this, false);
}
});
}
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)
);
}
}

View File

@ -0,0 +1,134 @@
package com.uam.wmi.findmytutor.adapters;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
import com.uam.wmi.findmytutor.R;
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.PrefUtils;
import com.uam.wmi.findmytutor.utils.RestApiHelper;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
import static com.mapbox.mapboxsdk.Mapbox.getApplicationContext;
public class BlackListAdapter extends RecyclerView.Adapter<BlackListAdapter.MyViewHolder> {
private Context context;
private List<User> tutorsList;
private CompositeDisposable disposable = new CompositeDisposable();
private UserService userService;
public BlackListAdapter(Context context, List<User> tutors) {
this.context = context;
this.tutorsList = tutors;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
userService = ApiClient.getClient(getApplicationContext())
.create(UserService.class);
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.black_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(tutor.getFirstName() + " " + tutor.getLastName());
holder.lastName.setText("Index: " + tutor.getLdapLogin() + " Email: " + tutor.getEmail());
//"s416196"
holder.imageButton.setOnClickListener(l ->{
StudentIdModel studentIdModel = new StudentIdModel(tutor.getLdapLogin());
String tutorId = PrefUtils.getUserId(getApplicationContext());
disposable.add(
userService.removeStudentFromBlacklist(tutorId, studentIdModel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(()->{
Toast.makeText(getApplicationContext(), "User removed", Toast.LENGTH_SHORT).show();
tutorsList.remove(position);
notifyDataSetChanged();
},this::showError)
);
});
//
// if (tutor.isIsOnline()) {
// image = context.getResources().getDrawable(R.drawable.user_list_online);
// } else {
// image = context.getResources().getDrawable(R.drawable.user_list_offline);
// }
//
// if (!tutor.isIsActive()) {
// image = context.getResources().getDrawable(R.drawable.user_list_off);
// }
// 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.lastName)
TextView lastName;
// @BindView(R.id.isOnline)
// TextView isOnline;
@BindView(R.id.removeUserImageButton)
ImageButton imageButton;
MyViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
private void showError(Throwable e) {
String message;
if (e instanceof HttpException) {
ResponseBody responseBody = ((HttpException) e).response().errorBody();
message = RestApiHelper.getErrorMessage(responseBody);
} else {
message = "Network Error !";
}
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
}

View File

@ -0,0 +1,132 @@
package com.uam.wmi.findmytutor.adapters;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
import com.uam.wmi.findmytutor.R;
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.PrefUtils;
import com.uam.wmi.findmytutor.utils.RestApiHelper;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
import static com.mapbox.mapboxsdk.Mapbox.getApplicationContext;
public class WhiteListAdapter extends RecyclerView.Adapter<WhiteListAdapter.MyViewHolder> {
private Context context;
private List<User> tutorsList;
private CompositeDisposable disposable = new CompositeDisposable();
private UserService userService;
public WhiteListAdapter(Context context, List<User> tutors) {
this.context = context;
this.tutorsList = tutors;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
userService = ApiClient.getClient(getApplicationContext())
.create(UserService.class);
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.white_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(tutor.getFirstName() + " " + tutor.getLastName());
holder.lastName.setText("Index: " + tutor.getLdapLogin() + " Email: " + tutor.getEmail());
//"s416196"
holder.imageButton.setOnClickListener(l ->{
StudentIdModel studentIdModel = new StudentIdModel(tutor.getLdapLogin());
String tutorId = PrefUtils.getUserId(getApplicationContext());
disposable.add(
userService.removeStudentFromWhitelist(tutorId, studentIdModel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(()->{
Toast.makeText(getApplicationContext(), "User removed", Toast.LENGTH_SHORT).show();
tutorsList.remove(position);
notifyDataSetChanged();
},this::showError)
);
});
//
// if (tutor.isIsOnline()) {
// image = context.getResources().getDrawable(R.drawable.user_list_online);
// } else {
// image = context.getResources().getDrawable(R.drawable.user_list_offline);
// }
//
// if (!tutor.isIsActive()) {
// image = context.getResources().getDrawable(R.drawable.user_list_off);
// }
// 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.lastName)
TextView lastName;
// @BindView(R.id.isOnline)
// TextView isOnline;
@BindView(R.id.removeUserImageButton)
ImageButton imageButton;
MyViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
private void showError(Throwable e) {
String message;
if (e instanceof HttpException) {
ResponseBody responseBody = ((HttpException) e).response().errorBody();
message = RestApiHelper.getErrorMessage(responseBody);
} else {
message = "Network Error !";
}
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
}

View File

@ -18,6 +18,15 @@ public class StudentIdModel extends BaseResponse{
@SerializedName("ldapLogin") @SerializedName("ldapLogin")
private String ldapLogin = null; private String ldapLogin = null;
/**
*
* @param str
*/
public StudentIdModel(String str){
// this.studentId = str;
this.ldapLogin = str;
}
public StudentIdModel studentId(String studentId) { public StudentIdModel studentId(String studentId) {
this.studentId = studentId; this.studentId = studentId;
return this; return this;

View File

@ -11,12 +11,13 @@ import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Color; import android.graphics.Color;
import android.location.Location; import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager; import android.location.LocationManager;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper;
import android.support.annotation.RequiresApi; import android.support.annotation.RequiresApi;
import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityCompat;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
@ -24,8 +25,10 @@ import android.util.Log;
import com.annimon.stream.Stream; import com.annimon.stream.Stream;
import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices; import com.google.android.gms.location.LocationServices;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
import com.mapbox.geojson.Point; import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLng;
import com.uam.wmi.findmytutor.model.Coordinate; import com.uam.wmi.findmytutor.model.Coordinate;
@ -33,21 +36,17 @@ import com.uam.wmi.findmytutor.network.ApiClient;
import com.uam.wmi.findmytutor.utils.ApproximatedLocalization; import com.uam.wmi.findmytutor.utils.ApproximatedLocalization;
import com.uam.wmi.findmytutor.utils.MapUtils; import com.uam.wmi.findmytutor.utils.MapUtils;
import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.PrefUtils;
import com.uam.wmi.findmytutor.utils.RestApiHelper;
import com.uam.wmi.findmytutor.utils.SharingLevel; import com.uam.wmi.findmytutor.utils.SharingLevel;
import org.apache.commons.collections4.queue.CircularFifoQueue; import org.apache.commons.collections4.queue.CircularFifoQueue;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.observers.DisposableCompletableObserver; import io.reactivex.observers.DisposableCompletableObserver;
import io.reactivex.observers.DisposableSingleObserver;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
import static com.uam.wmi.findmytutor.utils.Const.offlineBackgroundLocationInterval; import static com.uam.wmi.findmytutor.utils.Const.offlineBackgroundLocationInterval;
import static com.uam.wmi.findmytutor.utils.Const.onlineBackgroundLocationInterval; import static com.uam.wmi.findmytutor.utils.Const.onlineBackgroundLocationInterval;
@ -60,32 +59,33 @@ import static java.lang.String.valueOf;
public class BackgroundLocalizationService extends Service { public class BackgroundLocalizationService extends Service {
private static final String TAG = "MyLocationService"; private static final String TAG = "MyLocationService";
private static final float LOCATION_DISTANCE = 1f; private static Integer notify_interval = onlineBackgroundLocationInterval;
private static long notify_interval = onlineBackgroundLocationInterval; private static Integer notify_interval_inside_building = onlineBackgroundLocationInterval;
private static long notify_interval_inside_building = onlineBackgroundLocationInterval; private static Integer notify_interval_outside_building = offlineBackgroundLocationInterval;
private static long notify_interval_outside_building = offlineBackgroundLocationInterval;
private static int coordinatesHistoryLength = 5; private static int coordinatesHistoryLength = 5;
private static final Long LOCATION_INTERVAL = notify_interval; private Boolean highAccuracyMode;
private Location mLastLocation; private Location mLastLocation;
private Boolean stopService = false; private Boolean stopService = false;
private ArrayList<String> providers = new ArrayList<String>(); private ArrayList<String> providers = new ArrayList<String>();
private LocationListener[] mLocationListeners;
private CircularFifoQueue<Location> coordinatesHistory = new CircularFifoQueue<Location>(coordinatesHistoryLength); private CircularFifoQueue<Location> coordinatesHistory = new CircularFifoQueue<Location>(coordinatesHistoryLength);
private LocationManager mLocationManager = null;
private Handler mHandler = new Handler(); private Handler mHandler = new Handler();
private Runnable mStatusChecker; private Runnable mStatusChecker;
private FusedLocationProviderClient mFusedLocationClient; private FusedLocationProviderClient mFusedLocationClient;
private Location fakeLoc = null;
private LocationRequest mLocationRequest;
private Location mCurrentLocation;
private LocationCallback mLocationCallback;
private LocationListener mLocationListener;
public BackgroundLocalizationService() { public BackgroundLocalizationService() {
providers.add(LocationManager.GPS_PROVIDER); providers.add(LocationManager.GPS_PROVIDER);
providers.add(LocationManager.NETWORK_PROVIDER); providers.add(LocationManager.NETWORK_PROVIDER);
providers.add(LocationManager.PASSIVE_PROVIDER); providers.add(LocationManager.PASSIVE_PROVIDER);
fakeLoc = new Location("");
mLocationListeners = new LocationListener[]{ fakeLoc.setLatitude(0);
new LocationListener(LocationManager.GPS_PROVIDER), fakeLoc.setLongitude(0);
new LocationListener(LocationManager.NETWORK_PROVIDER), fakeLoc.setAltitude(0);
new LocationListener(LocationManager.PASSIVE_PROVIDER)
};
} }
@Override @Override
@ -100,7 +100,9 @@ public class BackgroundLocalizationService extends Service {
if (intent != null) { if (intent != null) {
stopService = intent.getBooleanExtra("request_stop", false); stopService = intent.getBooleanExtra("request_stop", false);
notify_interval = intent.getIntExtra("notify_interval", onlineBackgroundLocationInterval);
} }
if (stopService) { if (stopService) {
storeBackgroundLocationStatus(getApplication(), false); storeBackgroundLocationStatus(getApplication(), false);
stopForeground(true); stopForeground(true);
@ -111,6 +113,20 @@ public class BackgroundLocalizationService extends Service {
return START_STICKY; return START_STICKY;
} }
private void createLocationCallback() {
mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
if (locationResult != null) {
mCurrentLocation = locationResult.getLastLocation();
sendCoordinateToBackend(mCurrentLocation);
changeBackgroundMode();
}
}
};
}
@Override @Override
public void onCreate() { public void onCreate() {
Log.e(TAG, "onCreate"); Log.e(TAG, "onCreate");
@ -124,35 +140,13 @@ public class BackgroundLocalizationService extends Service {
startForeground(1001, notification); startForeground(1001, notification);
} }
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); if (!stopService && !PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.MANUAL.toString())) {
createFusedLocationClient();
initializeLocationManager(); } else if (!stopService &&
PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.MANUAL.toString())) {
Integer providerIndex = 0;
for (LocationListener listener : mLocationListeners) {
try {
mLocationManager.requestLocationUpdates(
providers.get(providerIndex),
LOCATION_INTERVAL,
LOCATION_DISTANCE,
listener
);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
providerIndex++;
}
if (!stopService) {
mStatusChecker = () -> { mStatusChecker = () -> {
try { try {
getLocalizationFromListeners(); sendCoordinateToBackend(fakeLoc);
changeBackgroundMode();
} finally { } finally {
mHandler.postDelayed(mStatusChecker, notify_interval); mHandler.postDelayed(mStatusChecker, notify_interval);
} }
@ -162,20 +156,54 @@ public class BackgroundLocalizationService extends Service {
} }
} }
private void createFusedLocationClient() {
Integer saveMode = Long.valueOf(notify_interval).compareTo(Long.valueOf(offlineBackgroundLocationInterval));
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLocationRequest = new LocationRequest();
if (saveMode != 0) {
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
} else {
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
}
mLocationRequest.setFastestInterval(notify_interval);
mLocationRequest.setInterval(notify_interval);
createLocationCallback();
if (!stopService) {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback, Looper.getMainLooper());
}
}
private void changeBackgroundMode() { private void changeBackgroundMode() {
if (coordinatesHistory.size() > 4) { Integer prevInterval = notify_interval;
Boolean shouldExtendTimeInterval = Stream.of(coordinatesHistory) Boolean shouldExtendTimeInterval = Stream.of(coordinatesHistory)
.map(MapUtils::checkIfCoordinateIsValid).takeWhile(s -> !s).toList().size() == coordinatesHistory.size(); .map(MapUtils::checkIfCoordinateIsValid).takeWhile(s -> !s).toList().size() == coordinatesHistory.size();
Boolean shouldAbbreviateTimeInterval = Stream.of(coordinatesHistory). Boolean shouldAbbreviateTimeInterval = Stream.of(coordinatesHistory).
map(MapUtils::checkIfCoordinateIsValid).toList().get(coordinatesHistory.size() - 1); map(MapUtils::checkIfCoordinateIsValid).filter(x -> x).toList().size() > 0;
if (shouldExtendTimeInterval) { if (shouldAbbreviateTimeInterval) {
notify_interval = notify_interval_outside_building;
} else if (shouldAbbreviateTimeInterval) {
notify_interval = notify_interval_inside_building; notify_interval = notify_interval_inside_building;
} }
if (coordinatesHistory.size() > 4 && shouldExtendTimeInterval) {
notify_interval = notify_interval_outside_building;
} }
Integer changedMode = Long.valueOf(prevInterval).compareTo(Long.valueOf(notify_interval));
if (changedMode != 0) {
updateListeners();
}
} }
@RequiresApi(api = Build.VERSION_CODES.O) @RequiresApi(api = Build.VERSION_CODES.O)
@ -198,50 +226,6 @@ public class BackgroundLocalizationService extends Service {
startForeground(2, notification); startForeground(2, notification);
} }
private void getLocalizationFromListeners() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
List<String> providers1 = mLocationManager.getProviders(true);
Location bestLocation = null;
AtomicReference<Boolean> triggerAnotherLocationListener = new AtomicReference<>(false);
mFusedLocationClient.getLastLocation().addOnSuccessListener(
location -> {
if (location != null) {
mLastLocation = location;
coordinatesHistory.add(location);
sendCoordinateToBackend(location);
}
triggerAnotherLocationListener.set(true);
});
if (triggerAnotherLocationListener.get()) {
for (String provider : providers1) {
Location location = mLocationManager.getLastKnownLocation(provider);
if (location == null) {
continue;
}
if (bestLocation == null || location.getAccuracy() < bestLocation.getAccuracy()) {
bestLocation = location;
}
}
coordinatesHistory.add(bestLocation);
}
}
private void sendCoordinateToBackend(Location location) { private void sendCoordinateToBackend(Location location) {
new Task(location).execute(); new Task(location).execute();
} }
@ -252,58 +236,48 @@ public class BackgroundLocalizationService extends Service {
super.onDestroy(); super.onDestroy();
mHandler.removeCallbacks(mStatusChecker); mHandler.removeCallbacks(mStatusChecker);
destroyLocationListeners();
}
if (mLocationManager != null) { private void destroyLocationListeners() {
for (LocationListener listener : mLocationListeners) { if (mFusedLocationClient != null) {
try { mFusedLocationClient.removeLocationUpdates(mLocationCallback);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { mFusedLocationClient = null;
return; mLocationCallback = null;
} mLocationRequest = null;
mLocationManager.removeUpdates(listener);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listener, ignore", ex);
}
}
} }
} }
private void initializeLocationManager() { private void updateListeners() {
Log.e(TAG, "initializeLocationManager - LOCATION_INTERVAL: " + LOCATION_INTERVAL + " LOCATION_DISTANCE: " + LOCATION_DISTANCE); if (mFusedLocationClient != null) {
mFusedLocationClient.removeLocationUpdates(mLocationCallback)
if (mLocationManager == null) { .addOnCompleteListener(task -> {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE); restartService();
mFusedLocationClient = null;
mLocationCallback = null;
mLocationRequest = null;
});
} }
} }
private class LocationListener implements android.location.LocationListener { private void restartService() {
LocationListener(String provider) { Intent stopIntent = new Intent(getApplicationContext(), BackgroundLocalizationService.class);
Log.e(TAG, "LocationListener " + provider); stopIntent.putExtra("request_stop", true);
mLastLocation = new Location(provider);
stopService(stopIntent);
Intent startIntent = new Intent(getApplicationContext(), BackgroundLocalizationService.class);
startIntent.putExtra("notify_interval", notify_interval);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
startForegroundService(startIntent);
} else {
startService(startIntent);
} }
@Override
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged: " + location);
mLastLocation.set(location);
} }
@Override
public void onProviderDisabled(String provider) {
Log.e(TAG, "onProviderDisabled: " + provider);
}
@Override
public void onProviderEnabled(String provider) {
Log.e(TAG, "onProviderEnabled: " + provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.e(TAG, "onStatusChanged: " + provider);
}
}
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
private class Task extends AsyncTask { private class Task extends AsyncTask {
@ -331,6 +305,10 @@ public class BackgroundLocalizationService extends Service {
String status = (PrefUtils.isStatusEnabled(getApplicationContext())) ? PrefUtils.getUserStatus(getApplicationContext()) : ""; String status = (PrefUtils.isStatusEnabled(getApplicationContext())) ? PrefUtils.getUserStatus(getApplicationContext()) : "";
if (locationLevel.equals(SharingLevel.PRESENCE.toString())) { if (locationLevel.equals(SharingLevel.PRESENCE.toString())) {
if (!MapUtils.checkIfCoordinateIsValid(latitude, longitude)) {
return null;
}
latitude = presenceLatitude; latitude = presenceLatitude;
longitude = presenceLongitude; longitude = presenceLongitude;
approximatedBuildingPart = presenceApproximatedName; approximatedBuildingPart = presenceApproximatedName;
@ -345,6 +323,12 @@ public class BackgroundLocalizationService extends Service {
approximatedBuildingPart = PrefUtils.getManualLocationApproximation(getApplicationContext()); approximatedBuildingPart = PrefUtils.getManualLocationApproximation(getApplicationContext());
} }
Location fakeLoc = new Location("");
fakeLoc.setLatitude(latitude);
fakeLoc.setLongitude(longitude);
coordinatesHistory.add(fakeLoc);
try { try {
Coordinate coordinate = new Coordinate( Coordinate coordinate = new Coordinate(
latitude, latitude,
@ -362,7 +346,6 @@ public class BackgroundLocalizationService extends Service {
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableCompletableObserver() { .subscribeWith(new DisposableCompletableObserver() {
@Override @Override
public void onComplete() { public void onComplete() {
Log.e(TAG, "CoordinateSuccess"); Log.e(TAG, "CoordinateSuccess");
@ -370,9 +353,7 @@ public class BackgroundLocalizationService extends Service {
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
Log.e(TAG, "onErr" + valueOf(e)); Log.e(TAG, "onErr" + valueOf(e));
} }
})); }));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {

View File

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

View File

@ -15,9 +15,11 @@ import retrofit2.Response;
import retrofit2.http.Body; import retrofit2.http.Body;
import retrofit2.http.DELETE; import retrofit2.http.DELETE;
import retrofit2.http.GET; import retrofit2.http.GET;
import retrofit2.http.HTTP;
import retrofit2.http.POST; import retrofit2.http.POST;
import retrofit2.http.PUT; import retrofit2.http.PUT;
import retrofit2.http.Path; import retrofit2.http.Path;
import retrofit2.http.Query;
public interface UserService { public interface UserService {
@ -30,6 +32,18 @@ public interface UserService {
@GET("api/users/tutors") @GET("api/users/tutors")
Single <List<User>> getAllTutors(); Single <List<User>> getAllTutors();
@GET("api/users/tutors/online")
Single <List<User>> getAllOnlineTutors();
@GET("api/users/tutors/active")
Single <List<User>> getAllActiveTutors();
@GET("api/users/tutors/offline")
Single <List<User>> getAllOfflineTutors();
@GET("api/users/tutors/search")
Single <List<User>> searchUser(@Query(value = "searchString", encoded = true) String searchString);
@POST("api/users") @POST("api/users")
Completable createUser(@Body User user); Completable createUser(@Body User user);
@ -61,26 +75,28 @@ public interface UserService {
Completable setUserInActive(@Path("userID") String userID); Completable setUserInActive(@Path("userID") String userID);
@GET("api/users/blacklist/{tutorID}") @GET("api/users/blacklist/{tutorID}")
Single<List<User>> getTutorBlacklistedByID(@Path("tutorID") String tutorID); Single<List<String>> getTutorBlacklistedByID(@Path("tutorID") String tutorID);
@PUT("api/users/blacklist/{tutorID}") @PUT("api/users/blacklist/{tutorID}")
Completable setTutorBlacklist(@Path("tutorID") String tutorID, @Body IsUsingListBool isUsing); Completable setTutorBlacklist(@Path("tutorID") String tutorID, @Body IsUsingListBool isUsing);
@POST("api/users/blacklist/{tutorID}") @POST("api/users/blacklist/{tutorID}")
Completable addStudentToBlacklist(@Path("tutorID") String tutorID, @Body StudentIdModel student); Observable <User> addStudentToBlacklist(@Path("tutorID") String tutorID, @Body StudentIdModel student);
@DELETE("api/users/blacklist/{tutorID}") // @DELETE("api/users/blacklist/{tutorID}")
@HTTP(method = "DELETE", path = "api/users/blacklist/{tutorID}", hasBody = true)
Completable removeStudentFromBlacklist(@Path("tutorID") String tutorID, @Body StudentIdModel student); Completable removeStudentFromBlacklist(@Path("tutorID") String tutorID, @Body StudentIdModel student);
@GET("api/users/whitelist/{tutorID}") @GET("api/users/whitelist/{tutorID}")
Single<List<User>> getTutorwhitelistedByID(@Path("tutorID") String tutorID); Single<List<String>> getTutorWhitelistedByID(@Path("tutorID") String tutorID);
@PUT("api/users/whitelist/{tutorID}") @PUT("api/users/whitelist/{tutorID}")
Completable setTutorWhitelist(@Path("tutorID") String tutorID, @Body IsUsingListBool isUsing); Completable setTutorWhitelist(@Path("tutorID") String tutorID, @Body IsUsingListBool isUsing);
@POST("api/users/whitelist/{tutorID}") @POST("api/users/whitelist/{tutorID}")
Completable addStudentTowhitelist(@Path("tutorID") String tutorID, @Body StudentIdModel student); Observable <User> addStudentToWhitelist(@Path("tutorID") String tutorID, @Body StudentIdModel student);
@DELETE("api/users/whitelist/{tutorID}") // @DELETE("api/users/whitelist/{tutorID}")
@HTTP(method = "DELETE", path = "api/users/whitelist/{tutorID}", hasBody = true)
Completable removeStudentFromWhitelist(@Path("tutorID") String tutorID, @Body StudentIdModel student); Completable removeStudentFromWhitelist(@Path("tutorID") String tutorID, @Body StudentIdModel student);
} }

View File

@ -8,7 +8,7 @@ import java.util.List;
public class Const { public class Const {
public final static String BASE_URL = "https://s416084.projektstudencki.pl/master/"; public final static String BASE_URL = "https://s416084.projektstudencki.pl/master/";
public final static Integer onlineBackgroundLocationInterval = 7000; public final static Integer onlineBackgroundLocationInterval = 7000;
public final static Integer offlineBackgroundLocationInterval = 36000; public final static Integer offlineBackgroundLocationInterval = 360000;
public final static Integer defaultMapZoom = 17; public final static Integer defaultMapZoom = 17;
public final static Integer searchMapZoom = 13; public final static Integer searchMapZoom = 13;
public final static Double presenceLatitude = 52.466365; public final static Double presenceLatitude = 52.466365;

View File

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

View File

@ -212,4 +212,35 @@ public class PrefUtils {
return getSharedPreferences(context).getString("current_manual_location_name", null); return getSharedPreferences(context).getString("current_manual_location_name", null);
} }
public static void putShowOnlyOnlineUsers(Context context, Boolean flag) {
SharedPreferences.Editor editor = getSharedPreferences(context).edit();
editor.putBoolean("show_only_online_users_in_list", flag);
editor.apply();
}
public static Boolean getShowOnlyOnlineUsers(Context context) {
return getSharedPreferences(context).getBoolean("show_only_online_users_in_list", true);
}
public static void useBlacklist(Context context, Boolean flag) {
SharedPreferences.Editor editor = getSharedPreferences(context).edit();
editor.putBoolean("blacklisting", flag);
editor.putBoolean("whitelisting", false);
editor.apply();
}
public static void useWhitelist(Context context, Boolean flag) {
SharedPreferences.Editor editor = getSharedPreferences(context).edit();
editor.putBoolean("whitelisting", flag);
editor.putBoolean("blacklisting", false);
editor.apply();
}
public static Boolean isBlackListing(Context context) {
return getSharedPreferences(context).getBoolean("blacklisting", false);
}
public static Boolean isWhiteListing(Context context) {
return getSharedPreferences(context).getBoolean("whitelisting", false);
}
} }

View File

@ -21,6 +21,7 @@ public class RxSearchObservable {
@Override @Override
public boolean onQueryTextSubmit(String s) { public boolean onQueryTextSubmit(String s) {
subject.onNext(s); subject.onNext(s);
searchView.clearFocus();
return false; return false;
} }
@ -31,6 +32,8 @@ public class RxSearchObservable {
} }
}); });

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M0 0h24v24H0z" />
<path
android:fillColor="#FFFFFF"
android:pathData="M15 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm-9-2V7H4v3H1v2h3v3h2v-3h3v-2H6zm9 4c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />
</vector>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:id="@+id/activity_blacklist_container"
tools:context=".activity.BlackList">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:expandedTitleGravity="top|right"
app:toolbarId="@+id/toolbar"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="left|bottom"
android:orientation="vertical"
android:padding="10dp"
android:layout_marginBottom="20dp"
app:layout_collapseMode="parallax">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="Block the users"
android:textSize="15sp"/>
<Switch
android:id="@+id/switch_blacklist_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:thumbTextPadding="45dp"
android:text="BLACKLIST TEXT SWITCH" />
</LinearLayout>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay"
/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_black_list" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/add_to_black_list_fab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:layout_marginTop="-322dp"
app:layout_anchor="@id/app_bar"
app:layout_anchorGravity="bottom|end"
app:srcCompat="@drawable/ic_add_person"
app:useCompatPadding="true"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
<!-- A RecyclerView with some commonly used attributes -->
</android.support.design.widget.CoordinatorLayout>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:id="@+id/activity_whitelist_container"
tools:context=".activity.WhiteList">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:expandedTitleGravity="top|right"
app:toolbarId="@+id/toolbar"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="left|bottom"
android:orientation="vertical"
android:padding="10dp"
android:layout_marginBottom="20dp"
app:layout_collapseMode="parallax">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="Be visible for these users"
android:textSize="15sp"/>
<Switch
android:id="@+id/switch_whitelist_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:thumbTextPadding="45dp"
android:text="WHITELIST TEXT SWITCH" />
</LinearLayout>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay"
/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_white_list" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/add_to_white_list_fab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:layout_marginTop="-322dp"
app:layout_anchor="@id/app_bar"
app:layout_anchorGravity="bottom|end"
app:srcCompat="@drawable/ic_add_person"
app:useCompatPadding="true"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
<!-- A RecyclerView with some commonly used attributes -->
</android.support.design.widget.CoordinatorLayout>

View File

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

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="90dp"
android:clickable="true"
android:focusable="true"
android:paddingLeft="10dp"
android:paddingTop="@dimen/dimen_10"
android:paddingRight="10dp"
android:fontFamily="@font/lato_regular"
android:paddingBottom="@dimen/dimen_10">
<TextView
android:id="@+id/firstName"
android:layout_width="271dp"
android:layout_height="22dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="12dp"
android:layout_marginTop="10dp"
android:textColor="@color/note_list_text"
android:textSize="15sp" />
<TextView
android:id="@+id/lastName"
android:layout_width="270dp"
android:layout_height="22dp"
android:layout_below="@+id/firstName"
android:layout_alignEnd="@+id/firstName"
android:layout_marginTop="10dp"
android:layout_marginEnd="0dp"
android:textColor="@color/note_list_text"
android:textSize="15sp" />
<ImageButton
android:id="@+id/removeUserImageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/firstName"
android:layout_toEndOf="@+id/firstName"
android:background="@null"
android:layout_alignParentEnd="true"
app:srcCompat="@drawable/abc_ic_clear_material" />
</RelativeLayout>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".activity.UsersListFragment"
android:fontFamily="@font/lato_regular"
tools:showIn="@layout/users_list_main">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view_blacklist"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/black_list_empty_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/margin_top_no_notes"
android:fontFamily="sans-serif-light"
android:text="@string/loading"
android:textColor="@color/msg_no_notes"
android:textSize="@dimen/msg_no_notes" />
</RelativeLayout>

View File

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

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".activity.UsersListFragment"
android:fontFamily="@font/lato_regular"
tools:showIn="@layout/users_list_main">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view_whitelist"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/white_list_empty_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/margin_top_no_notes"
android:fontFamily="sans-serif-light"
android:text="@string/loading"
android:textColor="@color/msg_no_notes"
android:textSize="@dimen/msg_no_notes" />
</RelativeLayout>

View File

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

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@drawable/layout_bg"
android:orientation="vertical"
android:padding="10dp"
android:textColor="@color/half_black">
<TextView
android:id="@+id/textViewP1_info_icon_blacklist_p1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_weight="1"
android:text="@string/info_icon_blacklist_p1"
android:textColor="@color/half_black" />
<TextView
android:id="@+id/textViewP2_info_icon_blacklist_p2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="20dp"
android:layout_weight="1"
android:text="@string/info_icon_blacklist_p2"
android:textColor="@color/half_black" />
<TextView
android:id="@+id/textViewP3_info_icon_blacklist_p3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="20dp"
android:layout_weight="1"
android:text="@string/info_icon_blacklist_p3"
android:textColor="@color/half_black" />
</LinearLayout>

View File

@ -72,4 +72,6 @@
android:text="@string/info_icon_userlist_summary" android:text="@string/info_icon_userlist_summary"
android:textColor="@color/half_black"/> android:textColor="@color/half_black"/>
</LinearLayout> </LinearLayout>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@drawable/layout_bg"
android:orientation="vertical"
android:padding="10dp"
android:textColor="@color/half_black">
<TextView
android:id="@+id/textViewP1_info_icon_whitelist_p1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_weight="1"
android:text="@string/info_icon_whitelist_p1"
android:textColor="@color/half_black" />
<TextView
android:id="@+id/textViewP2_info_icon_whitelist_p2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="20dp"
android:layout_weight="1"
android:text="@string/info_icon_whitelist_p2"
android:textColor="@color/half_black" />
<TextView
android:id="@+id/textViewP3_info_icon_whitelist_p3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="20dp"
android:layout_weight="1"
android:text="@string/info_icon_whitelist_p3"
android:textColor="@color/half_black" />
</LinearLayout>

View File

@ -24,14 +24,14 @@
android:textStyle="normal" /> android:textStyle="normal" />
<EditText <EditText
android:id="@+id/feedback_input" android:id="@+id/manual_input"
android:layout_width="315dp" android:layout_width="315dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_marginTop="50dp" android:layout_marginTop="50dp"
android:ems="10" android:ems="10"
android:hint="@string/modal_feedback_hint" android:hint="@string/modal_manual_hint"
android:maxLength="30" android:maxLength="30"
android:maxLines="1" android:maxLines="1"
android:requiresFadingEdge="vertical" android:requiresFadingEdge="vertical"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="90dp" android:layout_height="90dp"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
@ -13,7 +13,7 @@
<TextView <TextView
android:id="@+id/firstName" android:id="@+id/firstName"
android:layout_width="271dp" android:layout_width="270dp"
android:layout_height="22dp" android:layout_height="22dp"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
@ -26,23 +26,25 @@
android:id="@+id/lastName" android:id="@+id/lastName"
android:layout_width="270dp" android:layout_width="270dp"
android:layout_height="22dp" android:layout_height="22dp"
android:layout_marginStart="12dp"
android:layout_below="@+id/firstName" android:layout_below="@+id/firstName"
android:layout_alignEnd="@+id/firstName" android:layout_alignEnd="@+id/firstName"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_marginEnd="0dp" android:layout_marginEnd="0dp"
android:layout_alignParentStart="true"
android:textColor="@color/note_list_text" android:textColor="@color/note_list_text"
android:textSize="15sp" /> android:textSize="15sp" />
<TextView <TextView
android:id="@+id/isOnline" android:id="@+id/isOnline"
android:layout_width="48dp" android:layout_width="50dp"
android:layout_height="30dp" android:layout_height="30dp"
android:layout_below="@+id/firstName" android:layout_below="@+id/firstName"
android:layout_marginStart="7dp" android:layout_marginStart="7dp"
android:layout_marginTop="-10dp" android:layout_marginTop="-10dp"
android:layout_toEndOf="@+id/firstName"
android:textColor="@color/note_list_text" android:textColor="@color/note_list_text"
android:layout_alignParentEnd="true"
android:textSize="@dimen/note_list_text" /> android:textSize="@dimen/note_list_text" />

View File

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

View File

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

View File

@ -12,6 +12,7 @@
<android.support.v7.widget.RecyclerView <android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view" android:id="@+id/recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:scrollbars="vertical"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
<TextView <TextView

View File

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

View File

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

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="90dp"
android:clickable="true"
android:focusable="true"
android:paddingLeft="10dp"
android:paddingTop="@dimen/dimen_10"
android:paddingRight="10dp"
android:fontFamily="@font/lato_regular"
android:paddingBottom="@dimen/dimen_10">
<TextView
android:id="@+id/firstName"
android:layout_width="271dp"
android:layout_height="22dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="12dp"
android:layout_marginTop="10dp"
android:textColor="@color/note_list_text"
android:textSize="15sp" />
<TextView
android:id="@+id/lastName"
android:layout_width="270dp"
android:layout_height="22dp"
android:layout_below="@+id/firstName"
android:layout_alignEnd="@+id/firstName"
android:layout_marginTop="10dp"
android:layout_marginEnd="0dp"
android:textColor="@color/note_list_text"
android:textSize="15sp" />
<ImageButton
android:id="@+id/removeUserImageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/firstName"
android:layout_toEndOf="@+id/firstName"
android:background="@null"
android:layout_alignParentEnd="true"
app:srcCompat="@drawable/abc_ic_clear_material" />
</RelativeLayout>

View File

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

View File

@ -0,0 +1,11 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.uam.wmi.findmytutor.activity.BlackList">
<item
android:id="@+id/action_blacklist_info_popup"
android:orderInCategory="100"
android:title="Popup info icon"
android:icon="@drawable/outline_info_24"
app:showAsAction="ifRoom" />
</menu>

View File

@ -6,6 +6,8 @@
android:id="@+id/action_search" android:id="@+id/action_search"
android:icon="@drawable/ic_menu_search" android:icon="@drawable/ic_menu_search"
app:showAsAction="always" app:showAsAction="always"
android:focusable="true"
android:focusableInTouchMode="true"
app:actionViewClass="android.support.v7.widget.SearchView" app:actionViewClass="android.support.v7.widget.SearchView"
android:title="@string/search"/> android:title="@string/search"/>
<item <item

View File

@ -0,0 +1,11 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.uam.wmi.findmytutor.activity.BlackList">
<item
android:id="@+id/action_whitelist_info_popup"
android:orderInCategory="100"
android:title="Popup info icon"
android:icon="@drawable/outline_info_24"
app:showAsAction="ifRoom" />
</menu>

View File

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

View File

@ -29,7 +29,7 @@
<string name="mockup_location_string">\"\"</string> <string name="mockup_location_string">\"\"</string>
<string name="pref_header_about">O aplikacji</string> <string name="pref_header_about">O aplikacji</string>
<string name="summary_about"> <string name="summary_about">
Jesteśmy grupą studentów, która chce pomoć w rozwoju naszego wydziału.\nDziękujemy za używanie naszej aplikacji.\nZespół FMT.!</string> Jesteśmy grupą studentów, która chce pomoć w rozwoju naszego wydziału.\nDziękujemy za używanie naszej aplikacji.\nZespół FMT</string>
<string name="app_version">0.1.0</string> <string name="app_version">0.1.0</string>
<string name="summary_support">Masz jakieś pytania? Uwagi? Chętnie odpiszemy!</string> <string name="summary_support">Masz jakieś pytania? Uwagi? Chętnie odpiszemy!</string>
<string name="title_send_feedback">Skontaktuj się z nami</string> <string name="title_send_feedback">Skontaktuj się z nami</string>
@ -118,7 +118,7 @@
<string name="userDepartment">Zakład</string> <string name="userDepartment">Zakład</string>
<string name="loading">Ładowanie …</string> <string name="loading">Ładowanie …</string>
<string name="logo_find_my_tutor">Logo find my tutor</string> <string name="logo_find_my_tutor">Logo find my tutor</string>
<string name="prompt_login">Login (Ldap)</string> <string name="prompt_login">Login (LDAP WMI)</string>
<string name="action_log_in">Zaloguj!</string> <string name="action_log_in">Zaloguj!</string>
<string name="error_invalid_login_name">Niepoprawny format loginu.</string> <string name="error_invalid_login_name">Niepoprawny format loginu.</string>
<string name="user_list_nav">Kadra</string> <string name="user_list_nav">Kadra</string>
@ -132,7 +132,7 @@
<string name="fab_title_bound_area">Bounds OFF</string> <string name="fab_title_bound_area">Bounds OFF</string>
<string name="email_subject_feedback">Find My Tutor - feedback</string> <string name="email_subject_feedback">Find My Tutor - feedback</string>
<string name="email_subject_bug">Find My Tutor - zgłoszenie błędu</string> <string name="email_subject_bug">Find My Tutor - zgłoszenie błędu</string>
<string name="modal_feedback_hint">Proszę opisz swoje spostrzeżnia.</string> <string name="modal_feedback_hint">Opisz proszę swoje spostrzeżenia.</string>
<string name="modal_feedback_question">Wyślij anonimowo</string> <string name="modal_feedback_question">Wyślij anonimowo</string>
<string name="location_level_manual">Manualna</string> <string name="location_level_manual">Manualna</string>
<string name="preference_manual_location_button">Wybierz z mapy</string> <string name="preference_manual_location_button">Wybierz z mapy</string>
@ -159,7 +159,7 @@
<string name="network_error">Błąd sieci!</string> <string name="network_error">Błąd sieci!</string>
<string name="manual_status_error">Błąd podczas pobierania danych.</string> <string name="manual_status_error">Błąd podczas pobierania danych.</string>
<string name="error_status_fetch">Błąd podczas pobierania statusów.</string> <string name="error_status_fetch">Błąd podczas pobierania statusów.</string>
<string name="notification_text">Upss. Coś poszło nie tak. Pracujemy nad tym!</string> <string name="notification_text">Upss. Coś poszło nie tak!</string>
<string name="lack_duty_hours">Brak informacji o dyżurze.</string> <string name="lack_duty_hours">Brak informacji o dyżurze.</string>
<string name="lack_note">Brak notatki.</string> <string name="lack_note">Brak notatki.</string>
<string name="search">Wyszukiwarka</string> <string name="search">Wyszukiwarka</string>
@ -194,23 +194,27 @@
<!--(PL) Sharing Tab info helper--> <!--(PL) Sharing Tab info helper-->
<string name="info_icon_sharing_tab_p1">W tej zakładce możesz włączyć/wyłączyć udostępnianie swojej lokalizacji oraz ją skonfigurować.</string> <string name="info_icon_sharing_tab_p1">W tej zakładce możesz włączyć/wyłączyć udostępnianie swojej lokalizacji oraz ją skonfigurować.</string>
<string name="info_icon_sharing_tab_p2">Niektóre zmiany mogą nie być widoczne od razu! Odświeżanie informacji zajmuje do 2 minut.</string> <string name="info_icon_sharing_tab_p2">Niektóre zmiany mogą nie być widoczne od razu! Wyłączenie wysyłania ma skutek natychmiastowy, lecz odświeżanie informacji zajmuje serwerowi do 2 minut.</string>
<string name="info_icon_sharing_tab_p3">Udostępniać możesz na jednym z 4 poziomów:</string> <string name="info_icon_sharing_tab_p3">Udostępniać możesz na jednym z 4 poziomów:</string>
<string name="info_icon_sharing_tab_p3_level_exact"><b>dokładny </b> - lokalizacja wyświetlana na mapie na podstawie GPS</string> <string name="info_icon_sharing_tab_p3_level_exact"><b>dokładny </b> - lokalizacja wyświetlana na mapie na podstawie GPS</string>
<string name="info_icon_sharing_tab_p3_level_approximate"><b>przybliżony</b> - przybliżona lokalizacja wyświetlana na podstawie GPS</string> <string name="info_icon_sharing_tab_p3_level_approximate"><b>przybliżony</b> - przybliżona lokalizacja wyświetlana na podstawie GPS</string>
<string name="info_icon_sharing_tab_p3_level_manual"><b>manualny</b> - udostępnianie z ręcznie wybranego punktu na mapie</string> <string name="info_icon_sharing_tab_p3_level_manual"><b>manualny</b> - udostępnianie z ręcznie wybranego punktu na mapie</string>
<string name="info_icon_sharing_tab_p3_level_presence"><b>tylko obecność</b> - udostępnianie jedynie informacji o pojawieniu się na wydziale (aktywny na liście), bez udostępniania lokalizacji</string> <string name="info_icon_sharing_tab_p3_level_presence"><b>tylko obecność</b> - udostępnianie jedynie informacji o pojawieniu się na wydziale (aktywny na liście), bez udostępniania lokalizacji</string>
<string name="info_icon_sharing_tab_p4">Każdy poziom z wyjątkiem manualnie wybranej lokalizacji automatycznie zaczyna udostępniać po wejściu na wydział i przestaje udostępniać po jego opuszczeniu. Wystarczy włączyć udostępnianie, a lokalizacja nie będzie udostępniana tylko przy obecności na wydziale.</string> <string name="info_icon_sharing_tab_p4">Każdy poziom z wyjątkiem manualnie wybranej lokalizacji automatycznie zaczyna udostępniać po wejściu na wydział i przestaje udostępniać po jego opuszczeniu. Wystarczy włączyć udostępnianie, a lokalizacja będzie udostępniana tylko przy obecności na wydziale.</string>
<string name="info_icon_sharing_tab_p5">Udostępnianie w dowolnym momencie można wyłączyć za pomocą przełącznika.</string> <string name="info_icon_sharing_tab_p5">Udostępnianie w dowolnym momencie można wyłączyć za pomocą przełącznika.</string>
<string name="info_icon_sharing_tab_p6">Dodatkowo, do Twojej lokalizacji możesz dodać status opisowy (będzie on widoczny dla użytkowników po kliknięciu w marker).</string> <string name="info_icon_sharing_tab_p6">Dodatkowo, do Twojej lokalizacji możesz dodać status opisowy (będzie on widoczny dla użytkowników po kliknięciu w marker).</string>
<string name="info_icon_sharing_tab_p7">Zarówno manualne lokalizacje jak i statusy możesz dodać do listy, które potem możesz wybrać w wygodny sposób.</string> <string name="info_icon_sharing_tab_p7">Zarówno manualne lokalizacje jak i statusy możesz dodać do listy, z której możesz potem je wybrać w wygodny sposób.</string>
<!--(PL) Userlist Tab info helper--> <!--(PL) Userlist Tab info helper-->
<string name="info_icon_userlist_tab_p1">W tym panelu znajduje się listę profesorów.</string> <string name="info_icon_userlist_tab_p1">W tym panelu znajduje się lista profesorów.</string>
<string name="info_icon_userlist_tab_p2">Ich status symbolizowany jest przez kolorowe kropki:</string> <string name="info_icon_userlist_tab_p2">Ich status symbolizowany jest przez kolorowe kropki:</string>
<string name="info_icon_userlist_tab_level_status_online">- użytkownik jest obecnie online</string> <string name="info_icon_userlist_tab_level_status_online">- użytkownik jest obecnie online</string>
<string name="info_icon_userlist_tab_level_status_offline">- użytkownik jest obecnie offline</string> <string name="info_icon_userlist_tab_level_status_offline">- użytkownik jest obecnie offline</string>
<string name="info_icon_userlist_tab_level_status_inactive">- użytkownik jest nieaktywny</string> <string name="info_icon_userlist_tab_level_status_inactive">- użytkownik jest nieaktywny</string>
<string name="info_icon_userlist_tab_level_status_inactive_tip">(nie udostępnił żadnych danych o lokalizacji od conajmniej tygodnia)</string> <string name="info_icon_userlist_tab_level_status_inactive_tip">(nie udostępnił żadnych danych o lokalizacji od conajmniej tygodnia)</string>
<string name="add">Dodaj</string>
<string name="index_user">Index użytkownika</string>
<string name="black_list_title">Dodaj użytkownika do Blacklsi</string>
<string name="info_icon_userlist_summary">Po kliknięciu w imię i nazwisko, wyświetli się karta zawierająca dokładne informacje o profesorze.</string> <string name="info_icon_userlist_summary">Po kliknięciu w imię i nazwisko, wyświetli się karta zawierająca dokładne informacje o profesorze.</string>
@ -219,7 +223,7 @@
<string name="pref_acra_disabled" translatable="false">Pozwól na wysyłanie raportów o błędach.</string> <string name="pref_acra_disabled" translatable="false">Pozwól na wysyłanie raportów o błędach.</string>
<string name="pref_acra_enabled" translatable="false">Pozwól na wysyłanie raportów o błędach.</string> <string name="pref_acra_enabled" translatable="false">Pozwól na wysyłanie raportów o błędach.</string>
<string name="pref_title_acra" translatable="false">Raportowanie błędów.</string> <string name="pref_title_acra" translatable="false">Raportowanie błędów.</string>
<string name="acra_toast_text" translatable="false">Błąd aplikacji. Informacje o błędzie zostanie wysłana do twórców.</string> <string name="acra_toast_text" translatable="false">Błąd aplikacji. Informacje o błędzie zostaną wysłane do twórców.</string>
<string name="hint_duty_day">Dzień</string> <string name="hint_duty_day">Dzień</string>
@ -241,6 +245,29 @@
<string name="sharing_modal_title">Udostępnianie</string> <string name="sharing_modal_title">Udostępnianie</string>
<string name="preference_manual_location_button_remove">Zarządzaj zapisanymi</string> <string name="preference_manual_location_button_remove">Zarządzaj zapisanymi</string>
<string name="preference_manual_status_button_remove">Zarządzaj zapisanymi</string> <string name="preference_manual_status_button_remove">Zarządzaj zapisanymi</string>
<string name="blacklist">Czarna lista</string>
<string name="can_not_be_empty">Pole nie może być puste</string>
<string name="user_added">Użytkownik dodany</string>
<string name="list_is_empty">Lista jest pusta</string>
<string name="on">WŁĄCZONA</string>
<string name="off">WYŁĄCZONA</string>
<string name="title_activity_black_list">Czarna lista</string>
<string name="scrap_tutor_tab">Pobierz dane z WMI</string>
<string name="scrap_tutor_msg">Dane zostały zaktualizwane!</string>
<!--(ENG) Checkbox online users list -->
<string name="no_online_users">Brak aktywnych użytkowników.</string>
<string name="no_offline_users">Brak użytkowników offline.</string>
<string name="activity_title_blacklist">Czarna lista</string>
<string name="activity_title_whitelist">Biała lista</string>
<string name="title_activity_white_list">Biała lista</string>
<string name="white_list_title">Dodaj użytkownika do białej listy</string>
<string name="no_such_a_user">Nie ma takiego użytkownika</string>
<string name="only_online_users">Tylko aktywni użytkownicy</string>
<string name="network_err">Błąd sieci!</string>
<string name="search_null">Brak wyników!</string>
<string name="modal_manual_hint">Nadaj nazwę tej lokalizacji.</string>
</resources> </resources>

View File

@ -19,4 +19,6 @@
<dimen name="note_list_text">13sp</dimen> <dimen name="note_list_text">13sp</dimen>
<dimen name="default_margin">12dp</dimen> <dimen name="default_margin">12dp</dimen>
<dimen name="text_large">10dp</dimen> <dimen name="text_large">10dp</dimen>
<dimen name="app_bar_height">180dp</dimen>
<dimen name="text_margin">16dp</dimen>
</resources> </resources>

View File

@ -32,7 +32,8 @@
<!-- Tutors list --> <!-- Tutors list -->
<string name="action_settings">Settings</string> <string name="action_settings">Settings</string>
<string name="activity_title_home">Notes</string> <string name="activity_title_blacklist">Blacklist</string>
<string name="activity_title_whitelist">Whitelist</string>
<string name="prompt_password">Password</string> <string name="prompt_password">Password</string>
<string name="action_sign_in">Sign in or register</string> <string name="action_sign_in">Sign in or register</string>
<string name="action_sign_out">Sign out</string> <string name="action_sign_out">Sign out</string>
@ -257,7 +258,7 @@
<string name="pref_disable_acra" translatable="false">App issues reporting</string> <string name="pref_disable_acra" translatable="false">App issues reporting</string>
<!--(ENG) Map Activity info helper--> <!--(ENG) Map Activity info helper-->
<string name="map_info_text_p1">On the map there are markers which represents tutors sharing their location right now.</string> <string name="map_info_text_p1">On the map there are markers which represent tutors sharing their location right now.</string>
<string name="map_info_text_p2">After clicking on a marker, you can check who is sharing it and the descriptive status (if the tutor have set one).</string> <string name="map_info_text_p2">After clicking on a marker, you can check who is sharing it and the descriptive status (if the tutor have set one).</string>
<string name="map_info_text_p3">In the app there are 3 possible types of localization, represented by various colors.</string> <string name="map_info_text_p3">In the app there are 3 possible types of localization, represented by various colors.</string>
<string name="map_info_text_marker_exact">exact localization (from mobile GPS)</string> <string name="map_info_text_marker_exact">exact localization (from mobile GPS)</string>
@ -282,7 +283,7 @@
<!--(ENG) Sharing Tab info helper--> <!--(ENG) Sharing Tab info helper-->
<string name="info_icon_sharing_tab_p1">In this tab you can turn on/off sharing your localization and configure it.</string> <string name="info_icon_sharing_tab_p1">In this tab you can turn on/off sharing your localization and configure it.</string>
<string name="info_icon_sharing_tab_p2">Some of the changes may not happen immediately! Refreshing information takes up to 2 minutes.</string> <string name="info_icon_sharing_tab_p2">Some of the changes may not be visible immediately! Turning sharing off is stopping the sharing immediately, but refreshing information by server takes up to 2 minutes.</string>
<string name="info_icon_sharing_tab_p3">You can share your localization on one of the 4 levels:</string> <string name="info_icon_sharing_tab_p3">You can share your localization on one of the 4 levels:</string>
<string name="info_icon_sharing_tab_p3_level_exact"><b>exact</b> - localization displayed on a map, based on GPS</string> <string name="info_icon_sharing_tab_p3_level_exact"><b>exact</b> - localization displayed on a map, based on GPS</string>
<string name="info_icon_sharing_tab_p3_level_approximate"><b>approximated</b> - approximated localization based on GPS</string> <string name="info_icon_sharing_tab_p3_level_approximate"><b>approximated</b> - approximated localization based on GPS</string>
@ -291,7 +292,7 @@
<string name="info_icon_sharing_tab_p4">Each level, except from manual, will be automatically turned on when entering, and turn off when leaving the faculty. You only need to make sure that sharing is on, and the localization will be shared only when on the faculty.</string> <string name="info_icon_sharing_tab_p4">Each level, except from manual, will be automatically turned on when entering, and turn off when leaving the faculty. You only need to make sure that sharing is on, and the localization will be shared only when on the faculty.</string>
<string name="info_icon_sharing_tab_p5">Sharing can be turned off at any time with the switch.</string> <string name="info_icon_sharing_tab_p5">Sharing can be turned off at any time with the switch.</string>
<string name="info_icon_sharing_tab_p6">Additionally, you can add descriptive status to your localization (visible for users after clicking on a marker).</string> <string name="info_icon_sharing_tab_p6">Additionally, you can add descriptive status to your localization (visible for users after clicking on a marker).</string>
<string name="info_icon_sharing_tab_p7">Both manual localizations and statuses can be added to a list, and then used them in a convenient way. </string> <string name="info_icon_sharing_tab_p7">Both manual localizations and statuses can be added to a list, and then used in a convenient way. </string>
<!--(ENG) Userlist tab info helper--> <!--(ENG) Userlist tab info helper-->
<string name="info_icon_userlist_tab_p1">This panel contains the list of tutors.</string> <string name="info_icon_userlist_tab_p1">This panel contains the list of tutors.</string>
@ -300,10 +301,108 @@
<string name="info_icon_userlist_tab_level_status_offline">- user is currently offline</string> <string name="info_icon_userlist_tab_level_status_offline">- user is currently offline</string>
<string name="info_icon_userlist_tab_level_status_inactive">- user is inactive </string> <string name="info_icon_userlist_tab_level_status_inactive">- user is inactive </string>
<string name="info_icon_userlist_tab_level_status_inactive_tip">(didnt share any localization data since 7 days)</string> <string name="info_icon_userlist_tab_level_status_inactive_tip">(didnt share any localization data since 7 days)</string>
<string name="info_icon_userlist_summary">After clicking on a name, the tutor tab will pop up, containing details about selected tutor.</string> <string name="title_activity_black_list">BlackList</string>
<string name="title_activity_white_list">Whitelist</string>
<string name="white_list_title">Add user to Whitelist</string>
<string name="large_text" translatable="false">
"Material is the metaphor.\n\n"
"A material metaphor is the unifying theory of a rationalized space and a system of motion."
"The material is grounded in tactile reality, inspired by the study of paper and ink, yet "
"technologically advanced and open to imagination and magic.\n"
"Surfaces and edges of the material provide visual cues that are grounded in reality. The "
"use of familiar tactile attributes helps users quickly understand affordances. Yet the "
"flexibility of the material creates new affordances that supercede those in the physical "
"world, without breaking the rules of physics.\n"
"The fundamentals of light, surface, and movement are key to conveying how objects move, "
"interact, and exist in space and in relation to each other. Realistic lighting shows "
"seams, divides space, and indicates moving parts.\n\n"
"Bold, graphic, intentional.\n\n"
"The foundational elements of print based design typography, grids, space, scale, color, "
"and use of imagery guide visual treatments. These elements do far more than please the "
"eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge "
"imagery, large scale typography, and intentional white space create a bold and graphic "
"interface that immerse the user in the experience.\n"
"An emphasis on user actions makes core functionality immediately apparent and provides "
"waypoints for the user.\n\n"
"Motion provides meaning.\n\n"
"Motion respects and reinforces the user as the prime mover. Primary user actions are "
"inflection points that initiate motion, transforming the whole design.\n"
"All action takes place in a single environment. Objects are presented to the user without "
"breaking the continuity of experience even as they transform and reorganize.\n"
"Motion is meaningful and appropriate, serving to focus attention and maintain continuity. "
"Feedback is subtle yet clear. Transitions are efficient yet coherent.\n\n"
"3D world.\n\n"
"The material environment is a 3D space, which means all objects have x, y, and z "
"dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the "
"positive z-axis extending towards the viewer. Every sheet of material occupies a single "
"position along the z-axis and has a standard 1dp thickness.\n"
"On the web, the z-axis is used for layering and not for perspective. The 3D world is "
"emulated by manipulating the y-axis.\n\n"
"Light and shadow.\n\n"
"Within the material environment, virtual lights illuminate the scene. Key lights create "
"directional shadows, while ambient light creates soft shadows from all angles.\n"
"Shadows in the material environment are cast by these two light sources. In Android "
"development, shadows occur when light sources are blocked by sheets of material at "
"various positions along the z-axis. On the web, shadows are depicted by manipulating the "
"y-axis only. The following example shows the card with a height of 6dp.\n\n"
"Resting elevation.\n\n"
"All material objects, regardless of size, have a resting elevation, or default elevation "
"that does not change. If an object changes elevation, it should return to its resting "
"elevation as soon as possible.\n\n"
"Component elevations.\n\n"
"The resting elevation for a component type is consistent across apps (e.g., FAB elevation "
"does not vary from 6dp in one app to 16dp in another app).\n"
"Components may have different resting elevations across platforms, depending on the depth "
"of the environment (e.g., TV has a greater depth than mobile or desktop).\n\n"
"Responsive elevation and dynamic elevation offsets.\n\n"
"Some component types have responsive elevation, meaning they change elevation in response "
"to user input (e.g., normal, focused, and pressed) or system events. These elevation "
"changes are consistently implemented using dynamic elevation offsets.\n"
"Dynamic elevation offsets are the goal elevation that a component moves towards, relative "
"to the components resting state. They ensure that elevation changes are consistent "
"across actions and component types. For example, all components that lift on press have "
"the same elevation change relative to their resting elevation.\n"
"Once the input event is completed or cancelled, the component will return to its resting "
"elevation.\n\n"
"Avoiding elevation interference.\n\n"
"Components with responsive elevations may encounter other components as they move between "
"their resting elevations and dynamic elevation offsets. Because material cannot pass "
"through other material, components avoid interfering with one another any number of ways, "
"whether on a per component basis or using the entire app layout.\n"
"On a component level, components can move or be removed before they cause interference. "
"For example, a floating action button (FAB) can disappear or move off screen before a "
"user picks up a card, or it can move if a snackbar appears.\n"
"On the layout level, design your app layout to minimize opportunities for interference. "
"For example, position the FAB to one side of stream of a cards so the FAB wont interfere "
"when a user tries to pick up one of cards.\n\n"
</string>
<string name="info_icon_userlist_summary">After clicking on a name, the tutor tab will pop up, containing details about selected tutor.\n\nYou can search for any tutor on the map by entering his name and surname in the search field.\n\nBy default, only active users are shown. You can change that in menu (three dots icon).\n\nYou can also search for a tutor directly, by entering name and surname of person that you look for.</string>
<!--(ENG) Blacklist -->
<string name="index_user">User index</string>
<string name="black_list_title">Add user to blacklist</string>
<string name="add">Add</string>
<string name="possitive_dialog_button">Yes</string> <string name="possitive_dialog_button">Yes</string>
<string name="pref_title_acra" translatable="false">App issues reporting</string> <string name="pref_title_acra" translatable="false">App issues reporting</string>
<!--(ENG) Profile Activity strings--> <!--(ENG) Profile Activity strings-->
@ -322,4 +421,23 @@
<string name="enable_sharing_question">In order to use this function, you have to enable localization sharing. May I do it for you?</string> <string name="enable_sharing_question">In order to use this function, you have to enable localization sharing. May I do it for you?</string>
<string name="sharing_modal_title">Sharing</string> <string name="sharing_modal_title">Sharing</string>
<string name="lack_of_status">The user hasn\'t defined a status.</string> <string name="lack_of_status">The user hasn\'t defined a status.</string>
<string name="can_not_be_empty">Field can not be empty</string>
<string name="user_added">User added</string>
<string name="list_is_empty">The list is empty</string>
<string name="activity_title_home">Map</string>
<string name="on">ON</string>
<string name="off">OFF</string>
<string name="scrap_tutor_tab">Scrap!</string>
<string name="scrap_tutor_msg">Data updated!</string>
<!--(ENG) Checkbox online users list -->
<string name="no_online_users">Currently, there are no\nactive users.</string>
<string name="no_offline_users">Currently, there are no\noffline users.</string>
<string name="only_online_users">Only online users</string>
<string name="no_such_a_user">No such a user</string>
<string name="network_err">Network Error !</string>
<string name="search_null">Search response is empty!</string>
<string name="modal_manual_hint">Insert a name for this localization.</string>
</resources> </resources>

View File

@ -22,4 +22,5 @@
<item name="android:background">@drawable/fab_label_background</item> <item name="android:background">@drawable/fab_label_background</item>
<item name="android:textColor">@color/mapboxWhite</item> <item name="android:textColor">@color/mapboxWhite</item>
</style> </style>
</resources> </resources>