From 5c0f494b2cd897621a72d21c33dda007641ee922 Mon Sep 17 00:00:00 2001 From: M M Arif Date: Tue, 19 Sep 2023 22:53:36 +0500 Subject: [PATCH] Add profile repo to user profile, add ssh keys listing, new account settings screen and clean up --- app/src/main/AndroidManifest.xml | 2 +- ...java => AccountSettingsEmailActivity.java} | 43 +- .../mian/gitnex/activities/MainActivity.java | 51 +- .../gitnex/activities/ProfileActivity.java | 2 +- ...java => AccountSettingsEmailsAdapter.java} | 14 +- .../mian/gitnex/adapters/SSHKeysAdapter.java | 59 ++ .../AccountSettingsEmailsFragment.java | 104 ++++ .../fragments/AccountSettingsFragment.java | 131 +++++ .../fragments/MyProfileEmailsFragment.java | 102 ---- .../fragments/MyProfileFollowersFragment.java | 155 ------ .../fragments/MyProfileFollowingFragment.java | 157 ------ .../gitnex/fragments/MyProfileFragment.java | 177 ------ .../gitnex/fragments/SSHKeysFragment.java | 77 +++ .../fragments/profile/DetailFragment.java | 134 +++++ ...va => AccountSettingsEmailsViewModel.java} | 2 +- .../AccountSettingsSSHKeysViewModel.java | 63 +++ .../main/res/drawable/ic_account_settings.xml | 34 ++ ...ml => activity_account_settings_email.xml} | 2 +- .../res/layout/fragment_account_settings.xml | 37 ++ ...l => fragment_account_settings_emails.xml} | 0 .../fragment_account_settings_ssh_keys.xml | 47 ++ app/src/main/res/layout/fragment_profile.xml | 273 --------- .../res/layout/fragment_profile_detail.xml | 524 ++++++++++-------- ...s.xml => list_account_settings_emails.xml} | 2 +- .../layout/list_account_settings_ssh_keys.xml | 50 ++ app/src/main/res/menu/drawer_menu.xml | 4 + app/src/main/res/values/settings.xml | 2 +- app/src/main/res/values/strings.xml | 14 +- 28 files changed, 1097 insertions(+), 1165 deletions(-) rename app/src/main/java/org/mian/gitnex/activities/{MyProfileEmailActivity.java => AccountSettingsEmailActivity.java} (74%) rename app/src/main/java/org/mian/gitnex/adapters/{MyProfileEmailsAdapter.java => AccountSettingsEmailsAdapter.java} (80%) create mode 100644 app/src/main/java/org/mian/gitnex/adapters/SSHKeysAdapter.java create mode 100644 app/src/main/java/org/mian/gitnex/fragments/AccountSettingsEmailsFragment.java create mode 100644 app/src/main/java/org/mian/gitnex/fragments/AccountSettingsFragment.java delete mode 100644 app/src/main/java/org/mian/gitnex/fragments/MyProfileEmailsFragment.java delete mode 100644 app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowersFragment.java delete mode 100644 app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowingFragment.java delete mode 100644 app/src/main/java/org/mian/gitnex/fragments/MyProfileFragment.java create mode 100644 app/src/main/java/org/mian/gitnex/fragments/SSHKeysFragment.java rename app/src/main/java/org/mian/gitnex/viewmodels/{ProfileEmailsViewModel.java => AccountSettingsEmailsViewModel.java} (95%) create mode 100644 app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsSSHKeysViewModel.java create mode 100644 app/src/main/res/drawable/ic_account_settings.xml rename app/src/main/res/layout/{activity_profile_email.xml => activity_account_settings_email.xml} (98%) create mode 100644 app/src/main/res/layout/fragment_account_settings.xml rename app/src/main/res/layout/{fragment_profile_emails.xml => fragment_account_settings_emails.xml} (100%) create mode 100644 app/src/main/res/layout/fragment_account_settings_ssh_keys.xml delete mode 100644 app/src/main/res/layout/fragment_profile.xml rename app/src/main/res/layout/{list_profile_emails.xml => list_account_settings_emails.xml} (97%) create mode 100644 app/src/main/res/layout/list_account_settings_ssh_keys.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9b279027..27eafece 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -52,7 +52,7 @@ android:name=".activities.CreateNewUserActivity" android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/> processAddNewEmail(); + private ActivityAccountSettingsEmailBinding activityAccountSettingsEmailBinding; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - ActivityProfileEmailBinding activityProfileEmailBinding = - ActivityProfileEmailBinding.inflate(getLayoutInflater()); - setContentView(activityProfileEmailBinding.getRoot()); + activityAccountSettingsEmailBinding = + ActivityAccountSettingsEmailBinding.inflate(getLayoutInflater()); + setContentView(activityAccountSettingsEmailBinding.getRoot()); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - ImageView closeActivity = activityProfileEmailBinding.close; - userEmail = activityProfileEmailBinding.userEmail; - addEmailButton = activityProfileEmailBinding.addEmailButton; - - userEmail.requestFocus(); + activityAccountSettingsEmailBinding.userEmail.requestFocus(); assert imm != null; - imm.showSoftInput(userEmail, InputMethodManager.SHOW_IMPLICIT); + imm.showSoftInput( + activityAccountSettingsEmailBinding.userEmail, InputMethodManager.SHOW_IMPLICIT); initCloseListener(); - closeActivity.setOnClickListener(onClickListener); + activityAccountSettingsEmailBinding.close.setOnClickListener(onClickListener); if (!connToInternet) { disableProcessButton(); } else { - addEmailButton.setOnClickListener(addEmailListener); + activityAccountSettingsEmailBinding.addEmailButton.setOnClickListener(addEmailListener); } } @@ -73,7 +67,10 @@ public class MyProfileEmailActivity extends BaseActivity { boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); - String newUserEmail = userEmail.getText().toString().trim(); + String newUserEmail = + Objects.requireNonNull(activityAccountSettingsEmailBinding.userEmail.getText()) + .toString() + .trim(); if (!connToInternet) { @@ -115,7 +112,7 @@ public class MyProfileEmailActivity extends BaseActivity { if (response.code() == 201) { Toasty.success(ctx, getString(R.string.emailAddedText)); - MyProfileEmailsFragment.refreshEmails = true; + AccountSettingsEmailsFragment.refreshEmails = true; enableProcessButton(); finish(); } else if (response.code() == 401) { @@ -157,11 +154,11 @@ public class MyProfileEmailActivity extends BaseActivity { private void disableProcessButton() { - addEmailButton.setEnabled(false); + activityAccountSettingsEmailBinding.addEmailButton.setEnabled(false); } private void enableProcessButton() { - addEmailButton.setEnabled(true); + activityAccountSettingsEmailBinding.addEmailButton.setEnabled(true); } } diff --git a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java index b5464918..61e1b474 100644 --- a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java @@ -36,6 +36,7 @@ import org.mian.gitnex.database.api.BaseApi; import org.mian.gitnex.database.api.UserAccountsApi; import org.mian.gitnex.database.models.UserAccount; import org.mian.gitnex.databinding.ActivityMainBinding; +import org.mian.gitnex.fragments.AccountSettingsFragment; import org.mian.gitnex.fragments.AdministrationFragment; import org.mian.gitnex.fragments.BottomSheetDraftsFragment; import org.mian.gitnex.fragments.BottomSheetMyIssuesFilterFragment; @@ -44,7 +45,6 @@ import org.mian.gitnex.fragments.DraftsFragment; import org.mian.gitnex.fragments.ExploreFragment; import org.mian.gitnex.fragments.MostVisitedReposFragment; import org.mian.gitnex.fragments.MyIssuesFragment; -import org.mian.gitnex.fragments.MyProfileFragment; import org.mian.gitnex.fragments.MyRepositoriesFragment; import org.mian.gitnex.fragments.NotesFragment; import org.mian.gitnex.fragments.NotificationsFragment; @@ -85,6 +85,7 @@ public class MainActivity extends BaseActivity private BottomSheetListener profileInitListener; private FragmentRefreshListener fragmentRefreshListenerMyIssues; + private String username; @Override public void onCreate(Bundle savedInstanceState) { @@ -139,8 +140,8 @@ public class MainActivity extends BaseActivity toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore)); } else if (fragmentById instanceof NotificationsFragment) { toolbarTitle.setText(R.string.pageTitleNotifications); - } else if (fragmentById instanceof MyProfileFragment) { - toolbarTitle.setText(getResources().getString(R.string.navProfile)); + } else if (fragmentById instanceof AccountSettingsFragment) { + toolbarTitle.setText(getResources().getString(R.string.navAccount)); } else if (fragmentById instanceof MostVisitedReposFragment) { toolbarTitle.setText(getResources().getString(R.string.navMostVisited)); } else if (fragmentById instanceof NotesFragment) { @@ -241,6 +242,7 @@ public class MainActivity extends BaseActivity userFullName.setTypeface(myTypeface); if (getAccount().getUserInfo() != null) { + username = getAccount().getUserInfo().getLogin(); String userEmailNav = getAccount().getUserInfo().getEmail(); String userFullNameNav = getAccount().getFullName(); String userAvatarNav = getAccount().getUserInfo().getAvatarUrl(); @@ -270,15 +272,9 @@ public class MainActivity extends BaseActivity userAvatar.setOnClickListener( v -> { - toolbarTitle.setText( - getResources().getString(R.string.navProfile)); - getSupportFragmentManager() - .beginTransaction() - .replace( - R.id.fragment_container, - new MyProfileFragment()) - .commit(); - navigationView.setCheckedItem(R.id.nav_profile); + Intent intentProfile = new Intent(ctx, ProfileActivity.class); + intentProfile.putExtra("username", username); + ctx.startActivity(intentProfile); drawer.closeDrawers(); }); @@ -388,11 +384,9 @@ public class MainActivity extends BaseActivity return; case "profile": - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_container, new MyProfileFragment()) - .commit(); - navigationView.setCheckedItem(R.id.nav_profile); + Intent intentProfile = new Intent(ctx, ProfileActivity.class); + intentProfile.putExtra("username", username); + ctx.startActivity(intentProfile); return; case "admin": @@ -442,12 +436,12 @@ public class MainActivity extends BaseActivity break; case 4: - toolbarTitle.setText(getResources().getString(R.string.navProfile)); + toolbarTitle.setText(getResources().getString(R.string.navAccount)); getSupportFragmentManager() .beginTransaction() - .replace(R.id.fragment_container, new MyProfileFragment()) + .replace(R.id.fragment_container, new AccountSettingsFragment()) .commit(); - navigationView.setCheckedItem(R.id.nav_profile); + navigationView.setCheckedItem(R.id.nav_account_settings); break; case 5: @@ -654,11 +648,11 @@ public class MainActivity extends BaseActivity .replace(R.id.fragment_container, new OrganizationsFragment()) .commit(); } else if (id == R.id.nav_profile) { - toolbarTitle.setText(getResources().getString(R.string.navProfile)); - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_container, new MyProfileFragment()) - .commit(); + + Intent intentProfile = new Intent(ctx, ProfileActivity.class); + intentProfile.putExtra("username", username); + ctx.startActivity(intentProfile); + drawer.closeDrawers(); } else if (id == R.id.nav_repositories) { toolbarTitle.setText(getResources().getString(R.string.navRepos)); @@ -736,6 +730,13 @@ public class MainActivity extends BaseActivity .beginTransaction() .replace(R.id.fragment_container, new DashboardFragment()) .commit(); + } else if (id == R.id.nav_account_settings) { + + toolbarTitle.setText(getResources().getString(R.string.navAccount)); + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.fragment_container, new AccountSettingsFragment()) + .commit(); } drawer.closeDrawer(GravityCompat.START); diff --git a/app/src/main/java/org/mian/gitnex/activities/ProfileActivity.java b/app/src/main/java/org/mian/gitnex/activities/ProfileActivity.java index d0eaa364..e94b03f1 100644 --- a/app/src/main/java/org/mian/gitnex/activities/ProfileActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/ProfileActivity.java @@ -147,7 +147,7 @@ public class ProfileActivity extends BaseActivity implements BottomSheetListener } call.enqueue( - new Callback() { + new Callback<>() { @Override public void onResponse( diff --git a/app/src/main/java/org/mian/gitnex/adapters/MyProfileEmailsAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/AccountSettingsEmailsAdapter.java similarity index 80% rename from app/src/main/java/org/mian/gitnex/adapters/MyProfileEmailsAdapter.java rename to app/src/main/java/org/mian/gitnex/adapters/AccountSettingsEmailsAdapter.java index ccd13c0c..20de1b8f 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/MyProfileEmailsAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/AccountSettingsEmailsAdapter.java @@ -17,29 +17,29 @@ import org.mian.gitnex.R; /** * @author M M Arif */ -public class MyProfileEmailsAdapter - extends RecyclerView.Adapter { +public class AccountSettingsEmailsAdapter + extends RecyclerView.Adapter { private final List emailsList; private final Context context; - public MyProfileEmailsAdapter(Context ctx, List emailsListMain) { + public AccountSettingsEmailsAdapter(Context ctx, List emailsListMain) { this.context = ctx; this.emailsList = emailsListMain; } @NonNull @Override - public MyProfileEmailsAdapter.EmailsViewHolder onCreateViewHolder( + public AccountSettingsEmailsAdapter.EmailsViewHolder onCreateViewHolder( @NonNull ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.list_profile_emails, parent, false); - return new MyProfileEmailsAdapter.EmailsViewHolder(v); + .inflate(R.layout.list_account_settings_emails, parent, false); + return new AccountSettingsEmailsAdapter.EmailsViewHolder(v); } @Override public void onBindViewHolder( - @NonNull MyProfileEmailsAdapter.EmailsViewHolder holder, int position) { + @NonNull AccountSettingsEmailsAdapter.EmailsViewHolder holder, int position) { Email currentItem = emailsList.get(position); diff --git a/app/src/main/java/org/mian/gitnex/adapters/SSHKeysAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/SSHKeysAdapter.java new file mode 100644 index 00000000..2cc3ef1f --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/adapters/SSHKeysAdapter.java @@ -0,0 +1,59 @@ +package org.mian.gitnex.adapters; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import java.util.List; +import org.gitnex.tea4j.v2.models.PublicKey; +import org.mian.gitnex.R; + +/** + * @author M M Arif + */ +public class SSHKeysAdapter extends RecyclerView.Adapter { + + private final List keysList; + + public SSHKeysAdapter(List keysListMain) { + this.keysList = keysListMain; + } + + @NonNull @Override + public SSHKeysAdapter.KeysViewHolder onCreateViewHolder( + @NonNull ViewGroup parent, int viewType) { + View v = + LayoutInflater.from(parent.getContext()) + .inflate(R.layout.list_account_settings_ssh_keys, parent, false); + return new SSHKeysAdapter.KeysViewHolder(v); + } + + @Override + public void onBindViewHolder(@NonNull SSHKeysAdapter.KeysViewHolder holder, int position) { + + PublicKey currentItem = keysList.get(position); + + holder.keyName.setText(currentItem.getTitle()); + holder.key.setText(currentItem.getKey()); + } + + @Override + public int getItemCount() { + return keysList.size(); + } + + static class KeysViewHolder extends RecyclerView.ViewHolder { + + private final TextView keyName; + private final TextView key; + + private KeysViewHolder(View itemView) { + super(itemView); + + keyName = itemView.findViewById(R.id.keyName); + key = itemView.findViewById(R.id.key); + } + } +} diff --git a/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsEmailsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsEmailsFragment.java new file mode 100644 index 00000000..66599551 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsEmailsFragment.java @@ -0,0 +1,104 @@ +package org.mian.gitnex.fragments; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import org.mian.gitnex.activities.AccountSettingsEmailActivity; +import org.mian.gitnex.adapters.AccountSettingsEmailsAdapter; +import org.mian.gitnex.databinding.FragmentAccountSettingsEmailsBinding; +import org.mian.gitnex.viewmodels.AccountSettingsEmailsViewModel; + +/** + * @author M M Arif + */ +public class AccountSettingsEmailsFragment extends Fragment { + + public static boolean refreshEmails = false; + private AccountSettingsEmailsViewModel accountSettingsEmailsViewModel; + private AccountSettingsEmailsAdapter adapter; + + public AccountSettingsEmailsFragment() {} + + private FragmentAccountSettingsEmailsBinding fragmentAccountSettingsEmailsBinding; + + @Override + public View onCreateView( + @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + + fragmentAccountSettingsEmailsBinding = + FragmentAccountSettingsEmailsBinding.inflate(inflater, container, false); + accountSettingsEmailsViewModel = + new ViewModelProvider(this).get(AccountSettingsEmailsViewModel.class); + + final SwipeRefreshLayout swipeRefresh = fragmentAccountSettingsEmailsBinding.pullToRefresh; + + fragmentAccountSettingsEmailsBinding.recyclerView.setHasFixedSize(true); + fragmentAccountSettingsEmailsBinding.recyclerView.setLayoutManager( + new LinearLayoutManager(getContext())); + + swipeRefresh.setOnRefreshListener( + () -> + new Handler(Looper.getMainLooper()) + .postDelayed( + () -> { + swipeRefresh.setRefreshing(false); + accountSettingsEmailsViewModel.loadEmailsList( + getContext()); + }, + 200)); + + fetchDataAsync(); + + fragmentAccountSettingsEmailsBinding.addNewEmailAddress.setOnClickListener( + v1 -> startActivity(new Intent(getContext(), AccountSettingsEmailActivity.class))); + + return fragmentAccountSettingsEmailsBinding.getRoot(); + } + + @SuppressLint("NotifyDataSetChanged") + private void fetchDataAsync() { + + accountSettingsEmailsViewModel + .getEmailsList(getContext()) + .observe( + getViewLifecycleOwner(), + emailsListMain -> { + adapter = + new AccountSettingsEmailsAdapter(getContext(), emailsListMain); + if (adapter.getItemCount() > 0) { + fragmentAccountSettingsEmailsBinding.recyclerView.setAdapter( + adapter); + fragmentAccountSettingsEmailsBinding.noDataEmails.setVisibility( + View.GONE); + } else { + adapter.notifyDataSetChanged(); + fragmentAccountSettingsEmailsBinding.recyclerView.setAdapter( + adapter); + fragmentAccountSettingsEmailsBinding.noDataEmails.setVisibility( + View.VISIBLE); + } + fragmentAccountSettingsEmailsBinding.progressBar.setVisibility( + View.GONE); + }); + } + + @Override + public void onResume() { + super.onResume(); + + if (refreshEmails) { + accountSettingsEmailsViewModel.loadEmailsList(getContext()); + refreshEmails = false; + } + } +} diff --git a/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsFragment.java new file mode 100644 index 00000000..d23d1f16 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsFragment.java @@ -0,0 +1,131 @@ +package org.mian.gitnex.fragments; + +import android.content.Context; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.viewpager2.adapter.FragmentStateAdapter; +import androidx.viewpager2.widget.ViewPager2; +import com.google.android.material.tabs.TabLayout; +import com.google.android.material.tabs.TabLayoutMediator; +import org.mian.gitnex.R; +import org.mian.gitnex.activities.BaseActivity; +import org.mian.gitnex.activities.MainActivity; +import org.mian.gitnex.helpers.AppUtil; +import org.mian.gitnex.helpers.contexts.AccountContext; + +/** + * @author M M Arif + */ +public class AccountSettingsFragment extends Fragment { + + public ViewPager2 viewPager; + private Context ctx; + private View view; + private Typeface myTypeface; + + @Nullable @Override + public View onCreateView( + @NonNull LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + + ctx = getContext(); + + view = inflater.inflate(R.layout.fragment_account_settings, container, false); + setHasOptionsMenu(false); + + ((MainActivity) requireActivity()) + .setActionBarTitle(getResources().getString(R.string.navAccount)); + + myTypeface = AppUtil.getTypeface(ctx); + + AccountContext account = ((BaseActivity) requireActivity()).getAccount(); + if (account.getUserInfo() != null) { + viewData(); + } else { + ((MainActivity) requireActivity()) + .setProfileInitListener( + (text) -> { + viewData(); + }); + } + + return view; + } + + public void viewData() { + + TabLayout tabLayout = view.findViewById(R.id.tabs); + + if (viewPager == null) { + + viewPager = view.findViewById(R.id.accountSettingsContainer); + viewPager.setOffscreenPageLimit(1); + + viewPager.setAdapter(new ViewPagerAdapter(this)); + + String[] tabTitles = { + ctx.getResources().getString(R.string.accountEmails), + ctx.getResources().getString(R.string.sshKeys) + }; + new TabLayoutMediator( + tabLayout, + viewPager, + (tab, position) -> tab.setText(tabTitles[position])) + .attach(); + + ViewGroup viewGroup = (ViewGroup) tabLayout.getChildAt(0); + int tabsCount_ = viewGroup.getChildCount(); + + for (int j = 0; j < tabsCount_; j++) { + + ViewGroup vgTab = (ViewGroup) viewGroup.getChildAt(j); + int tabChildCount = vgTab.getChildCount(); + + for (int i = 0; i < tabChildCount; i++) { + + View tabViewChild = vgTab.getChildAt(i); + + if (tabViewChild instanceof TextView) { + + ((TextView) tabViewChild).setTypeface(myTypeface); + } + } + } + } + } + + public static class ViewPagerAdapter extends FragmentStateAdapter { + + public ViewPagerAdapter(@NonNull Fragment fa) { + super(fa); + } + + @NonNull @Override + public Fragment createFragment(int position) { + + Fragment fragment = null; + + switch (position) { + case 0: // Emails + return new AccountSettingsEmailsFragment(); + case 1: // SSH keys + return new SSHKeysFragment(); + } + assert false; + return fragment; + } + + @Override + public int getItemCount() { + return 2; + } + } +} diff --git a/app/src/main/java/org/mian/gitnex/fragments/MyProfileEmailsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/MyProfileEmailsFragment.java deleted file mode 100644 index 18797f9f..00000000 --- a/app/src/main/java/org/mian/gitnex/fragments/MyProfileEmailsFragment.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.mian.gitnex.fragments; - -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ProgressBar; -import android.widget.TextView; -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProvider; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -import org.mian.gitnex.activities.MyProfileEmailActivity; -import org.mian.gitnex.adapters.MyProfileEmailsAdapter; -import org.mian.gitnex.databinding.FragmentProfileEmailsBinding; -import org.mian.gitnex.viewmodels.ProfileEmailsViewModel; - -/** - * @author M M Arif - */ -public class MyProfileEmailsFragment extends Fragment { - - public static boolean refreshEmails = false; - private ProfileEmailsViewModel profileEmailsViewModel; - private ProgressBar mProgressBar; - private MyProfileEmailsAdapter adapter; - private RecyclerView mRecyclerView; - private TextView noDataEmails; - - public MyProfileEmailsFragment() {} - - @Override - public View onCreateView( - @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - - FragmentProfileEmailsBinding fragmentProfileEmailsBinding = - FragmentProfileEmailsBinding.inflate(inflater, container, false); - profileEmailsViewModel = new ViewModelProvider(this).get(ProfileEmailsViewModel.class); - - final SwipeRefreshLayout swipeRefresh = fragmentProfileEmailsBinding.pullToRefresh; - - noDataEmails = fragmentProfileEmailsBinding.noDataEmails; - mRecyclerView = fragmentProfileEmailsBinding.recyclerView; - - mRecyclerView.setHasFixedSize(true); - mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); - - mProgressBar = fragmentProfileEmailsBinding.progressBar; - - swipeRefresh.setOnRefreshListener( - () -> - new Handler(Looper.getMainLooper()) - .postDelayed( - () -> { - swipeRefresh.setRefreshing(false); - profileEmailsViewModel.loadEmailsList(getContext()); - }, - 200)); - - fetchDataAsync(); - - fragmentProfileEmailsBinding.addNewEmailAddress.setOnClickListener( - v1 -> startActivity(new Intent(getContext(), MyProfileEmailActivity.class))); - - return fragmentProfileEmailsBinding.getRoot(); - } - - private void fetchDataAsync() { - - profileEmailsViewModel - .getEmailsList(getContext()) - .observe( - getViewLifecycleOwner(), - emailsListMain -> { - adapter = new MyProfileEmailsAdapter(getContext(), emailsListMain); - if (adapter.getItemCount() > 0) { - mRecyclerView.setAdapter(adapter); - noDataEmails.setVisibility(View.GONE); - } else { - adapter.notifyDataSetChanged(); - mRecyclerView.setAdapter(adapter); - noDataEmails.setVisibility(View.VISIBLE); - } - mProgressBar.setVisibility(View.GONE); - }); - } - - @Override - public void onResume() { - super.onResume(); - - if (refreshEmails) { - profileEmailsViewModel.loadEmailsList(getContext()); - refreshEmails = false; - } - } -} diff --git a/app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowersFragment.java b/app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowersFragment.java deleted file mode 100644 index 31586d2e..00000000 --- a/app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowersFragment.java +++ /dev/null @@ -1,155 +0,0 @@ -package org.mian.gitnex.fragments; - -import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.recyclerview.widget.LinearLayoutManager; -import java.util.ArrayList; -import java.util.List; -import org.gitnex.tea4j.v2.models.User; -import org.mian.gitnex.R; -import org.mian.gitnex.adapters.UsersAdapter; -import org.mian.gitnex.clients.RetrofitClient; -import org.mian.gitnex.databinding.FragmentProfileFollowersFollowingBinding; -import org.mian.gitnex.helpers.Constants; -import org.mian.gitnex.helpers.SnackBar; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; - -/** - * @author M M Arif - */ -public class MyProfileFollowersFragment extends Fragment { - - private final String TAG = "MyProfileFollowersFragment"; - private FragmentProfileFollowersFollowingBinding viewBinding; - private Context context; - private List dataList; - private UsersAdapter adapter; - private int pageSize; - private int resultLimit; - - @Override - public View onCreateView( - @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - - viewBinding = FragmentProfileFollowersFollowingBinding.inflate(inflater, container, false); - context = getContext(); - - dataList = new ArrayList<>(); - adapter = new UsersAdapter(dataList, context); - resultLimit = Constants.getCurrentResultLimit(context); - - viewBinding.pullToRefresh.setOnRefreshListener( - () -> - new Handler(Looper.getMainLooper()) - .postDelayed( - () -> { - viewBinding.pullToRefresh.setRefreshing(false); - loadInitial(resultLimit); - adapter.notifyDataChanged(); - }, - 200)); - - adapter.setLoadMoreListener( - () -> - viewBinding.recyclerView.post( - () -> { - if (dataList.size() == resultLimit || pageSize == resultLimit) { - int page = (dataList.size() + resultLimit) / resultLimit; - loadMore(resultLimit, page); - } - })); - - viewBinding.recyclerView.setHasFixedSize(true); - viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context)); - viewBinding.recyclerView.setAdapter(adapter); - - loadInitial(resultLimit); - - return viewBinding.getRoot(); - } - - private void loadInitial(int resultLimit) { - - Call> call = - RetrofitClient.getApiInterface(context).userCurrentListFollowers(1, resultLimit); - call.enqueue( - new Callback>() { - @Override - public void onResponse( - @NonNull Call> call, - @NonNull Response> response) { - if (response.isSuccessful()) { - if (response.body() != null && response.body().size() > 0) { - dataList.clear(); - dataList.addAll(response.body()); - adapter.notifyDataChanged(); - viewBinding.noData.setVisibility(View.GONE); - } else { - dataList.clear(); - adapter.notifyDataChanged(); - viewBinding.noData.setVisibility(View.VISIBLE); - } - viewBinding.progressBar.setVisibility(View.GONE); - } else if (response.code() == 404) { - viewBinding.noData.setVisibility(View.VISIBLE); - viewBinding.progressBar.setVisibility(View.GONE); - } else { - Log.e(TAG, String.valueOf(response.code())); - } - } - - @Override - public void onFailure(@NonNull Call> call, @NonNull Throwable t) { - Log.e(TAG, t.toString()); - } - }); - } - - private void loadMore(int resultLimit, int page) { - - viewBinding.progressBar.setVisibility(View.VISIBLE); - Call> call = - RetrofitClient.getApiInterface(context).userCurrentListFollowers(page, resultLimit); - call.enqueue( - new Callback>() { - @Override - public void onResponse( - @NonNull Call> call, - @NonNull Response> response) { - if (response.isSuccessful()) { - assert response.body() != null; - List result = response.body(); - if (result.size() > 0) { - pageSize = result.size(); - dataList.addAll(result); - } else { - SnackBar.info( - context, - viewBinding.getRoot(), - getString(R.string.noMoreData)); - adapter.setMoreDataAvailable(false); - } - adapter.notifyDataChanged(); - viewBinding.progressBar.setVisibility(View.GONE); - } else { - Log.e(TAG, String.valueOf(response.code())); - } - } - - @Override - public void onFailure(@NonNull Call> call, @NonNull Throwable t) { - Log.e(TAG, t.toString()); - } - }); - } -} diff --git a/app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowingFragment.java b/app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowingFragment.java deleted file mode 100644 index 1a972c3f..00000000 --- a/app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowingFragment.java +++ /dev/null @@ -1,157 +0,0 @@ -package org.mian.gitnex.fragments; - -import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.recyclerview.widget.LinearLayoutManager; -import java.util.ArrayList; -import java.util.List; -import org.gitnex.tea4j.v2.models.User; -import org.mian.gitnex.R; -import org.mian.gitnex.adapters.UsersAdapter; -import org.mian.gitnex.clients.RetrofitClient; -import org.mian.gitnex.databinding.FragmentProfileFollowersFollowingBinding; -import org.mian.gitnex.helpers.Constants; -import org.mian.gitnex.helpers.SnackBar; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; - -/** - * @author M M Arif - */ -public class MyProfileFollowingFragment extends Fragment { - - private final String TAG = "MyProfileFollowingFragment"; - private FragmentProfileFollowersFollowingBinding viewBinding; - private Context context; - private List dataList; - private UsersAdapter adapter; - private int pageSize; - private int resultLimit; - - @Override - public View onCreateView( - @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - - viewBinding = FragmentProfileFollowersFollowingBinding.inflate(inflater, container, false); - context = getContext(); - - dataList = new ArrayList<>(); - adapter = new UsersAdapter(dataList, context); - resultLimit = Constants.getCurrentResultLimit(context); - - viewBinding.pullToRefresh.setOnRefreshListener( - () -> - new Handler(Looper.getMainLooper()) - .postDelayed( - () -> { - viewBinding.pullToRefresh.setRefreshing(false); - loadInitial(resultLimit); - adapter.notifyDataChanged(); - }, - 200)); - - adapter.setLoadMoreListener( - () -> - viewBinding.recyclerView.post( - () -> { - if (dataList.size() == resultLimit || pageSize == resultLimit) { - int page = (dataList.size() + resultLimit) / resultLimit; - loadMore(resultLimit, page); - } - })); - - viewBinding.recyclerView.setHasFixedSize(true); - viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context)); - viewBinding.recyclerView.setAdapter(adapter); - - loadInitial(resultLimit); - - return viewBinding.getRoot(); - } - - private void loadInitial(int resultLimit) { - - Call> call = - RetrofitClient.getApiInterface(context).userCurrentListFollowing(1, resultLimit); - call.enqueue( - new Callback>() { - - @Override - public void onResponse( - @NonNull Call> call, - @NonNull Response> response) { - if (response.isSuccessful()) { - if (response.body() != null && response.body().size() > 0) { - dataList.clear(); - dataList.addAll(response.body()); - adapter.notifyDataChanged(); - viewBinding.noData.setVisibility(View.GONE); - } else { - dataList.clear(); - adapter.notifyDataChanged(); - viewBinding.noData.setVisibility(View.VISIBLE); - } - viewBinding.progressBar.setVisibility(View.GONE); - } else if (response.code() == 404) { - viewBinding.noData.setVisibility(View.VISIBLE); - viewBinding.progressBar.setVisibility(View.GONE); - } else { - Log.e(TAG, String.valueOf(response.code())); - } - } - - @Override - public void onFailure(@NonNull Call> call, @NonNull Throwable t) { - Log.e(TAG, t.toString()); - } - }); - } - - private void loadMore(int resultLimit, int page) { - - viewBinding.progressBar.setVisibility(View.VISIBLE); - Call> call = - RetrofitClient.getApiInterface(context).userCurrentListFollowing(page, resultLimit); - call.enqueue( - new Callback>() { - - @Override - public void onResponse( - @NonNull Call> call, - @NonNull Response> response) { - if (response.isSuccessful()) { - assert response.body() != null; - List result = response.body(); - if (result.size() > 0) { - pageSize = result.size(); - dataList.addAll(result); - } else { - SnackBar.info( - context, - viewBinding.getRoot(), - getString(R.string.noMoreData)); - adapter.setMoreDataAvailable(false); - } - adapter.notifyDataChanged(); - viewBinding.progressBar.setVisibility(View.GONE); - } else { - Log.e(TAG, String.valueOf(response.code())); - } - } - - @Override - public void onFailure(@NonNull Call> call, @NonNull Throwable t) { - Log.e(TAG, t.toString()); - } - }); - } -} diff --git a/app/src/main/java/org/mian/gitnex/fragments/MyProfileFragment.java b/app/src/main/java/org/mian/gitnex/fragments/MyProfileFragment.java deleted file mode 100644 index 83042f36..00000000 --- a/app/src/main/java/org/mian/gitnex/fragments/MyProfileFragment.java +++ /dev/null @@ -1,177 +0,0 @@ -package org.mian.gitnex.fragments; - -import android.content.Context; -import android.graphics.Typeface; -import android.os.Bundle; -import android.text.Html; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentStatePagerAdapter; -import androidx.viewpager.widget.ViewPager; -import com.google.android.material.progressindicator.LinearProgressIndicator; -import com.google.android.material.tabs.TabLayout; -import java.util.Locale; -import org.mian.gitnex.R; -import org.mian.gitnex.activities.BaseActivity; -import org.mian.gitnex.activities.MainActivity; -import org.mian.gitnex.clients.PicassoService; -import org.mian.gitnex.helpers.AppUtil; -import org.mian.gitnex.helpers.RoundedTransformation; -import org.mian.gitnex.helpers.contexts.AccountContext; - -/** - * @author M M Arif - */ -public class MyProfileFragment extends Fragment { - - private Context ctx; - - @Nullable @Override - public View onCreateView( - @NonNull LayoutInflater inflater, - @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - - ctx = getContext(); - - View v = inflater.inflate(R.layout.fragment_profile, container, false); - setHasOptionsMenu(false); - - ((MainActivity) requireActivity()) - .setActionBarTitle(getResources().getString(R.string.navProfile)); - - AccountContext account = ((BaseActivity) requireActivity()).getAccount(); - if (account.getUserInfo() != null) { - viewData(v, account); - } else { - // we have to wait until loading is finished - LinearProgressIndicator loading = v.findViewById(R.id.loadingIndicator); - loading.setVisibility(View.VISIBLE); - ((MainActivity) requireActivity()) - .setProfileInitListener( - (text) -> { - loading.setVisibility(View.GONE); - viewData(v, account); - }); - } - - return v; - } - - public void viewData(View v, AccountContext account) { - - TextView userFullName = v.findViewById(R.id.userFullName); - ImageView userAvatar = v.findViewById(R.id.userAvatar); - TextView userLogin = v.findViewById(R.id.userLogin); - TextView userLanguage = v.findViewById(R.id.userLanguage); - TextView userFollowersCount = v.findViewById(R.id.user_followers_count); - TextView userFollowingCount = v.findViewById(R.id.user_following_count); - TextView userStarredReposCount = v.findViewById(R.id.user_starred_repos_count); - - String[] userLanguageCodes = - account.getUserInfo().getLanguage() != null - ? account.getUserInfo().getLanguage().split("-") - : new String[] {""}; - - if (userLanguageCodes.length >= 2) { - Locale locale = new Locale(userLanguageCodes[0], userLanguageCodes[1]); - userLanguage.setText(locale.getDisplayLanguage()); - } else { - userLanguage.setText(getResources().getConfiguration().locale.getDisplayLanguage()); - } - - userAvatar.setOnClickListener( - loginId -> - AppUtil.copyToClipboard( - ctx, - account.getAccount().getUserName(), - ctx.getString( - R.string.copyLoginIdToClipBoard, - account.getAccount().getUserName()))); - - userFullName.setText(Html.fromHtml(account.getFullName())); - userLogin.setText(getString(R.string.usernameWithAt, account.getAccount().getUserName())); - - int avatarRadius = AppUtil.getPixelsFromDensity(ctx, 60); - - PicassoService.getInstance(ctx) - .get() - .load(account.getUserInfo().getAvatarUrl()) - .transform(new RoundedTransformation(avatarRadius, 0)) - .placeholder(R.drawable.loader_animated) - .resize(120, 120) - .centerCrop() - .into(userAvatar); - - userFollowersCount.setText(String.valueOf(account.getUserInfo().getFollowersCount())); - userFollowingCount.setText(String.valueOf(account.getUserInfo().getFollowingCount())); - userStarredReposCount.setText(String.valueOf(account.getUserInfo().getStarredReposCount())); - - MyProfileFragment.SectionsPagerAdapter mSectionsPagerAdapter = - new SectionsPagerAdapter(getChildFragmentManager()); - - ViewPager mViewPager = v.findViewById(R.id.container); - mViewPager.setAdapter(mSectionsPagerAdapter); - - Typeface myTypeface = AppUtil.getTypeface(requireContext()); - TabLayout tabLayout = v.findViewById(R.id.tabs); - - ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0); - int tabsCount = vg.getChildCount(); - - for (int j = 0; j < tabsCount; j++) { - - ViewGroup vgTab = (ViewGroup) vg.getChildAt(j); - int tabChildCount = vgTab.getChildCount(); - - for (int i = 0; i < tabChildCount; i++) { - - View tabViewChild = vgTab.getChildAt(i); - - if (tabViewChild instanceof TextView) { - ((TextView) tabViewChild).setTypeface(myTypeface); - } - } - } - - mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); - tabLayout.addOnTabSelectedListener( - new TabLayout.ViewPagerOnTabSelectedListener(mViewPager)); - } - - public static class SectionsPagerAdapter extends FragmentStatePagerAdapter { - - SectionsPagerAdapter(FragmentManager fm) { - super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); - } - - @NonNull @Override - public Fragment getItem(int position) { - - switch (position) { - case 0: // followers - return new MyProfileFollowersFragment(); - - case 1: // following - return new MyProfileFollowingFragment(); - - case 2: // emails - return new MyProfileEmailsFragment(); - } - - return null; - } - - @Override - public int getCount() { - return 3; - } - } -} diff --git a/app/src/main/java/org/mian/gitnex/fragments/SSHKeysFragment.java b/app/src/main/java/org/mian/gitnex/fragments/SSHKeysFragment.java new file mode 100644 index 00000000..c061dc07 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/fragments/SSHKeysFragment.java @@ -0,0 +1,77 @@ +package org.mian.gitnex.fragments; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import org.mian.gitnex.adapters.SSHKeysAdapter; +import org.mian.gitnex.databinding.FragmentAccountSettingsSshKeysBinding; +import org.mian.gitnex.viewmodels.AccountSettingsSSHKeysViewModel; + +/** + * @author M M Arif + */ +public class SSHKeysFragment extends Fragment { + + private FragmentAccountSettingsSshKeysBinding viewBinding; + private Context context; + private SSHKeysAdapter adapter; + private AccountSettingsSSHKeysViewModel accountSettingsSSHKeysViewModel; + + @Override + public View onCreateView( + @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + + viewBinding = FragmentAccountSettingsSshKeysBinding.inflate(inflater, container, false); + context = getContext(); + + accountSettingsSSHKeysViewModel = + new ViewModelProvider(this).get(AccountSettingsSSHKeysViewModel.class); + + viewBinding.recyclerView.setHasFixedSize(true); + viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context)); + + viewBinding.pullToRefresh.setOnRefreshListener( + () -> + new Handler(Looper.getMainLooper()) + .postDelayed( + () -> { + viewBinding.pullToRefresh.setRefreshing(false); + accountSettingsSSHKeysViewModel.loadKeysList(context); + }, + 200)); + + fetchDataAsync(); + + return viewBinding.getRoot(); + } + + @SuppressLint("NotifyDataSetChanged") + private void fetchDataAsync() { + + accountSettingsSSHKeysViewModel + .getKeysList(context) + .observe( + getViewLifecycleOwner(), + keysListMain -> { + adapter = new SSHKeysAdapter(keysListMain); + if (adapter.getItemCount() > 0) { + viewBinding.recyclerView.setAdapter(adapter); + viewBinding.noData.setVisibility(View.GONE); + } else { + adapter.notifyDataSetChanged(); + viewBinding.recyclerView.setAdapter(adapter); + viewBinding.noData.setVisibility(View.VISIBLE); + } + viewBinding.progressBar.setVisibility(View.GONE); + }); + } +} diff --git a/app/src/main/java/org/mian/gitnex/fragments/profile/DetailFragment.java b/app/src/main/java/org/mian/gitnex/fragments/profile/DetailFragment.java index d037dcab..7040139c 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/profile/DetailFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/profile/DetailFragment.java @@ -7,7 +7,10 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; +import java.io.IOException; import java.util.Locale; +import okhttp3.ResponseBody; +import org.gitnex.tea4j.v2.models.Repository; import org.gitnex.tea4j.v2.models.User; import org.mian.gitnex.R; import org.mian.gitnex.clients.PicassoService; @@ -16,6 +19,7 @@ import org.mian.gitnex.databinding.FragmentProfileDetailBinding; import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.ClickListener; +import org.mian.gitnex.helpers.Markdown; import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.TimeHelper; import org.mian.gitnex.helpers.TinyDB; @@ -63,6 +67,7 @@ public class DetailFragment extends Fragment { locale = getResources().getConfiguration().locale; getProfileDetail(username); + getProfileRepository(username); return binding.getRoot(); } @@ -162,4 +167,133 @@ public class DetailFragment extends Fragment { } }); } + + public void getProfileRepository(String username) { + + Call call = + RetrofitClient.getApiInterface(context).repoGet(username, ".profile"); + + call.enqueue( + new Callback<>() { + + @Override + public void onResponse( + @NonNull Call call, + @NonNull retrofit2.Response response) { + + if (response.isSuccessful() && response.body() != null) { + + switch (response.code()) { + case 200: + String defBranch = response.body().getDefaultBranch(); + binding.profileRepoView.setVisibility(View.VISIBLE); + + Call call_profile = + RetrofitClient.getWebInterface(getContext()) + .getFileContents( + username, + ".profile", + defBranch, + "README.md"); + + call_profile.enqueue( + new Callback<>() { + + @Override + public void onResponse( + @NonNull Call call_profile, + @NonNull retrofit2.Response + response) { + + if (isAdded()) { + + switch (response.code()) { + case 200: + assert response.body() != null; + new Thread( + () -> { + try { + Markdown + .render( + context, + response.body() + .string(), + binding.profileRepoContent); + } catch ( + IOException + e) { + requireActivity() + .runOnUiThread( + () -> + Toasty + .error( + context, + context + .getString( + R + .string + .genericError))); + } + }) + .start(); + break; + + case 401: + binding.profileRepoView + .setVisibility(View.GONE); + AlertDialogs + .authorizationTokenRevokedDialog( + context); + break; + + case 403: + binding.profileRepoView + .setVisibility(View.GONE); + Toasty.error( + context, + context.getString( + R.string + .authorizeError)); + break; + + default: + break; + } + } + } + + @Override + public void onFailure( + @NonNull Call call_profile, + @NonNull Throwable t) {} + }); + + break; + + case 401: + AlertDialogs.authorizationTokenRevokedDialog(context); + binding.profileRepoView.setVisibility(View.GONE); + break; + + case 403: + binding.profileRepoView.setVisibility(View.GONE); + Toasty.error( + context, context.getString(R.string.authorizeError)); + break; + + default: + binding.profileRepoView.setVisibility(View.GONE); + Toasty.error(context, getString(R.string.genericError)); + break; + } + } + binding.progressBar.setVisibility(View.GONE); + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + binding.profileRepoView.setVisibility(View.GONE); + } + }); + } } diff --git a/app/src/main/java/org/mian/gitnex/viewmodels/ProfileEmailsViewModel.java b/app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsEmailsViewModel.java similarity index 95% rename from app/src/main/java/org/mian/gitnex/viewmodels/ProfileEmailsViewModel.java rename to app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsEmailsViewModel.java index c442025e..a0b7e00d 100644 --- a/app/src/main/java/org/mian/gitnex/viewmodels/ProfileEmailsViewModel.java +++ b/app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsEmailsViewModel.java @@ -17,7 +17,7 @@ import retrofit2.Response; /** * @author M M Arif */ -public class ProfileEmailsViewModel extends ViewModel { +public class AccountSettingsEmailsViewModel extends ViewModel { private MutableLiveData> emailsList; diff --git a/app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsSSHKeysViewModel.java b/app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsSSHKeysViewModel.java new file mode 100644 index 00000000..0ff5f8b1 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsSSHKeysViewModel.java @@ -0,0 +1,63 @@ +package org.mian.gitnex.viewmodels; + +import android.content.Context; +import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; +import java.util.List; +import org.gitnex.tea4j.v2.models.PublicKey; +import org.mian.gitnex.R; +import org.mian.gitnex.clients.RetrofitClient; +import org.mian.gitnex.helpers.Constants; +import org.mian.gitnex.helpers.Toasty; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +/** + * @author M M Arif + */ +public class AccountSettingsSSHKeysViewModel extends ViewModel { + + private MutableLiveData> keysList; + private int resultLimit; + + public LiveData> getKeysList(Context ctx) { + + keysList = new MutableLiveData<>(); + resultLimit = Constants.getCurrentResultLimit(ctx); + loadKeysList(ctx); + + return keysList; + } + + public void loadKeysList(Context ctx) { + + Call> call = + RetrofitClient.getApiInterface(ctx).userCurrentListKeys("", 1, resultLimit); + + call.enqueue( + new Callback<>() { + + @Override + public void onResponse( + @NonNull Call> call, + @NonNull Response> response) { + + if (response.isSuccessful()) { + keysList.postValue(response.body()); + } else { + Toasty.error(ctx, ctx.getString(R.string.genericError)); + } + } + + @Override + public void onFailure( + @NonNull Call> call, @NonNull Throwable t) { + + Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError)); + } + }); + } +} diff --git a/app/src/main/res/drawable/ic_account_settings.xml b/app/src/main/res/drawable/ic_account_settings.xml new file mode 100644 index 00000000..976c1618 --- /dev/null +++ b/app/src/main/res/drawable/ic_account_settings.xml @@ -0,0 +1,34 @@ + + + + + + diff --git a/app/src/main/res/layout/activity_profile_email.xml b/app/src/main/res/layout/activity_account_settings_email.xml similarity index 98% rename from app/src/main/res/layout/activity_profile_email.xml rename to app/src/main/res/layout/activity_account_settings_email.xml index d1e08692..a4b5c8dd 100644 --- a/app/src/main/res/layout/activity_profile_email.xml +++ b/app/src/main/res/layout/activity_account_settings_email.xml @@ -60,7 +60,7 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/dimen8dp" android:layout_marginBottom="@dimen/dimen8dp" - android:hint="@string/profileEmailTitle" + android:hint="@string/accountEmailTitle" android:textColorHint="?attr/hintColor" app:boxBackgroundColor="?attr/inputBackgroundColor" app:boxStrokeErrorColor="@color/darkRed" diff --git a/app/src/main/res/layout/fragment_account_settings.xml b/app/src/main/res/layout/fragment_account_settings.xml new file mode 100644 index 00000000..342b050d --- /dev/null +++ b/app/src/main/res/layout/fragment_account_settings.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_profile_emails.xml b/app/src/main/res/layout/fragment_account_settings_emails.xml similarity index 100% rename from app/src/main/res/layout/fragment_profile_emails.xml rename to app/src/main/res/layout/fragment_account_settings_emails.xml diff --git a/app/src/main/res/layout/fragment_account_settings_ssh_keys.xml b/app/src/main/res/layout/fragment_account_settings_ssh_keys.xml new file mode 100644 index 00000000..7c6ac3a6 --- /dev/null +++ b/app/src/main/res/layout/fragment_account_settings_ssh_keys.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml deleted file mode 100644 index 04d49892..00000000 --- a/app/src/main/res/layout/fragment_profile.xml +++ /dev/null @@ -1,273 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_profile_detail.xml b/app/src/main/res/layout/fragment_profile_detail.xml index 461ccd2c..f502a159 100644 --- a/app/src/main/res/layout/fragment_profile_detail.xml +++ b/app/src/main/res/layout/fragment_profile_detail.xml @@ -17,276 +17,330 @@ style="@style/Widget.Material3.LinearProgressIndicator" app:indicatorColor="?attr/progressIndicatorColor" /> - + android:layout_height="match_parent"> + android:layout_height="wrap_content"> - - - - - - - + style="?attr/materialCardViewFilledStyle" + app:cardElevation="@dimen/dimen0dp"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:orientation="horizontal" + tools:ignore="UseCompoundDrawables"> - + - + + + + + android:paddingStart="@dimen/dimen24dp" + android:paddingEnd="@dimen/dimen10dp" + android:orientation="vertical"> + + + + + + + - - - - - - + android:layout_marginTop="@dimen/dimen20dp" + android:layout_marginBottom="@dimen/dimen0dp" + android:orientation="horizontal" + android:baselineAligned="false"> - + android:layout_weight="1" + android:gravity="center" + android:orientation="vertical"> - + + + + + + + android:layout_weight="1" + android:gravity="center" + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/app/src/main/res/layout/list_profile_emails.xml b/app/src/main/res/layout/list_account_settings_emails.xml similarity index 97% rename from app/src/main/res/layout/list_profile_emails.xml rename to app/src/main/res/layout/list_account_settings_emails.xml index 363cdc4f..8573711f 100644 --- a/app/src/main/res/layout/list_profile_emails.xml +++ b/app/src/main/res/layout/list_account_settings_emails.xml @@ -28,7 +28,7 @@ android:id="@+id/userEmail" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/profileEmailTitle" + android:text="@string/accountEmailTitle" android:textColor="?attr/primaryTextColor" android:textSize="@dimen/dimen16sp"/> diff --git a/app/src/main/res/layout/list_account_settings_ssh_keys.xml b/app/src/main/res/layout/list_account_settings_ssh_keys.xml new file mode 100644 index 00000000..5528b163 --- /dev/null +++ b/app/src/main/res/layout/list_account_settings_ssh_keys.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/menu/drawer_menu.xml b/app/src/main/res/menu/drawer_menu.xml index 5be95c19..00afcaa7 100644 --- a/app/src/main/res/menu/drawer_menu.xml +++ b/app/src/main/res/menu/drawer_menu.xml @@ -60,6 +60,10 @@ android:icon="@drawable/ic_person" android:title="@string/navProfile"/> + + @string/pageTitleStarredRepos @string/navOrg @string/navRepos - @string/navProfile + @string/navAccount @string/pageTitleExplore @string/titleDrafts @string/pageTitleNotifications diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index de310abf..83a1fbe9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -35,6 +35,7 @@ My Issues Most Visited Repos Notes + Account Settings @@ -342,16 +343,19 @@ Followers Following - Add Email Address - Email Address + \u0040%1$s + + + + Emails + Email Address New email added successfully Email address is empty Email address is not valid Email address is already in use Primary - Emails - \u0040%1$s - + SSH Keys + Add / Remove Labels