Refactor account switcher/manager (#1007)

closes #985

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1007
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
This commit is contained in:
qwerty287 2021-12-17 18:50:03 +01:00 committed by 6543
parent 95a5940f04
commit 76fae56b87
9 changed files with 26 additions and 339 deletions

View File

@ -46,7 +46,6 @@ import org.mian.gitnex.fragments.MyProfileFragment;
import org.mian.gitnex.fragments.RepositoriesFragment;
import org.mian.gitnex.fragments.SettingsFragment;
import org.mian.gitnex.fragments.StarredRepositoriesFragment;
import org.mian.gitnex.fragments.UserAccountsFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
@ -173,9 +172,6 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
else if(fragmentById instanceof AdministrationFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
}
else if(fragmentById instanceof UserAccountsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleUserAccounts));
}
getNotificationsCount(instanceToken);
@ -218,7 +214,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
RecyclerView navRecyclerViewUserAccounts = hView.findViewById(R.id.userAccounts);
UserAccountsNavAdapter adapterUserAccounts;
adapterUserAccounts = new UserAccountsNavAdapter(ctx, userAccountsList, drawer, toolbarTitle);
adapterUserAccounts = new UserAccountsNavAdapter(ctx, userAccountsList, drawer);
userAccountsApi.getAllAccounts().observe((AppCompatActivity) ctx, userAccounts -> {
if(userAccounts.size() > 0) {

View File

@ -2,6 +2,7 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
@ -33,6 +34,7 @@ public class UserAccountsAdapter extends RecyclerView.Adapter<UserAccountsAdapte
private final List<UserAccount> userAccountsList;
private final Context context;
private TinyDB tinyDB;
private final Dialog dialog;
class UserAccountsViewHolder extends RecyclerView.ViewHolder {
@ -85,6 +87,7 @@ public class UserAccountsAdapter extends RecyclerView.Adapter<UserAccountsAdapte
Toasty.success(context, context.getResources().getString(R.string.switchAccountSuccess, userAccount.getUserName(), url));
((Activity) context).recreate();
dialog.dismiss();
}
});
@ -93,8 +96,8 @@ public class UserAccountsAdapter extends RecyclerView.Adapter<UserAccountsAdapte
}
public UserAccountsAdapter(Context ctx, List<UserAccount> userAccountsListMain) {
public UserAccountsAdapter(Context ctx, List<UserAccount> userAccountsListMain, Dialog dialog) {
this.dialog = dialog;
this.context = ctx;
this.userAccountsList = userAccountsListMain;
}

View File

@ -1,77 +0,0 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import java.util.List;
import io.mikael.urlbuilder.UrlBuilder;
/**
* Author M M Arif
*/
public class UserAccountsListDialogAdapter extends ArrayAdapter<UserAccount> {
private final Context context;
private final TinyDB tinyDB;
private final List<UserAccount> userAccounts;
public UserAccountsListDialogAdapter(@NonNull Context ctx, int resource, @NonNull List<UserAccount> userAccounts) {
super(ctx, resource, userAccounts);
tinyDB = TinyDB.getInstance(ctx);
this.userAccounts = userAccounts;
this.context = ctx;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
if(convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.custom_user_accounts_list, parent, false);
}
ImageView profileImage = convertView.findViewById(R.id.profileImage);
TextView userName = convertView.findViewById(R.id.userName);
TextView accountUrl = convertView.findViewById(R.id.accountUrl);
ImageView activeAccount = convertView.findViewById(R.id.activeAccount);
UserAccount currentItem = userAccounts.get(position);
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
String url = UrlBuilder.fromString(currentItem.getInstanceUrl())
.withPath("/")
.toString();
userName.setText(currentItem.getUserName());
accountUrl.setText(url);
if(tinyDB.getInt("currentActiveAccountId") == currentItem.getAccountId()) {
activeAccount.setVisibility(View.VISIBLE);
}
else {
activeAccount.setVisibility(View.GONE);
}
PicassoService
.getInstance(context).get().load(url + "img/favicon.png").placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(profileImage);
return convertView;
}
}

View File

