Multi server/user implementation

This commit is contained in:
CappielloAntonio 2021-08-08 19:21:56 +02:00
parent 4e269a7446
commit 78a4006ed6
30 changed files with 959 additions and 192 deletions

View file

@ -1,44 +1,64 @@
package com.cappielloantonio.play.ui.fragment;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.cappielloantonio.play.App;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.adapter.ServerAdapter;
import com.cappielloantonio.play.databinding.FragmentLoginBinding;
import com.cappielloantonio.play.interfaces.SystemCallback;
import com.cappielloantonio.play.repository.SystemRepository;
import com.cappielloantonio.play.service.MusicPlayerRemote;
import com.cappielloantonio.play.ui.activity.MainActivity;
import com.cappielloantonio.play.util.PreferenceUtil;
import com.cappielloantonio.play.ui.fragment.dialog.ServerSignupDialog;
import com.cappielloantonio.play.viewmodel.LoginViewModel;
import java.util.Collections;
public class LoginFragment extends Fragment {
private static final String TAG = "LoginFragment";
private FragmentLoginBinding bind;
private MainActivity activity;
private LoginViewModel loginViewModel;
private String username;
private String password;
private String server;
private ServerAdapter serverAdapter;
private SystemRepository systemRepository;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.login_page_menu, menu);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
activity = (MainActivity) getActivity();
loginViewModel = new ViewModelProvider(requireActivity()).get(LoginViewModel.class);
bind = FragmentLoginBinding.inflate(inflater, container, false);
View view = bind.getRoot();
init();
initAppBar();
initServerListView();
return view;
}
@ -49,67 +69,75 @@ public class LoginFragment extends Fragment {
bind = null;
}
private void init() {
systemRepository = new SystemRepository(App.getInstance());
private void initAppBar() {
activity.setSupportActionBar(bind.toolbar);
bind.loginButton.setOnClickListener(v -> {
if (validateInput()) {
saveServerPreference(server, username, password, null, null);
authenticate();
bind.appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> {
if ((bind.serverInfoSector.getHeight() + verticalOffset) < (2 * ViewCompat.getMinimumHeight(bind.toolbar))) {
bind.toolbar.setTitle("Subsonic servers");
} else {
bind.toolbar.setTitle("");
}
});
}
private boolean validateInput() {
username = bind.usernameTextView.getText().toString().trim();
password = bind.passwordTextView.getText().toString();
server = bind.serverTextView.getText().toString().trim();
private void initServerListView() {
bind.serverListRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
bind.serverListRecyclerView.setHasFixedSize(true);
if (TextUtils.isEmpty(username)) {
Toast.makeText(requireContext(), "Empty username", Toast.LENGTH_SHORT).show();
return false;
}
if (TextUtils.isEmpty(server)) {
Toast.makeText(requireContext(), "Empty server url", Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
private void authenticate() {
systemRepository.checkUserCredential(new SystemCallback() {
@Override
public void onError(Exception exception) {
Log.e(TAG, exception.getMessage());
Toast.makeText(requireContext(), exception.getMessage(), Toast.LENGTH_LONG).show();
serverAdapter = new ServerAdapter(activity, requireContext());
bind.serverListRecyclerView.setAdapter(serverAdapter);
loginViewModel.getServerList().observe(requireActivity(), servers -> {
if(servers.size() > 0) {
if (bind != null) bind.noServerAddedTextView.setVisibility(View.GONE);
if (bind != null) bind.serverListRecyclerView.setVisibility(View.VISIBLE);
serverAdapter.setItems(servers);
}
@Override
public void onSuccess(String token, String salt) {
saveServerPreference(null, null, null, token, salt);
enter();
else {
if (bind != null) bind.noServerAddedTextView.setVisibility(View.VISIBLE);
if (bind != null) bind.serverListRecyclerView.setVisibility(View.GONE);
}
});
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT) {
int originalPosition = -1;
int fromPosition = -1;
int toPosition = -1;
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
if (originalPosition == -1)
originalPosition = viewHolder.getBindingAdapterPosition();
fromPosition = viewHolder.getBindingAdapterPosition();
toPosition = target.getBindingAdapterPosition();
Collections.swap(serverAdapter.getItems(), fromPosition, toPosition);
recyclerView.getAdapter().notifyItemMoved(fromPosition, toPosition);
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
loginViewModel.deleteServer(serverAdapter.getItem(viewHolder.getBindingAdapterPosition()));
bind.serverListRecyclerView.getAdapter().notifyItemRemoved(viewHolder.getBindingAdapterPosition());
}
}
).attachToRecyclerView(bind.serverListRecyclerView);
}
private void enter() {
activity.goFromLogin();
}
private void saveServerPreference(String server, String user, String password, String token, String salt) {
if (user != null) PreferenceUtil.getInstance(requireContext()).setUser(user);
if (server != null) PreferenceUtil.getInstance(requireContext()).setServer(server);
if (password != null) PreferenceUtil.getInstance(requireContext()).setPassword(password);
if (token != null && salt != null) {
PreferenceUtil.getInstance(requireContext()).setPassword(null);
PreferenceUtil.getInstance(requireContext()).setToken(token);
PreferenceUtil.getInstance(requireContext()).setSalt(salt);
return;
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_add:
ServerSignupDialog dialog = new ServerSignupDialog();
dialog.show(activity.getSupportFragmentManager(), null);
return true;
default:
break;
}
App.getSubsonicClientInstance(requireContext(), true);
return false;
}
}

View file

@ -6,11 +6,13 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.helper.ThemeHelper;
import com.cappielloantonio.play.ui.activity.MainActivity;
import com.cappielloantonio.play.util.PreferenceUtil;
public class SettingsFragment extends PreferenceFragmentCompat {
private static final String TAG = "SettingsFragment";
@ -36,6 +38,24 @@ public class SettingsFragment extends PreferenceFragmentCompat {
activity.setBottomNavigationBarVisibility(false);
}
@Override
public void onResume() {
super.onResume();
findPreference("logout").setOnPreferenceClickListener(preference -> {
PreferenceUtil.getInstance(requireContext()).setUser(null);
PreferenceUtil.getInstance(requireContext()).setServer(null);
PreferenceUtil.getInstance(requireContext()).setPassword(null);
PreferenceUtil.getInstance(requireContext()).setToken(null);
PreferenceUtil.getInstance(requireContext()).setSalt(null);
PreferenceUtil.getInstance(requireContext()).setServerId(null);
activity.goToLogin();
return true;
});
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.global_preferences, rootKey);

View file

@ -0,0 +1,142 @@
package com.cappielloantonio.play.ui.fragment.dialog;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.Toast;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;
import com.cappielloantonio.play.App;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.databinding.DialogServerSignupBinding;
import com.cappielloantonio.play.interfaces.SystemCallback;
import com.cappielloantonio.play.model.Server;
import com.cappielloantonio.play.repository.SystemRepository;
import com.cappielloantonio.play.ui.activity.MainActivity;
import com.cappielloantonio.play.util.PreferenceUtil;
import com.cappielloantonio.play.viewmodel.LoginViewModel;
import java.util.Objects;
import java.util.UUID;
public class ServerSignupDialog extends DialogFragment {
private static final String TAG = "ServerSignupDialog";
private DialogServerSignupBinding bind;
private MainActivity activity;
private Context context;
private LoginViewModel loginViewModel;
private SystemRepository systemRepository;
private String serverName;
private String username;
private String password;
private String server;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
activity = (MainActivity) getActivity();
context = requireContext();
loginViewModel = new ViewModelProvider(requireActivity()).get(LoginViewModel.class);
systemRepository = new SystemRepository(App.getInstance());
bind = DialogServerSignupBinding.inflate(LayoutInflater.from(requireContext()));
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(bind.getRoot())
.setTitle("Add server")
.setPositiveButton("Enter", (dialog, id) -> { })
.setNegativeButton("Cancel", (dialog, id) -> dialog.cancel());
return builder.create();
}
@Override
public void onStart() {
super.onStart();
((AlertDialog) Objects.requireNonNull(getDialog())).getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(getResources().getColor(R.color.colorAccent, null));
((AlertDialog) Objects.requireNonNull(getDialog())).getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(getResources().getColor(R.color.colorAccent, null));
((AlertDialog) Objects.requireNonNull(getDialog())).getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(v -> {
if (validateInput()) {
saveServerPreference(server, username, password, null, null);
authenticate();
((AlertDialog) Objects.requireNonNull(getDialog())).dismiss();
}
});
}
private boolean validateInput() {
serverName = bind.serverNameTextView.getText().toString().trim();
username = bind.usernameTextView.getText().toString().trim();
password = bind.passwordTextView.getText().toString();
server = bind.serverTextView.getText().toString().trim();
if (TextUtils.isEmpty(serverName)) {
bind.serverNameTextView.setError("Required");
return false;
}
if (TextUtils.isEmpty(username)) {
bind.usernameTextView.setError("Required");
return false;
}
if (TextUtils.isEmpty(server)) {
bind.serverTextView.setError("Required");
return false;
}
return true;
}
private void authenticate() {
systemRepository.checkUserCredential(new SystemCallback() {
@Override
public void onError(Exception exception) {
Log.e(TAG, exception.getMessage());
Toast.makeText(requireContext(), exception.getMessage(), Toast.LENGTH_LONG).show();
}
@Override
public void onSuccess(String token, String salt) {
saveServerPreference(null, null, null, token, salt);
enter();
}
});
}
private void enter() {
activity.goFromLogin();
}
private void saveServerPreference(String server, String user, String password, String token, String salt) {
if (user != null) PreferenceUtil.getInstance(context).setUser(user);
if (server != null) PreferenceUtil.getInstance(context).setServer(server);
if (password != null) PreferenceUtil.getInstance(context).setPassword(password);
if (token != null && salt != null) {
String serverID = UUID.randomUUID().toString();
PreferenceUtil.getInstance(context).setPassword(null);
PreferenceUtil.getInstance(context).setToken(token);
PreferenceUtil.getInstance(context).setSalt(salt);
PreferenceUtil.getInstance(context).setServerId(serverID);
loginViewModel.addServer(new Server(serverID, this.serverName, this.username, this.server, token, salt, System.currentTimeMillis()));
return;
}
App.getSubsonicClientInstance(requireContext(), true);
}
}