Design Accounts from Nav menu (#648)

Merge branch 'master' into new-account-design

Merge branch 'master' into new-account-design

enhance the dialog UI

Merge branch 'master' into new-account-design

New account design in nav with dialog popup list

New design for accounts accessing

Co-authored-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/648
This commit is contained in:
M M Arif 2020-08-18 16:10:46 +02:00
parent 7585eb4834
commit dcacf1f141
8 changed files with 392 additions and 33 deletions

View File

@ -18,15 +18,20 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.navigation.NavigationView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.UserAccountsNavAdapter;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.fragments.AboutFragment;
import org.mian.gitnex.fragments.AdministrationFragment;
import org.mian.gitnex.fragments.BottomSheetDraftsFragment;
@ -51,6 +56,8 @@ import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.GiteaVersion;
import org.mian.gitnex.models.UserInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import eightbitlab.com.blurview.BlurView;
import eightbitlab.com.blurview.RenderScriptBlur;
@ -218,6 +225,26 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
userAvatarBackground = hView.findViewById(R.id.userAvatarBackground);
navHeaderFrame = hView.findViewById(R.id.navHeaderFrame);
List<UserAccount> userAccountsList;
userAccountsList = new ArrayList<>();
UserAccountsApi userAccountsApi;
userAccountsApi = new UserAccountsApi(ctx);
RecyclerView navRecyclerViewUserAccounts = hView.findViewById(R.id.navRecyclerViewUserAccounts);
UserAccountsNavAdapter adapterUserAccounts;
adapterUserAccounts = new UserAccountsNavAdapter(ctx, userAccountsList, drawer, toolbarTitle);
userAccountsApi.getAllAccounts().observe((AppCompatActivity) ctx, userAccounts -> {
if(userAccounts.size() > 0) {
userAccountsList.addAll(userAccounts);
navRecyclerViewUserAccounts.setAdapter(adapterUserAccounts);
}
});
userEmail.setTypeface(myTypeface);
userFullName.setTypeface(myTypeface);
@ -285,14 +312,6 @@ 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();
toolbar.setNavigationIcon(R.drawable.ic_menu);

View File

@ -0,0 +1,72 @@
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.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.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 mCtx;
private final List<UserAccount> userAccountsList;
public UserAccountsListDialogAdapter(@NonNull Context mCtx, int resource, @NonNull List<UserAccount> objects) {
super(mCtx, resource, objects);
userAccountsList = objects;
this.mCtx = mCtx;
}
@SuppressLint("ViewHolder")
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mCtx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
assert inflater != null;
View rowView = inflater.inflate(R.layout.custom_user_accounts_list, parent, false);
TinyDB tinyDB = new TinyDB(mCtx);
ImageView profileImage = rowView.findViewById(R.id.profileImage);
TextView userName = rowView.findViewById(R.id.userName);
TextView accountUrl = rowView.findViewById(R.id.accountUrl);
ImageView activeAccount = rowView.findViewById(R.id.activeAccount);
UserAccount currentItem = userAccountsList.get(position);
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);
}
PicassoService
.getInstance(mCtx).get().load(url + "img/favicon.png").placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(profileImage);
return rowView;
}
}

View File