@ -1,28 +1,26 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.AddNewAccountActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.fragments.UserAccountsFragment;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.Toasty;
import java.util.List;
import io.mikael.urlbuilder.UrlBuilder;
@ -35,14 +33,12 @@ public class UserAccountsNavAdapter extends RecyclerView.Adapter<UserAccountsNav
private static DrawerLayout drawer;
private final List<UserAccount> userAccountsList;
private final Context context;
private final TextView toolbarTitle;
public UserAccountsNavAdapter(Context ctx, List<UserAccount> userAccountsListMain, DrawerLayout drawerLayout, TextView toolbarTitle) {
public UserAccountsNavAdapter(Context ctx, List<UserAccount> userAccountsListMain, DrawerLayout drawerLayout) {
this.context = ctx;
this.userAccountsList = userAccountsListMain;
drawer = drawerLayout;
this.toolbarTitle = toolbarTitle;
}
class UserAccountsViewHolder extends RecyclerView.ViewHolder {
@ -104,42 +100,22 @@ public class UserAccountsNavAdapter extends RecyclerView.Adapter<UserAccountsNav
Dialog dialog = new Dialog(context, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
dialog.setContentView(R.layout.custom_user_accounts_dialog);
ListView listView = dialog.findViewById(R.id.accountsList);
TextView manageAccounts = dialog.findViewById(R.id.manageAccounts);
RecyclerView listView = dialog.findViewById(R.id.accountsList);
Button newAccount = dialog.findViewById(R.id.newAccount);
if (dialog.getWindow() != null) {
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
manageAccounts.setOnClickListener(item -> {
toolbarTitle.setText(context.getResources().getString(R.string.pageTitleUserAccounts));
AppCompatActivity activity = (AppCompatActivity) context;
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new UserAccountsFragment()).commit();
newAccount.setOnClickListener(item -> {
context.startActivity(new Intent(context, AddNewAccountActivity.class));
dialog.dismiss();
});
UserAccountsListDialogAdapter arrayAdapter = new UserAccountsListDialogAdapter(context, R.layout.custom_user_accounts_list, allAccountsList);
UserAccountsAdapter arrayAdapter = new UserAccountsAdapter(context, allAccountsList, dialog);
listView.setLayoutManager(new LinearLayoutManager(context));
listView.setAdapter(arrayAdapter);
listView.setOnItemClickListener((adapterView, view, which, l) -> {
UserAccount userAccount = allAccountsList.get(which);
if(AppUtil.switchToAccount(context, userAccount)) {
String url = UrlBuilder.fromString(userAccount.getInstanceUrl())
.withPath("/")
.toString();
Toasty.success(context, context.getResources().getString(R.string.switchAccountSuccess, userAccount.getUserName(), url));
((Activity) context).recreate();
dialog.dismiss();
}
});
dialog.show();
}

View File

@ -1,112 +0,0 @@
package org.mian.gitnex.fragments;
import android.content.Context;
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.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.AddNewAccountActivity;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.adapters.UserAccountsAdapter;
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.FragmentUserAccountsBinding;
import java.util.ArrayList;
import java.util.List;
/**
* Author M M Arif
*/
public class UserAccountsFragment extends Fragment {
private Context ctx;
private UserAccountsAdapter adapter;
private RecyclerView mRecyclerView;
private UserAccountsApi userAccountsApi;
private List<UserAccount> userAccountsList;
private ExtendedFloatingActionButton addNewAccount;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
FragmentUserAccountsBinding fragmentUserAccountsBinding = FragmentUserAccountsBinding.inflate(inflater, container, false);
ctx = getContext();
setHasOptionsMenu(true);
((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.pageTitleUserAccounts));
userAccountsList = new ArrayList<>();
userAccountsApi = BaseApi.getInstance(ctx, UserAccountsApi.class);
mRecyclerView = fragmentUserAccountsBinding.recyclerView;
final SwipeRefreshLayout swipeRefresh = fragmentUserAccountsBinding.pullToRefresh;
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(ctx));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
adapter = new UserAccountsAdapter(getContext(), userAccountsList);
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
userAccountsList.clear();
swipeRefresh.setRefreshing(false);
fetchDataAsync();
}, 250));
addNewAccount = fragmentUserAccountsBinding.addNewAccount;
addNewAccount.setOnClickListener(view -> {
Intent intent = new Intent(view.getContext(), AddNewAccountActivity.class);
startActivity(intent);
});
fetchDataAsync();
return fragmentUserAccountsBinding.getRoot();
}
private void fetchDataAsync() {
userAccountsApi.getAllAccounts().observe(getViewLifecycleOwner(), userAccounts -> {
assert userAccounts != null;
if(userAccounts.size() > 0) {
userAccountsList.clear();
userAccountsList.addAll(userAccounts);
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
}
});
}
@Override
public void onResume() {
super.onResume();
userAccountsList.clear();
fetchDataAsync();
}
}

View File

@ -7,15 +7,17 @@
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:orientation="vertical"
android:padding="16dp">
<ListView
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/accountsList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp" />
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:scrollbars="vertical" />
</LinearLayout>
@ -26,13 +28,13 @@
android:background="?attr/dividerColor" />
<Button
android:id="@+id/manageAccounts"
android:id="@+id/newAccount"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_margin="16dp"
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:text="@string/pageTitleUserAccounts"
android:text="@string/addNewAccount"
android:textColor="@color/colorWhite"
android:textSize="16sp" />

View File

@ -1,62 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layoutFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="8dp">
<ImageView
android:id="@+id/profileImage"
android:layout_width="@dimen/list_avatar_size"
android:layout_height="@dimen/list_avatar_size"
android:layout_marginEnd="10dp"
android:contentDescription="@string/generalImgContentText"
android:visibility="visible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/frameAccountsInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/userName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/activeAccount"
android:layout_width="20dp"
android:layout_height="wrap_content"
android:layout_weight="0"
android:contentDescription="@string/generalImgContentText"
android:src="@drawable/ic_check"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>
<TextView
android:id="@+id/accountUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/userAccountsFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/pullToRefresh"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:scrollbars="vertical" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/addNewAccount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
android:text="@string/addNewAccount"
android:contentDescription="@string/addNewAccount"
android:textColor="@color/colorWhite"
android:backgroundTint="?attr/fabColor"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
app:iconTint="@color/colorWhite"
app:icon="@drawable/ic_add" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -47,7 +47,6 @@
<string name="pageTitleNewFile">New File</string>
<string name="pageTitleExplore">Explore</string>
<string name="pageTitleAdministration">Gitea Administration</string>
<string name="pageTitleUserAccounts">Manage Accounts</string>
<string name="pageTitleNewPullRequest">New Pull Request</string>
<string name="pageTitleUsers">Users</string>
<!-- page titles -->