Accounts overview screen (#577)

optimize url string

Overview of accounts in the app

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/577
Reviewed-by: opyale <opyale@noreply.codeberg.org>
This commit is contained in:
M M Arif 2020-07-07 16:20:43 +02:00
parent cdfc2cfb9e
commit e2aff890d7
11 changed files with 374 additions and 25 deletions

View File

@ -40,6 +40,7 @@ import org.mian.gitnex.fragments.ProfileFragment;
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.Authorization;
import org.mian.gitnex.helpers.ChangeLog;
@ -182,6 +183,9 @@ 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));
}
drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
@ -281,6 +285,14 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
});
ImageView userAccounts = hView.findViewById(R.id.userAccounts);
userAccounts.setOnClickListener(v -> {
toolbarTitle.setText(getResources().getString(R.string.pageTitleUserAccounts));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new UserAccountsFragment()).commit();
drawer.closeDrawers();
});
toggle.syncState();
if(launchFragment != null) {

View File

@ -0,0 +1,110 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
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.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
import io.mikael.urlbuilder.UrlBuilder;
/**
* Author M M Arif
*/
public class UserAccountsAdapter extends RecyclerView.Adapter<UserAccountsAdapter.UserAccountsViewHolder> {
private List<UserAccount> userAccountsList;
private Context mCtx;
private TinyDB tinyDB;
static class UserAccountsViewHolder extends RecyclerView.ViewHolder {
private TextView accountUrl;
private TextView userId;
private ImageView activeAccount;
private ImageView deleteAccount;
private UserAccountsViewHolder(View itemView) {
super(itemView);
accountUrl = itemView.findViewById(R.id.accountUrl);
userId = itemView.findViewById(R.id.userId);
activeAccount = itemView.findViewById(R.id.activeAccount);
deleteAccount = itemView.findViewById(R.id.deleteAccount);
deleteAccount.setOnClickListener(itemDelete -> {
// use later to delete an account
});
itemView.setOnClickListener(itemEdit -> {
// use later to switch account
});
}
}
public UserAccountsAdapter(Context mCtx, List<UserAccount> userAccountsListMain) {
this.mCtx = mCtx;
this.userAccountsList = userAccountsListMain;
}
private void deleteAccount(int position) {
userAccountsList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, userAccountsList.size());
Toasty.info(mCtx, mCtx.getResources().getString(R.string.accountDeletedMessage));
}
@NonNull
@Override
public UserAccountsAdapter.UserAccountsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_user_accounts, parent, false);
return new UserAccountsViewHolder(v);
}
@SuppressLint("DefaultLocale")
@Override
public void onBindViewHolder(@NonNull UserAccountsAdapter.UserAccountsViewHolder holder, int position) {
UserAccount currentItem = userAccountsList.get(position);
tinyDB = new TinyDB(mCtx);
String url = UrlBuilder.fromString(currentItem.getInstanceUrl())
.withPath("/")
.toString();
holder.userId.setText(String.format("@%s", currentItem.getUserName()));
holder.accountUrl.setText(url);
if(tinyDB.getInt("currentActiveAccountId") == currentItem.getAccountId()) {
holder.activeAccount.setVisibility(View.VISIBLE);
}
else {
holder.deleteAccount.setVisibility(View.GONE);
}
}
@Override
public int getItemCount() {
return userAccountsList.size();
}
}

View File

@ -0,0 +1,95 @@
package org.mian.gitnex.fragments;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
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 org.mian.gitnex.R;
import org.mian.gitnex.adapters.UserAccountsAdapter;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.UserAccount;
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;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_user_accounts, container, false);
ctx = getContext();
setHasOptionsMenu(true);
userAccountsList = new ArrayList<>();
userAccountsApi = new UserAccountsApi(ctx);
mRecyclerView = v.findViewById(R.id.recyclerView);
final SwipeRefreshLayout swipeRefresh = v.findViewById(R.id.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().postDelayed(() -> {
userAccountsList.clear();
swipeRefresh.setRefreshing(false);
fetchDataAsync();
}, 250));
fetchDataAsync();
return v;
}
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

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="@color/darkGreen"/>
</shape>
</shape>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="@color/colorRed"/>
</shape>
</shape>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<size
android:width="32dp"
android:height="32dp" />
<solid
android:color="@color/white" />
</shape>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#368F73"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
</vector>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/userAccountsFrame"
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:padding="4dp"
android:scrollbars="vertical" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</RelativeLayout>

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layoutUserAccountsFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:fitsSystemWindows="true"
android:orientation="vertical"
android:layout_margin="10dp"
android:background="?attr/primaryBackgroundColor">
<LinearLayout
android:id="@+id/frameAccountsInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="10dp">
<TextView
android:id="@+id/userId"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".95"
android:layout_gravity="start"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
<ImageView
android:id="@+id/activeAccount"
android:layout_weight=".05"
android:layout_width="10dp"
android:layout_height="20dp"
android:layout_gravity="end"
android:src="@drawable/ic_check"
android:visibility="gone"
android:contentDescription="@string/menuContentDesc" />
<ImageView
android:id="@+id/deleteAccount"
android:layout_weight=".05"
android:layout_width="10dp"
android:layout_height="20dp"
android:layout_gravity="end"
android:src="@drawable/ic_delete"
android:visibility="gone"
android:contentDescription="@string/menuDeleteText" />
</LinearLayout>
<TextView
android:id="@+id/accountUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="0dp"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp" />
</LinearLayout>

View File

@ -35,35 +35,61 @@
android:paddingEnd="5dp"
android:contentDescription="@string/generalImgContentText"/>
<TextView
android:id="@+id/userFullname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:textSize="18sp"
android:textIsSelectable="true"
android:textColor="@color/white"
android:paddingStart="20dp"
android:paddingEnd="5dp" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp">
android:orientation="horizontal"
android:layout_marginTop="5dp"
android:baselineAligned="false">
<TextView
android:id="@+id/userEmail"
<LinearLayout
android:layout_width="0dp"
android:layout_weight="0.85"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textIsSelectable="true"
android:textColor="@color/white"
android:gravity="start"
android:layout_gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="5dp" />
android:layout_weight=".82"
android:orientation="vertical"
android:layout_marginTop="5dp">
<TextView
android:id="@+id/userFullname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:textSize="18sp"
android:textIsSelectable="true"
android:textColor="@color/white"
android:paddingStart="20dp"
android:paddingEnd="5dp" />
<TextView
android:id="@+id/userEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textIsSelectable="true"
android:textColor="@color/white"
android:gravity="start"
android:layout_gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="5dp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".18"
android:orientation="vertical"
android:layout_marginTop="15dp">
<ImageView
android:id="@+id/userAccounts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/circle_white"
android:src="@drawable/ic_account_circle"
android:contentDescription="@string/generalImgContentText"/>
</LinearLayout>
</LinearLayout>

View File

@ -58,6 +58,7 @@
<string name="pageTitleNewFile">New File</string>
<string name="pageTitleExplore">Explore</string>
<string name="pageTitleAdministration">Gitea Administration</string>
<string name="pageTitleUserAccounts">Manage Accounts (beta)</string>
<!-- page titles -->
<string name="appVersion">Version\u0020:\u0020</string>
@ -684,4 +685,6 @@
<string name="reportsHintText">Crash reports</string>
<string name="archivedRepository">Archived</string>
<string name="accountDeletedMessage">Account deleted successfully</string>
</resources>