@ -0,0 +1,147 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
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.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.fragments.UserAccountsFragment;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.List;
import io.mikael.urlbuilder.UrlBuilder;
/**
* Author M M Arif
*/
public class UserAccountsNavAdapter extends RecyclerView.Adapter<UserAccountsNavAdapter.UserAccountsViewHolder> {
private static DrawerLayout drawer;
private List<UserAccount> userAccountsList;
private Context mCtx;
private TextView toolbarTitle;
public UserAccountsNavAdapter(Context mCtx, List<UserAccount> userAccountsListMain, DrawerLayout drawerLayout, TextView toolbarTitle) {
this.mCtx = mCtx;
this.userAccountsList = userAccountsListMain;
drawer = drawerLayout;
this.toolbarTitle = toolbarTitle;
}
class UserAccountsViewHolder extends RecyclerView.ViewHolder {
private ImageView userAccountAvatar;
private UserAccountsViewHolder(View itemView) {
super(itemView);
userAccountAvatar = itemView.findViewById(R.id.userAccountAvatar);
itemView.setOnClickListener(item -> {
customDialogUserAccountsList(userAccountsList);
drawer.closeDrawers();
});
}
}
@NonNull
@Override
public UserAccountsNavAdapter.UserAccountsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.nav_user_accounts, parent, false);
return new UserAccountsViewHolder(v);
}
@SuppressLint("DefaultLocale")
@Override
public void onBindViewHolder(@NonNull UserAccountsNavAdapter.UserAccountsViewHolder holder, int position) {
UserAccount currentItem = userAccountsList.get(position);
String url = UrlBuilder.fromString(currentItem.getInstanceUrl())
.withPath("/")
.toString();
PicassoService
.getInstance(mCtx).get().load(url + "img/favicon.png").placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAccountAvatar);
}
@Override
public int getItemCount() {
return userAccountsList.size();
}
private void customDialogUserAccountsList(List<UserAccount> allAccountsList) {
TinyDB tinyDB = new TinyDB(mCtx);
Dialog dialog = new Dialog(mCtx);
dialog.setContentView(R.layout.custom_user_accounts_dialog);
ListView listView = dialog.findViewById(R.id.accountsList);
TextView manageAccounts = dialog.findViewById(R.id.manageAccounts);
if (dialog.getWindow() != null) {
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
manageAccounts.setOnClickListener(item -> {
toolbarTitle.setText(mCtx.getResources().getString(R.string.pageTitleUserAccounts));
AppCompatActivity activity = (AppCompatActivity) mCtx;
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new UserAccountsFragment()).commit();
dialog.dismiss();
});
UserAccountsListDialogAdapter arrayAdapter = new UserAccountsListDialogAdapter(mCtx, R.layout.custom_user_accounts_list, allAccountsList);
listView.setAdapter(arrayAdapter);
listView.setOnItemClickListener((adapterView, view, which, l) -> {
String accountNameSwitch = allAccountsList.get(which).getAccountName();
UserAccountsApi userAccountsApi = new UserAccountsApi(mCtx);
UserAccount userAccount = userAccountsApi.getAccountData(accountNameSwitch);
if(tinyDB.getInt("currentActiveAccountId") != userAccount.getAccountId()) {
String url = UrlBuilder.fromString(userAccount.getInstanceUrl())
.withPath("/")
.toString();
tinyDB.putString("loginUid", userAccount.getUserName());
tinyDB.putString("userLogin", userAccount.getUserName());
tinyDB.putString(userAccount.getUserName() + "-token", userAccount.getToken());
tinyDB.putString("instanceUrl", userAccount.getInstanceUrl());
tinyDB.putInt("currentActiveAccountId", userAccount.getAccountId());
Toasty.success(mCtx, mCtx.getResources().getString(R.string.switchAccountSuccess, userAccount.getUserName(), url));
((Activity) mCtx).recreate();
dialog.dismiss();
}
});
dialog.show();
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="?attr/primaryBackgroundColor" />
<corners android:radius="8dp" />
</shape>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/shape_custom_dialog"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical">
<ListView
android:id="@+id/accountsList"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:id="@+id/divider"
android:background="?attr/dividerColor" />
<Button
android:id="@+id/manageAccounts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:text="@string/pageTitleUserAccounts"
android:textColor="@color/colorWhite"
android:textSize="14sp" />
</LinearLayout>

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layoutFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="8dp"
android:orientation="vertical">
<ImageView
android:id="@+id/profileImage"
android:visibility="visible"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginEnd="15dp"
android:contentDescription="@string/generalImgContentText" />
<LinearLayout
android:id="@+id/frameAccountsInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_toEndOf="@+id/profileImage"
android:layout_marginBottom="2dp">
<TextView
android:id="@+id/userName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".95"
android:layout_gravity="start"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp"
android:textStyle="bold" />
<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/generalImgContentText" />
</LinearLayout>
<TextView
android:id="@+id/accountUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="0dp"
android:layout_toEndOf="@+id/profileImage"
android:layout_below="@+id/frameAccountsInfo"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp" />
</RelativeLayout>

View File

@ -25,15 +25,41 @@
android:gravity="bottom"
android:paddingTop="16dp">
<ImageView
android:id="@+id/userAvatar"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxHeight="24dp"
android:maxWidth="24dp"
android:paddingStart="20dp"
android:paddingEnd="5dp"
android:contentDescription="@string/generalImgContentText"/>
android:orientation="horizontal">
<ImageView
android:id="@+id/userAvatar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="24dp"
android:maxWidth="24dp"
android:paddingStart="20dp"
android:paddingEnd="5dp"
android:contentDescription="@string/generalImgContentText"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:paddingEnd="25dp"
android:paddingStart="15dp"
android:paddingTop="10dp"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/navRecyclerViewUserAccounts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:reverseLayout="true"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
@ -74,23 +100,6 @@
</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/shape_circle_white"
android:src="@drawable/ic_account_circle"
android:contentDescription="@string/generalImgContentText"/>
</LinearLayout>
</LinearLayout>
<View

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<ImageView
android:id="@+id/userAccountAvatar"
android:layout_width="32dp"
android:layout_height="32dp"
android:contentDescription="@string/generalImgContentText"
xmlns:android="http://schemas.android.com/apk/res/android" />