Updated LoginFragment and ModulesFragment (not runnable)
This commit is contained in:
@@ -48,7 +48,6 @@ import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
|
||||
public class MainActivity extends AppCompatActivity
|
||||
implements MainActivityListener, KVVListener,
|
||||
NavigationView.OnNavigationItemSelectedListener,
|
||||
LoginFragment.OnLoginFragmentInteractionListener,
|
||||
ModulesFragment.OnModulesFragmentInteractionListener,
|
||||
CanteensFragment.OnCanteensFragmentInteractionListener {
|
||||
|
||||
@@ -102,7 +101,10 @@ public class MainActivity extends AppCompatActivity
|
||||
mNavigationView.setNavigationItemSelectedListener(this);
|
||||
mFragmentManager = getSupportFragmentManager();
|
||||
|
||||
getNewKVV().account().doOfflineLogin();
|
||||
if (!getNewKVV().account().restoreOnlineLogin()) {
|
||||
desiredPage = FRAGMENT_LOGIN;
|
||||
desiredData = "";
|
||||
}
|
||||
updateNavigation();
|
||||
changeFragment(desiredPage, desiredData);
|
||||
}
|
||||
@@ -492,12 +494,6 @@ public class MainActivity extends AppCompatActivity
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onLoginFragmentInteraction(LoginToken loginToken, boolean onlineMode) {
|
||||
int fragment = getDefaultFragmentAfterLogin();
|
||||
toLoginState(loginToken.getFullName(), loginToken.getEmail(), fragment, "", onlineMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModulesFragmentInteraction(final String itemID) {
|
||||
changeFragment(FRAGMENT_MODULES_DETAILS, itemID);
|
||||
|
||||
@@ -70,8 +70,8 @@ public class CanteensFragment extends Fragment {
|
||||
CanteenBrowser browser = ((MainActivity) getActivity()).getCanteenBrowser();
|
||||
browser.getCanteens(success -> {
|
||||
adapter.setCanteens(success);
|
||||
if (mMainActivityListener != null)
|
||||
mMainActivityListener.refreshNavigation();
|
||||
//if (mMainActivityListener != null)
|
||||
// mMainActivityListener.refreshNavigation();
|
||||
swipeLayout.setRefreshing(false);
|
||||
}, error -> {
|
||||
log.e(error.toString());
|
||||
|
||||
@@ -9,31 +9,21 @@ import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import de.sebse.fuplanner.MainActivity;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth;
|
||||
import de.sebse.fuplanner.services.KVV.KVV;
|
||||
import de.sebse.fuplanner.services.KVV.types.LoginToken;
|
||||
import de.sebse.fuplanner.services.KVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.MainActivityListener;
|
||||
import de.sebse.fuplanner.tools.logging.Logger;
|
||||
|
||||
/**
|
||||
* A simple {@link Fragment} subclass.
|
||||
* Activities that contain this fragment must implement the
|
||||
* {@link LoginFragment.OnLoginFragmentInteractionListener} interface
|
||||
* to handle interaction events.
|
||||
* Use the {@link LoginFragment#newInstance} factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
public class LoginFragment extends Fragment {
|
||||
private OnLoginFragmentInteractionListener mListener;
|
||||
private final Logger log = new Logger(this);
|
||||
private MainActivityListener mActivityListener;
|
||||
@Nullable private MainActivityListener mActivityListener;
|
||||
|
||||
public LoginFragment() {
|
||||
// Required empty public constructor
|
||||
@@ -57,21 +47,11 @@ public class LoginFragment extends Fragment {
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View v = inflater.inflate(R.layout.fragment_login, container, false);
|
||||
try {
|
||||
Context context = getContext();
|
||||
if (context != null) {
|
||||
Modules modules = Modules.load(context);
|
||||
if (modules != null) {
|
||||
if (mActivityListener != null && mActivityListener.getNewKVV().modules().list().stored()) {
|
||||
Button offline_btn = v.findViewById(R.id.btn_offline);
|
||||
offline_btn.setVisibility(View.VISIBLE);
|
||||
offline_btn.setText(v.getResources().getString(R.string.enter_offline_mode, modules.getToken().getUsername()));
|
||||
offline_btn.setOnClickListener(v1 -> mListener.onLoginFragmentInteraction(modules.getToken(), false));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
offline_btn.setText(v.getResources().getString(R.string.enter_offline_mode, mActivityListener.getNewKVV().modules().list().getUsername()));
|
||||
offline_btn.setOnClickListener(v1 -> mActivityListener.getNewKVV().account().doOfflineLogin());
|
||||
}
|
||||
|
||||
View btn_login = v.findViewById(R.id.btn_login);
|
||||
@@ -84,24 +64,15 @@ public class LoginFragment extends Fragment {
|
||||
|
||||
EditText input_usr = ((View) view.getParent()).findViewById(R.id.input_username);
|
||||
EditText input_pwd = ((View) view.getParent()).findViewById(R.id.input_password);
|
||||
if (input_usr != null) {
|
||||
if (input_pwd != null) {
|
||||
if (LoginFragment.this.getActivity() == null) {
|
||||
log.e("Login fragment has no activity!");
|
||||
return;
|
||||
}
|
||||
|
||||
String username = input_usr.getText().toString();
|
||||
String password = input_pwd.getText().toString();
|
||||
KVV kvv = ((MainActivity) getActivity()).getKVV();
|
||||
GoogleAuth gauth = ((MainActivity) getActivity()).getGoogleAuth();
|
||||
kvv.login(username, password, success -> {
|
||||
|
||||
mActivityListener.getNewKVV().account().doOnlineLogin(username, password, success -> {
|
||||
progressDialog.dismiss();
|
||||
gauth.setLoginState(username, password);
|
||||
if (mListener != null) {
|
||||
mActivityListener.getGoogleAuth().setLoginState(username, password);
|
||||
input_usr.setError(null);
|
||||
input_pwd.setError(null);
|
||||
mListener.onLoginFragmentInteraction(success, true);
|
||||
}
|
||||
}, error -> {
|
||||
progressDialog.dismiss();
|
||||
// Invalid password
|
||||
@@ -116,8 +87,6 @@ public class LoginFragment extends Fragment {
|
||||
}
|
||||
log.e("Error on KVV login!", error);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return v;
|
||||
@@ -128,12 +97,6 @@ public class LoginFragment extends Fragment {
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (context instanceof OnLoginFragmentInteractionListener) {
|
||||
mListener = (OnLoginFragmentInteractionListener) context;
|
||||
} else {
|
||||
throw new RuntimeException(context.toString()
|
||||
+ " must implement OnLoginFragmentInteractionListener");
|
||||
}
|
||||
if (context instanceof MainActivityListener) {
|
||||
mActivityListener = (MainActivityListener) context;
|
||||
mActivityListener.onTitleTextChange(R.string.log_in);
|
||||
@@ -144,20 +107,6 @@ public class LoginFragment extends Fragment {
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface must be implemented by activities that contain this
|
||||
* fragment to allow an interaction in this fragment to be communicated
|
||||
* to the activity and potentially other fragments contained in that
|
||||
* activity.
|
||||
* <p>
|
||||
* See the Android Training lesson <a href=
|
||||
* "http://developer.android.com/training/basics/fragments/communicating.html"
|
||||
* >Communicating with Other Fragments</a> for more information.
|
||||
*/
|
||||
public interface OnLoginFragmentInteractionListener {
|
||||
void onLoginFragmentInteraction(LoginToken loginToken, boolean onlineMode);
|
||||
mActivityListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.fragments.ModulesFragment.OnModulesFragmentInteractionListener;
|
||||
import de.sebse.fuplanner.services.KVV.types.Modules;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.ui.ItemViewHolder;
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
@@ -28,7 +29,7 @@ public class ModulesFragment extends Fragment {
|
||||
private final Logger log = new Logger(this);
|
||||
private ModulesAdapter adapter;
|
||||
private SwipeRefreshLayout swipeLayout;
|
||||
private MainActivityListener mMainActivityListener;
|
||||
@Nullable private MainActivityListener mMainActivityListener;
|
||||
|
||||
/**
|
||||
* Mandatory empty constructor for the fragment manager to instantiate the
|
||||
@@ -66,12 +67,11 @@ public class ModulesFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void refresh(boolean forceRefresh) {
|
||||
if (getActivity() != null) {
|
||||
KVV kvv = ((MainActivity) getActivity()).getKVV();
|
||||
kvv.getModuleList(success -> {
|
||||
if (mMainActivityListener != null) {
|
||||
mMainActivityListener.getNewKVV().modules().list().recv(success -> {
|
||||
adapter.setModules(success);
|
||||
if (mMainActivityListener != null)
|
||||
mMainActivityListener.refreshNavigation();
|
||||
//if (mMainActivityListener != null)
|
||||
// mMainActivityListener.refreshNavigation();
|
||||
swipeLayout.setRefreshing(false);
|
||||
}, error -> {
|
||||
log.e(error.toString());
|
||||
|
||||
@@ -3,6 +3,7 @@ package de.sebse.fuplanner.services.NewKVV;
|
||||
import android.content.Context;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
@@ -39,10 +40,10 @@ public class KVVLogin extends HTTPService {
|
||||
}
|
||||
mLoginPending = true;
|
||||
doLogin(username, password, token -> {
|
||||
testLoginToken(token2 -> {
|
||||
setToken(token, true);
|
||||
testLoginToken(token, token2 -> {
|
||||
setToken(token2, true);
|
||||
mLoginPending = false;
|
||||
callback.onResponse(token);
|
||||
callback.onResponse(token2);
|
||||
}, error -> {
|
||||
mLoginPending = false;
|
||||
errorCallback.onError(error);
|
||||
@@ -53,13 +54,21 @@ public class KVVLogin extends HTTPService {
|
||||
});
|
||||
}
|
||||
|
||||
public boolean restoreOnlineLogin() {
|
||||
return restoreLogin(true);
|
||||
}
|
||||
|
||||
public boolean doOfflineLogin() {
|
||||
return restoreLogin(false);
|
||||
}
|
||||
|
||||
private boolean restoreLogin(boolean enteringOnlineMode) {
|
||||
if (mLoginPending || mToken != null)
|
||||
return false;
|
||||
mLoginPending = true;
|
||||
boolean result = false;
|
||||
try {
|
||||
result = setToken(LoginToken.load(getContext()), false);
|
||||
result = setToken(LoginToken.load(getContext()), enteringOnlineMode);
|
||||
} catch (FileNotFoundException ignored) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
@@ -110,12 +119,16 @@ public class KVVLogin extends HTTPService {
|
||||
return isLoggedIn() && mOnlineMode;
|
||||
}
|
||||
|
||||
public void testLoginToken(NetworkCallback<LoginToken> callback, NetworkErrorCallback errorCallback) {
|
||||
void testLoginToken(NetworkCallback<LoginToken> callback, NetworkErrorCallback errorCallback) {
|
||||
if (mToken == null) {
|
||||
errorCallback.onError(new NetworkError(100173, -1, "Not logged in!"));
|
||||
return;
|
||||
}
|
||||
get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", mToken.getUsername()), mToken.getCookies(), response -> {
|
||||
testLoginToken(mToken, callback, errorCallback);
|
||||
}
|
||||
|
||||
private void testLoginToken(@NotNull LoginToken token, NetworkCallback<LoginToken> callback, NetworkErrorCallback errorCallback) {
|
||||
get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", token.getUsername()), token.getCookies(), response -> {
|
||||
String body = response.getParsed();
|
||||
if (body == null) {
|
||||
errorCallback.onError(new NetworkError(100172, 403, "Testing login failed!"));
|
||||
@@ -125,8 +138,8 @@ public class KVVLogin extends HTTPService {
|
||||
JSONObject json = new JSONObject(body);
|
||||
String displayName = json.getString("displayName");
|
||||
String email = json.getString("email");
|
||||
mToken.setAdditionals(displayName, email);
|
||||
callback.onResponse(mToken);
|
||||
token.setAdditionals(displayName, email);
|
||||
callback.onResponse(token);
|
||||
} catch (JSONException e) {
|
||||
errorCallback.onError(new NetworkError(100171, 403, "Cannot parse profile!"));
|
||||
}
|
||||
@@ -150,7 +163,7 @@ public class KVVLogin extends HTTPService {
|
||||
|
||||
private boolean handleCallbacks() {
|
||||
if (mToken != null) {
|
||||
mListener.handleLogin(mToken, false);
|
||||
mListener.handleLogin(mToken, mOnlineMode);
|
||||
return true;
|
||||
} else {
|
||||
mListener.handleLogout();
|
||||
@@ -169,7 +182,7 @@ public class KVVLogin extends HTTPService {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
mOnlineMode = !enteringOnlineMode;
|
||||
mOnlineMode = enteringOnlineMode;
|
||||
return handleCallbacks();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,27 +24,41 @@ import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
|
||||
import static de.sebse.fuplanner.services.NewKVV.ModulesPart.RETRY_COUNT;
|
||||
|
||||
public class KVVModulesList extends HTTPService {
|
||||
protected final KVVLogin login;
|
||||
@Nullable private Modules modules;
|
||||
private NewAsyncQueue queue = new NewAsyncQueue();
|
||||
private final KVVLogin mLogin;
|
||||
@Nullable private Modules mModules;
|
||||
private NewAsyncQueue mQueue = new NewAsyncQueue();
|
||||
|
||||
KVVModulesList(KVVLogin login, Context context) {
|
||||
super(context);
|
||||
this.login = login;
|
||||
this.mLogin = login;
|
||||
restore();
|
||||
}
|
||||
|
||||
public boolean stored() {
|
||||
return mModules != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getUsername() {
|
||||
if (mModules != null) {
|
||||
return mModules.getUsername();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void find(String moduleID, NetworkCallback<Modules.Module> moduleNetworkCallback, NetworkErrorCallback errorCallback) {
|
||||
find(moduleID, moduleNetworkCallback, errorCallback, RETRY_COUNT);
|
||||
}
|
||||
|
||||
private void find(String moduleID, NetworkCallback<Modules.Module> moduleNetworkCallback, NetworkErrorCallback errorCallback, int retries) {
|
||||
if (mModules != null && mLogin.getLoginToken() != null && mLogin.getLoginToken().isSameUser(mModules.getUsername()))
|
||||
delete();
|
||||
if (retries < 0) {
|
||||
errorCallback.onError(new NetworkError(101107, -1, "Too many retries!"));
|
||||
return;
|
||||
}
|
||||
if (this.modules != null) {
|
||||
Modules.Module module = this.modules.get(moduleID);
|
||||
if (this.mModules != null) {
|
||||
Modules.Module module = this.mModules.get(moduleID);
|
||||
if (module != null) {
|
||||
moduleNetworkCallback.onResponse(module);
|
||||
return;
|
||||
@@ -54,9 +68,9 @@ public class KVVModulesList extends HTTPService {
|
||||
}
|
||||
|
||||
void store() {
|
||||
if (this.modules != null) {
|
||||
if (this.mModules != null) {
|
||||
try {
|
||||
this.modules.save(getContext());
|
||||
this.mModules.save(getContext());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -65,7 +79,7 @@ public class KVVModulesList extends HTTPService {
|
||||
|
||||
private void restore() {
|
||||
try {
|
||||
this.modules = Modules.load(getContext());
|
||||
this.mModules = Modules.load(getContext());
|
||||
} catch (FileNotFoundException ignored) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
@@ -74,51 +88,64 @@ public class KVVModulesList extends HTTPService {
|
||||
}
|
||||
}
|
||||
|
||||
public void recv(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback) {
|
||||
recv(callback, errorCallback, false, RETRY_COUNT);
|
||||
private void delete() {
|
||||
if (this.mModules != null) {
|
||||
this.mModules.delete(getContext());
|
||||
this.mModules = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void recv(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh, final int retries) {
|
||||
queue.add(() -> {
|
||||
if (this.modules != null && !forceRefresh) {
|
||||
callback.onResponse(this.modules);
|
||||
queue.next();
|
||||
public void recv(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback) {
|
||||
recv(callback, errorCallback, false);
|
||||
}
|
||||
|
||||
public void recv(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) {
|
||||
recv(callback, errorCallback, forceRefresh, RETRY_COUNT);
|
||||
}
|
||||
|
||||
private void recv(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh, final int retries) {
|
||||
if (mModules != null && mLogin.getLoginToken() != null && mLogin.getLoginToken().isSameUser(mModules.getUsername()))
|
||||
delete();
|
||||
mQueue.add(() -> {
|
||||
if (this.mModules != null && !forceRefresh) {
|
||||
callback.onResponse(this.mModules);
|
||||
mQueue.next();
|
||||
return;
|
||||
}
|
||||
this.upgrade(success -> {
|
||||
if (this.modules == null)
|
||||
this.modules = success;
|
||||
if (this.mModules == null)
|
||||
this.mModules = success;
|
||||
else
|
||||
this.modules.updateList(success);
|
||||
callback.onResponse(this.modules);
|
||||
queue.next();
|
||||
this.mModules.updateList(success);
|
||||
callback.onResponse(this.mModules);
|
||||
mQueue.next();
|
||||
}, error -> {
|
||||
if (retries > 0 && (error.getHttpStatus() == 401 || error.getHttpStatus() == 403)) {
|
||||
login.refreshLogin(success -> {
|
||||
mLogin.refreshLogin(success -> {
|
||||
recv(callback, errorCallback, forceRefresh, retries-1);
|
||||
queue.next();
|
||||
mQueue.next();
|
||||
}, errorCallback);
|
||||
return;
|
||||
}
|
||||
errorCallback.onError(error);
|
||||
queue.next();
|
||||
mQueue.next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void upgrade(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback) {
|
||||
if (!login.isInOnlineMode()) {
|
||||
if (!mLogin.isInOnlineMode()) {
|
||||
errorCallback.onError(new NetworkError(101105, 500, "Currently running in offline mode!"));
|
||||
return;
|
||||
}
|
||||
// https://file.io/71sa2V
|
||||
get("https://kvv.imp.fu-berlin.de/direct/site.json", login.getLoginToken().getCookies(), response -> {
|
||||
get("https://kvv.imp.fu-berlin.de/direct/site.json", mLogin.getLoginToken().getCookies(), response -> {
|
||||
String body = response.getParsed();
|
||||
if (body == null) {
|
||||
errorCallback.onError(new NetworkError(101101, 403, "No module list retrieved!"));
|
||||
return;
|
||||
}
|
||||
Modules modules = new Modules(login.getLoginToken());
|
||||
Modules modules = new Modules(mLogin.getLoginToken().getUsername());
|
||||
try {
|
||||
JSONObject json = new JSONObject(body);
|
||||
JSONArray sites = json.getJSONArray("site_collection");
|
||||
@@ -153,7 +180,7 @@ public class KVVModulesList extends HTTPService {
|
||||
}
|
||||
// Empty module *may be* because token is invalid -> check
|
||||
if (modules.size() == 0)
|
||||
login.testLoginToken(token -> callback.onResponse(modules), errorCallback);
|
||||
mLogin.testLoginToken(token -> callback.onResponse(modules), errorCallback);
|
||||
else
|
||||
callback.onResponse(modules);
|
||||
}, error -> errorCallback.onError(new NetworkError(101104, error.networkResponse.statusCode, "Cannot get module list!")));
|
||||
|
||||
@@ -98,8 +98,8 @@ public class LoginToken implements Serializable {
|
||||
return cookies;
|
||||
}
|
||||
|
||||
public boolean isSameUser(LoginToken token) {
|
||||
return token != null && this.getUsername().equals(token.getUsername());
|
||||
public boolean isSameUser(String username) {
|
||||
return this.getUsername().equals(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,12 +21,12 @@ import androidx.annotation.Nullable;
|
||||
|
||||
public class Modules implements Iterable<Modules.Module>, Serializable {
|
||||
private SortedListModule list;
|
||||
private final LoginToken token;
|
||||
private final String mUsername;
|
||||
//private transient Logger log = new Logger(this);
|
||||
private static final String FILE_NAME = "ModuleListSaveFile";
|
||||
|
||||
public Modules(LoginToken loginToken) {
|
||||
this.token = loginToken;
|
||||
public Modules(String username) {
|
||||
this.mUsername = username;
|
||||
this.list = new SortedListModule();
|
||||
}
|
||||
|
||||
@@ -84,8 +84,8 @@ public class Modules implements Iterable<Modules.Module>, Serializable {
|
||||
context.deleteFile(FILE_NAME);
|
||||
}
|
||||
|
||||
public LoginToken getToken() {
|
||||
return token;
|
||||
public String getUsername() {
|
||||
return mUsername;
|
||||
}
|
||||
|
||||
public void updateList(Modules modules) {
|
||||
|
||||
@@ -17,6 +17,8 @@ public interface MainActivityListener {
|
||||
|
||||
KVV getKVV();
|
||||
|
||||
de.sebse.fuplanner.services.NewKVV.KVV getNewKVV();
|
||||
|
||||
GoogleAuth getGoogleAuth();
|
||||
|
||||
void loginTokenInvalid(boolean doLoginCheck);
|
||||
|
||||
Reference in New Issue
Block a user