X-Git-Url: https://git.ktnx.net/?p=mobile-ledger.git;a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fnet%2Fktnx%2Fmobileledger%2Fui%2Fprofiles%2FProfileDetailFragment.java;h=0843dc29eb56ba145e46a7a93bb1b34348a33af3;hp=59f27a7906798d7bae098eb68ba9cf0f5ab1bb9f;hb=0fc2ddc465cd9b9314ae336e69535020a96a7fbc;hpb=8d69552b756ba44e254251edf08206f8866c639b diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/profiles/ProfileDetailFragment.java b/app/src/main/java/net/ktnx/mobileledger/ui/profiles/ProfileDetailFragment.java index 59f27a79..0843dc29 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/profiles/ProfileDetailFragment.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/profiles/ProfileDetailFragment.java @@ -18,22 +18,18 @@ package net.ktnx.mobileledger.ui.profiles; import android.app.Activity; -import android.content.Context; -import android.graphics.drawable.ColorDrawable; +import android.app.AlertDialog; +import android.content.DialogInterface; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; -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.AdapterView; -import android.widget.ArrayAdapter; import android.widget.LinearLayout; -import android.widget.Spinner; import android.widget.Switch; import android.widget.TextView; @@ -41,25 +37,32 @@ import com.google.android.material.appbar.CollapsingToolbarLayout; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.textfield.TextInputLayout; +import net.ktnx.mobileledger.BuildConfig; import net.ktnx.mobileledger.R; import net.ktnx.mobileledger.model.Data; import net.ktnx.mobileledger.model.MobileLedgerProfile; +import net.ktnx.mobileledger.ui.HueRingDialog; import net.ktnx.mobileledger.ui.activity.ProfileDetailActivity; import net.ktnx.mobileledger.utils.Colors; -import java.util.List; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Objects; -import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; + +import static net.ktnx.mobileledger.utils.Logger.debug; /** * A fragment representing a single Profile detail screen. - * a {@link ProfileDetailActivity} + * a {@link ProfileDetailActivity} * on handsets. */ -public class ProfileDetailFragment extends Fragment { +public class ProfileDetailFragment extends Fragment implements HueRingDialog.HueSelectedListener { /** * The fragment argument representing the item ID that this fragment * represents. @@ -81,8 +84,9 @@ public class ProfileDetailFragment extends Fragment { private TextInputLayout passwordLayout; private TextView profileName; private TextInputLayout profileNameLayout; - private FloatingActionButton fab; - private Spinner colorSpinner; + private TextView preferredAccountsFilter; + private TextInputLayout preferredAccountsFilterLayout; + private View huePickerView; /** * Mandatory empty constructor for the fragment manager to instantiate the @@ -91,22 +95,58 @@ public class ProfileDetailFragment extends Fragment { public ProfileDetailFragment() { } @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - Log.d("profiles", "[fragment] Creating profile details options menu"); + public void onCreateOptionsMenu(@NotNull Menu menu, @NotNull MenuInflater inflater) { + debug("profiles", "[fragment] Creating profile details options menu"); super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.profile_details, menu); final MenuItem menuDeleteProfile = menu.findItem(R.id.menuDelete); menuDeleteProfile.setOnMenuItemClickListener(item -> { - Log.d("profiles", String.format("[fragment] removing profile %s", mProfile.getUuid())); - mProfile.removeFromDB(); - Data.profiles.remove(mProfile); - if (Data.profile.get().equals(mProfile)) { - Log.d("profiles", "[fragment] setting current profile to 0"); - Data.setCurrentProfile(Data.profiles.get(0)); - } + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(mProfile.getName()); + builder.setMessage(R.string.remove_profile_dialog_message); + builder.setPositiveButton(R.string.Remove, (dialog, which) -> { + debug("profiles", + String.format("[fragment] removing profile %s", mProfile.getUuid())); + mProfile.removeFromDB(); + ArrayList oldList = Data.profiles.getValue(); + assert oldList != null; + ArrayList newList = + (ArrayList) oldList.clone(); + newList.remove(mProfile); + Data.profiles.setValue(newList); + if (mProfile.equals(Data.profile.getValue())) { + debug("profiles", "[fragment] setting current profile to 0"); + Data.setCurrentProfile(newList.get(0)); + final FragmentActivity activity = getActivity(); + if (activity != null) activity.finish(); + } + }); + builder.show(); return false; }); - menuDeleteProfile.setVisible((mProfile != null) && (Data.profiles.size() > 1)); + final ArrayList profiles = Data.profiles.getValue(); + menuDeleteProfile + .setVisible((mProfile != null) && (profiles != null) && (profiles.size() > 1)); + + if (BuildConfig.DEBUG) { + final MenuItem menuWipeProfileData = menu.findItem(R.id.menuWipeData); + menuWipeProfileData.setOnMenuItemClickListener(ignored -> onWipeDataMenuClicked()); + menuWipeProfileData.setVisible(mProfile != null); + } + } + private boolean onWipeDataMenuClicked() { + // this is a development option, so no confirmation + mProfile.wipeAllData(); + if (mProfile.equals(Data.profile.getValue())) triggerProfileChange(); + return true; + } + private void triggerProfileChange() { + int index = Data.getProfileIndex(mProfile); + MobileLedgerProfile newProfile = new MobileLedgerProfile(mProfile); + final ArrayList profiles = Data.profiles.getValue(); + assert profiles != null; + profiles.set(index, newProfile); + if (mProfile.equals(Data.profile.getValue())) Data.profile.setValue(newProfile); } @Override public void onCreate(Bundle savedInstanceState) { @@ -114,7 +154,9 @@ public class ProfileDetailFragment extends Fragment { if ((getArguments() != null) && getArguments().containsKey(ARG_ITEM_ID)) { int index = getArguments().getInt(ARG_ITEM_ID, -1); - if (index != -1) mProfile = Data.profiles.get(index); + ArrayList profiles = Data.profiles.getValue(); + if ((profiles != null) && (index != -1) && (index < profiles.size())) + mProfile = profiles.get(index); Activity activity = this.getActivity(); if (activity == null) throw new AssertionError(); @@ -131,48 +173,49 @@ public class ProfileDetailFragment extends Fragment { Activity context = getActivity(); if (context == null) return; - fab = context.findViewById(R.id.fab); - fab.setOnClickListener(v -> { - if (!checkValidity()) return; + FloatingActionButton fab = context.findViewById(R.id.fab); + fab.setOnClickListener(v -> onSaveFabClicked()); - if (mProfile != null) { - mProfile.setName(profileName.getText()); - mProfile.setUrl(url.getText()); - mProfile.setPostingPermitted(postingPermitted.isChecked()); - mProfile.setAuthEnabled(useAuthentication.isChecked()); - mProfile.setAuthUserName(userName.getText()); - mProfile.setAuthPassword(password.getText()); - mProfile.setThemeId(colorSpinner.getSelectedItem()); -// Log.d("profiles", String.format("Selected item is %d", mProfile.getThemeId())); - mProfile.storeInDB(); - Log.d("profiles", "profile stored in DB"); - Data.profiles.triggerItemChangedNotification(mProfile); - - - if (mProfile.getUuid().equals(Data.profile.get().getUuid())) { - // dummy update to notify the observers of the possibly new name/URL - Data.profile.set(mProfile); - } - } - else { - mProfile = - new MobileLedgerProfile(profileName.getText(), postingPermitted.isChecked(), - url.getText(), useAuthentication.isChecked(), userName.getText(), - password.getText(), - Integer.valueOf((String) colorSpinner.getSelectedItem())); - mProfile.storeInDB(); - Data.profiles.add(mProfile); - MobileLedgerProfile.storeProfilesOrder(); - - // first profile ever? - if (Data.profiles.getList().size() == 1) Data.profile.set(mProfile); - } + profileName.requestFocus(); + } + private void onSaveFabClicked() { + if (!checkValidity()) return; - Activity activity = getActivity(); - if (activity != null) activity.finish(); - }); + if (mProfile != null) { + updateProfileFromUI(); +// debug("profiles", String.format("Selected item is %d", mProfile.getThemeId())); + mProfile.storeInDB(); + debug("profiles", "profile stored in DB"); + triggerProfileChange(); + } + else { + mProfile = new MobileLedgerProfile(); + updateProfileFromUI(); + mProfile.storeInDB(); + final ArrayList profiles = Data.profiles.getValue(); + assert profiles != null; + ArrayList newList = + (ArrayList) profiles.clone(); + newList.add(mProfile); + Data.profiles.setValue(newList); + MobileLedgerProfile.storeProfilesOrder(); + + // first profile ever? + if (newList.size() == 1) Data.profile.setValue(mProfile); + } - profileName.requestFocus(); + Activity activity = getActivity(); + if (activity != null) activity.finish(); + } + private void updateProfileFromUI() { + mProfile.setName(profileName.getText()); + mProfile.setUrl(url.getText()); + mProfile.setPostingPermitted(postingPermitted.isChecked()); + mProfile.setPreferredAccountsFilter(preferredAccountsFilter.getText()); + mProfile.setAuthEnabled(useAuthentication.isChecked()); + mProfile.setAuthUserName(userName.getText()); + mProfile.setAuthPassword(password.getText()); + mProfile.setThemeId(huePickerView.getTag()); } @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, @@ -190,53 +233,27 @@ public class ProfileDetailFragment extends Fragment { userNameLayout = rootView.findViewById(R.id.auth_user_name_layout); password = rootView.findViewById(R.id.password); passwordLayout = rootView.findViewById(R.id.password_layout); - colorSpinner = rootView.findViewById(R.id.colorSpinner); - - ColorListAdapter adapter = - new ColorListAdapter(rootView.getContext(), R.layout.color_selector_item); - adapter.add(-1); - for (int i = 0; i < 360; i += 15) adapter.add(i); - Log.d("profiles", String.format("color count: %s", adapter.getCount())); -// adapter.setDropDownViewResource(R.layout.color_selector_item); - colorSpinner.setAdapter(adapter); - colorSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onNothingSelected(AdapterView parent) { - - } - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - final int primaryColor; - final int degrees = (Integer) parent.getAdapter().getItem(position); - if (degrees < 0) { - primaryColor = Colors.getPrimaryColorForHue(Colors.DEFAULT_HUE_DEG); - } - else primaryColor = Colors.getPrimaryColorForHue(degrees); - - if (colorSpinner != null) { - colorSpinner.setBackgroundColor(primaryColor); -// for (int i = 0; i < colorSpinner.getChildCount(); i++) { -// View v = colorSpinner.getChildAt(i); -// -// if (v instanceof TextView) { -// ((TextView) v).setTextColor(Color.TRANSPARENT); -// } -// } - } - } - }); + huePickerView = rootView.findViewById(R.id.btn_pick_ring_color); + preferredAccountsFilter = rootView.findViewById(R.id.preferred_accounts_filter_filter); + preferredAccountsFilterLayout = + rootView.findViewById(R.id.preferred_accounts_accounts_filter_layout); useAuthentication.setOnCheckedChangeListener((buttonView, isChecked) -> { - Log.d("profiles", isChecked ? "auth enabled " : "auth disabled"); + debug("profiles", isChecked ? "auth enabled " : "auth disabled"); authParams.setVisibility(isChecked ? View.VISIBLE : View.GONE); if (isChecked) userName.requestFocus(); }); + postingPermitted.setOnCheckedChangeListener(((buttonView, isChecked) -> { + preferredAccountsFilterLayout.setVisibility(isChecked ? View.VISIBLE : View.GONE); + })); + hookClearErrorOnFocusListener(profileName, profileNameLayout); hookClearErrorOnFocusListener(url, urlLayout); hookClearErrorOnFocusListener(userName, userNameLayout); hookClearErrorOnFocusListener(password, passwordLayout); + int profileThemeId; if (mProfile != null) { profileName.setText(mProfile.getName()); postingPermitted.setChecked(mProfile.isPostingPermitted()); @@ -245,33 +262,33 @@ public class ProfileDetailFragment extends Fragment { authParams.setVisibility(mProfile.isAuthEnabled() ? View.VISIBLE : View.GONE); userName.setText(mProfile.isAuthEnabled() ? mProfile.getAuthUserName() : ""); password.setText(mProfile.isAuthEnabled() ? mProfile.getAuthPassword() : ""); - - colorSpinner.setSelection(0); - int i = 0; - int sought = mProfile.getThemeId(); -// Log.d("profiles", String.format("Looking for %d",sought)); - while (i < adapter.getCount()) { - int item = Integer.valueOf(String.valueOf(adapter.getItem(i))); -// Log.d("profiles", String.format("Item %d is %d", i, item)); - if (item == sought) { - colorSpinner.setSelection(i); - break; - } - - i++; - } + preferredAccountsFilter.setText(mProfile.getPreferredAccountsFilter()); + profileThemeId = mProfile.getThemeId(); } else { profileName.setText(""); - url.setText(""); + url.setText("https://"); postingPermitted.setChecked(true); useAuthentication.setChecked(false); authParams.setVisibility(View.GONE); userName.setText(""); password.setText(""); - colorSpinner.setSelection(0); + preferredAccountsFilter.setText(null); + profileThemeId = -1; } + final int hue = (profileThemeId == -1) ? Colors.DEFAULT_HUE_DEG : profileThemeId; + final int profileColor = Colors.getPrimaryColorForHue(hue); + + huePickerView.setBackgroundColor(profileColor); + huePickerView.setTag(profileThemeId); + huePickerView.setOnClickListener(v -> { + HueRingDialog d = new HueRingDialog( + Objects.requireNonNull(ProfileDetailFragment.this.getContext()), + profileThemeId, (Integer) v.getTag()); + d.show(); + d.setColorSelectedListener(this); + }); return rootView; } private void hookClearErrorOnFocusListener(TextView view, TextInputLayout layout) { @@ -291,7 +308,7 @@ public class ProfileDetailFragment extends Fragment { } }); } - boolean checkValidity() { + private boolean checkValidity() { boolean valid = true; String val = String.valueOf(profileName.getText()); @@ -323,43 +340,9 @@ public class ProfileDetailFragment extends Fragment { return valid; } - private class ColorListAdapter extends ArrayAdapter { - public ColorListAdapter(@NonNull Context context, int resource) { - super(context, resource); - } - public ColorListAdapter(@NonNull Context context, int resource, int textViewResourceId) { - super(context, resource, textViewResourceId); - } - public ColorListAdapter(@NonNull Context context, int resource, - @NonNull Integer[] objects) { - super(context, resource, objects); - } - public ColorListAdapter(@NonNull Context context, int resource, int textViewResourceId, - @NonNull Integer[] objects) { - super(context, resource, textViewResourceId, objects); - } - public ColorListAdapter(@NonNull Context context, int resource, - @NonNull List objects) { - super(context, resource, objects); - } - public ColorListAdapter(@NonNull Context context, int resource, int textViewResourceId, - @NonNull List objects) { - super(context, resource, textViewResourceId, objects); - } - @Override - public @NonNull - View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { - Integer hueDeg = getItem(position); - int hue = ((hueDeg == null) || (hueDeg == -1)) ? Colors.DEFAULT_HUE_DEG : hueDeg; - @ColorInt int primaryColor = Colors.getPrimaryColorForHue(hue); - - View view = convertView; - if (convertView == null) { - view = getLayoutInflater().inflate(R.layout.color_selector_item, null); - } - - view.setBackground(new ColorDrawable(primaryColor)); - return view; - } + @Override + public void onHueSelected(int hue) { + huePickerView.setBackgroundColor(Colors.getPrimaryColorForHue(hue)); + huePickerView.setTag(hue); } }