User profile view (#931)

Closes #881

Please suggest on current data shown as some may be related to personal(email etc), but at this moment we have not much to show either. So sticking to it is my view on this.

I will extend the taps on profile images once we agree what to show.

@gitnex/Code-Managers

- [x] Detail
- [x] Repositories
- [x] Starred Repos
- [x] Followers
- [x] Following
- [x] Tap on all profile images
- [x] Organizations

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: opyale <opyale@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/931
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
This commit is contained in:
M M Arif 2021-08-02 20:04:33 +02:00
parent 1e8c8efd6b
commit 1693acaa70
53 changed files with 3092 additions and 277 deletions

View File

@ -56,12 +56,13 @@ configurations {
dependencies {
def lifecycle_version = '2.3.1'
def markwon_version = '4.6.2'
def work_version = "2.7.0-alpha03"
def work_version = "2.7.0-alpha04"
def acra = "5.7.0"
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.3.0-rc01'
implementation 'androidx.appcompat:appcompat:1.4.0-alpha02'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.viewpager2:viewpager2:1.1.0-alpha01'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
@ -108,9 +109,9 @@ dependencies {
implementation "androidx.work:work-runtime:$work_version"
implementation "io.mikael:urlbuilder:2.0.9"
implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2"
implementation "org.codeberg.gitnex:tea4j:1.0.10"
implementation "org.codeberg.gitnex:tea4j:1.0.16"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
implementation 'androidx.biometric:biometric:1.1.0'
implementation 'com.github.chrisvest:stormpot:2.4.1'
implementation 'com.github.chrisvest:stormpot:2.4.2'
}

View File

@ -51,7 +51,7 @@
android:name=".activities.CreateNewUserActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.ProfileEmailActivity"
android:name=".activities.MyProfileEmailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.AddCollaboratorToRepositoryActivity"
@ -123,7 +123,7 @@
android:name=".activities.SettingsAppearanceActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsFileViewerActivity"
android:name=".activities.ProfileActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsSecurityActivity"

View File

@ -215,7 +215,7 @@ public class CreateRepoActivity extends BaseActivity {
Call<List<OrgOwner>> call = RetrofitClient
.getApiInterface(ctx)
.getOrgOwners(instanceToken);
.getOrgOwners(instanceToken, 1, 50);
call.enqueue(new Callback<List<OrgOwner>>() {

View File

@ -1,6 +1,7 @@
package org.mian.gitnex.activities;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
@ -591,6 +592,17 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.issueTitle.setText(HtmlCompat.fromHtml(issueNumber_ + " " + EmojiParser.parseToUnicode(singleIssue.getTitle()), HtmlCompat.FROM_HTML_MODE_LEGACY));
String cleanIssueDescription = singleIssue.getBody().trim();
viewBinding.assigneeAvatar.setOnClickListener(loginId -> {
Intent intent = new Intent(ctx, ProfileActivity.class);
intent.putExtra("username", singleIssue.getUser().getLogin());
ctx.startActivity(intent);
});
viewBinding.assigneeAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(ctx, singleIssue.getUser().getLogin(), ctx.getString(R.string.copyLoginIdToClipBoard, singleIssue.getUser().getLogin()));
return true;
});
Markdown.render(ctx, EmojiParser.parseToUnicode(cleanIssueDescription), viewBinding.issueDescription);
RelativeLayout.LayoutParams paramsDesc = (RelativeLayout.LayoutParams) viewBinding.issueDescription.getLayoutParams();
@ -612,7 +624,20 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.frameAssignees.addView(assigneesView);
assigneesView.setLayoutParams(params1);
if(!singleIssue.getAssignees().get(i).getFull_name().equals("")) {
int finalI = i;
assigneesView.setOnClickListener(loginId -> {
Intent intent = new Intent(ctx, ProfileActivity.class);
intent.putExtra("username", singleIssue.getAssignees().get(finalI).getLogin());
ctx.startActivity(intent);
});
assigneesView.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(ctx, singleIssue.getAssignees().get(finalI).getLogin(), ctx.getString(R.string.copyLoginIdToClipBoard, singleIssue.getAssignees().get(finalI).getLogin()));
return true;
});
/*if(!singleIssue.getAssignees().get(i).getFull_name().equals("")) {
assigneesView.setOnClickListener(
new ClickListener(getString(R.string.assignedTo, singleIssue.getAssignees().get(i).getFull_name()), ctx));
@ -621,7 +646,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
assigneesView.setOnClickListener(
new ClickListener(getString(R.string.assignedTo, singleIssue.getAssignees().get(i).getLogin()), ctx));
}
}*/
}
}
else {
@ -759,7 +784,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.issueMilestone.setVisibility(View.GONE);
}
if(!singleIssue.getUser().getFull_name().equals("")) {
/*if(!singleIssue.getUser().getFull_name().equals("")) {
viewBinding.assigneeAvatar.setOnClickListener(
new ClickListener(ctx.getResources().getString(R.string.issueCreator) + singleIssue.getUser().getFull_name(), ctx));
@ -768,7 +793,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.assigneeAvatar.setOnClickListener(
new ClickListener(ctx.getResources().getString(R.string.issueCreator) + singleIssue.getUser().getLogin(), ctx));
}
}*/
viewBinding.progressBar.setVisibility(View.GONE);
}

View File

@ -44,7 +44,7 @@ import org.mian.gitnex.fragments.ExploreFragment;
import org.mian.gitnex.fragments.MyRepositoriesFragment;
import org.mian.gitnex.fragments.NotificationsFragment;
import org.mian.gitnex.fragments.OrganizationsFragment;
import org.mian.gitnex.fragments.ProfileFragment;
import org.mian.gitnex.fragments.MyProfileFragment;
import org.mian.gitnex.fragments.RepositoriesFragment;
import org.mian.gitnex.fragments.SettingsFragment;
import org.mian.gitnex.fragments.StarredRepositoriesFragment;
@ -203,7 +203,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
else if(fragmentById instanceof NotificationsFragment) {
toolbarTitle.setText(R.string.pageTitleNotifications);
}
else if(fragmentById instanceof ProfileFragment) {
else if(fragmentById instanceof MyProfileFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
}
else if(fragmentById instanceof DraftsFragment) {
@ -309,7 +309,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
userAvatar.setOnClickListener(v -> {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
drawer.closeDrawers();
@ -389,7 +389,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
return;
case "profile":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
return;
@ -431,7 +431,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
case 4:
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
break;
@ -569,7 +569,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
else if(id == R.id.nav_profile) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyProfileFragment()).commit();
}
else if(id == R.id.nav_repositories) {

View File

@ -30,7 +30,7 @@ import retrofit2.Callback;
* Author M M Arif
*/
public class ProfileEmailActivity extends BaseActivity {
public class MyProfileEmailActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private EditText userEmail;

View File

@ -0,0 +1,143 @@
package org.mian.gitnex.activities;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
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.fragments.profile.DetailFragment;
import org.mian.gitnex.fragments.profile.FollowersFragment;
import org.mian.gitnex.fragments.profile.FollowingFragment;
import org.mian.gitnex.fragments.profile.OrganizationsFragment;
import org.mian.gitnex.fragments.profile.RepositoriesFragment;
import org.mian.gitnex.fragments.profile.StarredRepositoriesFragment;
import org.mian.gitnex.helpers.Toasty;
import java.util.Objects;
/**
* Author M M Arif
*/
public class ProfileActivity extends BaseActivity {
private String username;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
Intent profileIntent = getIntent();
Typeface myTypeface;
Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = findViewById(R.id.toolbarTitle);
if(profileIntent.getStringExtra("username") != null && !Objects.equals(profileIntent.getStringExtra("username"), "")) {
username = profileIntent.getStringExtra("username");
}
else {
Toasty.warning(ctx, ctx.getResources().getString(R.string.userInvalidUserName));
finish();
}
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(username);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ViewPager2 viewPager = findViewById(R.id.profileContainer);
viewPager.setOffscreenPageLimit(1);
TabLayout tabLayout = findViewById(R.id.tabs);
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
break;
}
toolbarTitle.setTypeface(myTypeface);
toolbarTitle.setText(username);
viewPager.setAdapter(new ViewPagerAdapter(this));
String[] tabTitles = {ctx.getResources().getString(R.string.tabTextInfo), ctx.getResources().getString(R.string.navRepos), ctx.getResources().getString(R.string.navStarredRepos), ctx.getResources().getString(R.string.navOrg), ctx.getResources().getString(R.string.profileTabFollowers), ctx.getResources().getString(R.string.profileTabFollowing)};
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> tab.setText(tabTitles[position])).attach();
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);
}
}
}
}
public class ViewPagerAdapter extends FragmentStateAdapter {
public ViewPagerAdapter(@NonNull FragmentActivity fa) { super(fa); }
@NonNull
@Override
public Fragment createFragment(int position) {
switch(position) {
case 0: // detail
return DetailFragment.newInstance(username);
case 1: // repos
return RepositoriesFragment.newInstance(username);
case 2: // starred repos
return StarredRepositoriesFragment.newInstance(username);
case 3: // organizations
return OrganizationsFragment.newInstance(username);
case 4: // followers
return FollowersFragment.newInstance(username);
case 5: // following
return FollowingFragment.newInstance(username);
}
return null;
}
@Override
public int getItemCount() {
return 6;
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home) {
finish();
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
}

View File

@ -1,6 +1,7 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
@ -15,6 +16,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
@ -31,7 +33,7 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
private final Context context;
private final List<UserInfo> usersListFull;
static class UsersViewHolder extends RecyclerView.ViewHolder {
class UsersViewHolder extends RecyclerView.ViewHolder {
private String userLoginId;
@ -52,10 +54,14 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
userRole = itemView.findViewById(R.id.userRole);
userAvatar.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userLoginId);
context.startActivity(intent);
});
Context context = loginId.getContext();
userAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
return true;
});
}
}

View File

@ -2,6 +2,7 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
@ -11,6 +12,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.gitnex.tea4j.models.Collaborators;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
@ -25,7 +27,7 @@ public class CollaboratorsAdapter extends BaseAdapter {
private final List<Collaborators> collaboratorsList;
private final Context context;
private static class ViewHolder {
private class ViewHolder {
private String userLoginId;
@ -38,10 +40,14 @@ public class CollaboratorsAdapter extends BaseAdapter {
collaboratorName = v.findViewById(R.id.collaboratorName);
collaboratorAvatar.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userLoginId);
context.startActivity(intent);
});
Context context = loginId.getContext();
collaboratorAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
return true;
});
}
}

View File

@ -14,6 +14,7 @@ import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.Issues;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
@ -64,8 +65,6 @@ public class ExploreIssuesAdapter extends RecyclerView.Adapter<ExploreIssuesAdap
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
itemView.setOnClickListener(v -> {
Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issue.getNumber());
@ -99,10 +98,14 @@ public class ExploreIssuesAdapter extends RecyclerView.Adapter<ExploreIssuesAdap
});
issueAssigneeAvatar.setOnClickListener(v -> {
Context context = v.getContext();
String userLoginId = issue.getUser().getLogin();
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", issue.getUser().getLogin());
context.startActivity(intent);
});
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
issueAssigneeAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, issue.getUser().getLogin(), context.getString(R.string.copyLoginIdToClipBoard, issue.getUser().getLogin()));
return true;
});
}
}

View File

@ -20,6 +20,7 @@ import com.google.gson.JsonElement;
import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.models.IssueComments;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
@ -87,10 +88,9 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
menu.setOnClickListener(v -> {
final Context ctx = v.getContext();
final String loginUid = tinyDB.getString("loginUid");
@SuppressLint("InflateParams") View vw = LayoutInflater.from(ctx).inflate(R.layout.bottom_sheet_issue_comments, null);
@SuppressLint("InflateParams") View vw = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_issue_comments, null);
TextView commentMenuEdit = vw.findViewById(R.id.commentMenuEdit);
TextView commentShare = vw.findViewById(R.id.issueCommentShare);
@ -108,7 +108,7 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
commentMenuCopy.setVisibility(View.GONE);
}
BottomSheetDialog dialog = new BottomSheetDialog(ctx);
BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(vw);
dialog.show();
@ -118,7 +118,7 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
bundle1.putAll(bundle);
bundle1.putInt("commentId", issueComment.getId());
ReactionSpinner reactionSpinner = new ReactionSpinner(ctx, bundle1);
ReactionSpinner reactionSpinner = new ReactionSpinner(context, bundle1);
reactionSpinner.setOnInteractedListener(() -> {
tinyDB.putBoolean("commentEdited", true);
@ -148,10 +148,10 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
// share issue comment
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
String intentHeader = tinyDB.getString("issueNumber") + ctx.getResources().getString(R.string.hash) + "issuecomment-" + issueComment.getId() + " " + tinyDB.getString("issueTitle");
String intentHeader = tinyDB.getString("issueNumber") + context.getResources().getString(R.string.hash) + "issuecomment-" + issueComment.getId() + " " + tinyDB.getString("issueTitle");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, intentHeader);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, commentUrl);
ctx.startActivity(Intent.createChooser(sharingIntent, intentHeader));
context.startActivity(Intent.createChooser(sharingIntent, intentHeader));
dialog.dismiss();
});
@ -160,14 +160,14 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
// comment Url
CharSequence commentUrl = issueComment.getHtml_url();
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(context).getSystemService(Context.CLIPBOARD_SERVICE);
assert clipboard != null;
ClipData clip = ClipData.newPlainText(commentUrl, commentUrl);
clipboard.setPrimaryClip(clip);
dialog.dismiss();
Toasty.success(ctx, ctx.getString(R.string.copyIssueUrlToastMsg));
Toasty.success(context, context.getString(R.string.copyIssueUrlToastMsg));
});
commentMenuQuote.setOnClickListener(v1 -> {
@ -195,27 +195,32 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
});
commentMenuCopy.setOnClickListener(v1 -> {
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(context).getSystemService(Context.CLIPBOARD_SERVICE);
assert clipboard != null;
ClipData clip = ClipData.newPlainText("Comment on issue #" + tinyDB.getString("issueNumber"), issueComment.getBody());
clipboard.setPrimaryClip(clip);
dialog.dismiss();
Toasty.success(ctx, ctx.getString(R.string.copyIssueCommentToastMsg));
Toasty.success(context, context.getString(R.string.copyIssueCommentToastMsg));
});
commentMenuDelete.setOnClickListener(v1 -> {
deleteIssueComment(ctx, issueComment.getId(), getAdapterPosition());
deleteIssueComment(context, issueComment.getId(), getAdapterPosition());
dialog.dismiss();
});
});
avatar.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userLoginId);
context.startActivity(intent);
});
Context context = loginId.getContext();
avatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
return true;
});
}
}

View File

@ -16,6 +16,7 @@ import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.models.Issues;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
@ -110,9 +111,6 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
itemView.setOnClickListener(layoutView -> {
Context context = layoutView.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issue.getNumber());
@ -123,12 +121,15 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
});
issueAssigneeAvatar.setOnClickListener(v -> {
Context context = v.getContext();
String userLoginId = issue.getUser().getLogin();
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", issue.getUser().getLogin());
context.startActivity(intent);
});
issueAssigneeAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, issue.getUser().getLogin(), context.getString(R.string.copyLoginIdToClipBoard, issue.getUser().getLogin()));
return true;
});
}
@SuppressLint("SetTextI18n")

View File

@ -2,6 +2,7 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
@ -13,6 +14,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
@ -29,7 +31,7 @@ public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
private final Context context;
private final List<UserInfo> membersListFull;
private static class ViewHolder {
private class ViewHolder {
private String userLoginId;
@ -42,10 +44,14 @@ public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
memberName = v.findViewById(R.id.memberName);
memberAvatar.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userLoginId);
context.startActivity(intent);
});
Context context = loginId.getContext();
memberAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
return true;
});
}
}

View File

@ -18,7 +18,7 @@ import java.util.List;
* Author M M Arif
*/
public class ProfileEmailsAdapter extends RecyclerView.Adapter<ProfileEmailsAdapter.EmailsViewHolder> {
public class MyProfileEmailsAdapter extends RecyclerView.Adapter<MyProfileEmailsAdapter.EmailsViewHolder> {
private final List<Emails> emailsList;
private final Context context;
@ -37,20 +37,20 @@ public class ProfileEmailsAdapter extends RecyclerView.Adapter<ProfileEmailsAdap
}
}
public ProfileEmailsAdapter(Context ctx, List<Emails> emailsListMain) {
public MyProfileEmailsAdapter(Context ctx, List<Emails> emailsListMain) {
this.context = ctx;
this.emailsList = emailsListMain;
}
@NonNull
@Override
public ProfileEmailsAdapter.EmailsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
public MyProfileEmailsAdapter.EmailsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_profile_emails, parent, false);
return new ProfileEmailsAdapter.EmailsViewHolder(v);
return new MyProfileEmailsAdapter.EmailsViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull ProfileEmailsAdapter.EmailsViewHolder holder, int position) {
public void onBindViewHolder(@NonNull MyProfileEmailsAdapter.EmailsViewHolder holder, int position) {
Emails currentItem = emailsList.get(position);

View File

@ -1,6 +1,7 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
@ -11,6 +12,7 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
@ -20,12 +22,12 @@ import java.util.List;
* Author M M Arif
*/
public class ProfileFollowersAdapter extends RecyclerView.Adapter<ProfileFollowersAdapter.FollowersViewHolder> {
public class MyProfileFollowersAdapter extends RecyclerView.Adapter<MyProfileFollowersAdapter.FollowersViewHolder> {
private final List<UserInfo> followersList;
private final Context context;
static class FollowersViewHolder extends RecyclerView.ViewHolder {
class FollowersViewHolder extends RecyclerView.ViewHolder {
private String userLoginId;
@ -41,16 +43,20 @@ public class ProfileFollowersAdapter extends RecyclerView.Adapter<ProfileFollowe
userFullName = itemView.findViewById(R.id.userFullName);
userName = itemView.findViewById(R.id.userName);
userAvatar.setOnClickListener(loginId -> {
Context context = loginId.getContext();
itemView.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userLoginId);
context.startActivity(intent);
});
itemView.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
return true;
});
}
}
public ProfileFollowersAdapter(Context ctx, List<UserInfo> followersListMain) {
public MyProfileFollowersAdapter(Context ctx, List<UserInfo> followersListMain) {
this.context = ctx;
this.followersList = followersListMain;
@ -58,14 +64,14 @@ public class ProfileFollowersAdapter extends RecyclerView.Adapter<ProfileFollowe
@NonNull
@Override
public ProfileFollowersAdapter.FollowersViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
public MyProfileFollowersAdapter.FollowersViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_profile_followers, parent, false);
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_profile_followers_following, parent, false);
return new FollowersViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull ProfileFollowersAdapter.FollowersViewHolder holder, int position) {
public void onBindViewHolder(@NonNull MyProfileFollowersAdapter.FollowersViewHolder holder, int position) {
UserInfo currentItem = followersList.get(position);
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);

View File

@ -1,6 +1,7 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
@ -11,6 +12,7 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
@ -20,12 +22,12 @@ import java.util.List;
* Author M M Arif
*/
public class ProfileFollowingAdapter extends RecyclerView.Adapter<ProfileFollowingAdapter.FollowingViewHolder> {
public class MyProfileFollowingAdapter extends RecyclerView.Adapter<MyProfileFollowingAdapter.FollowingViewHolder> {
private final List<UserInfo> followingList;
private final Context context;
static class FollowingViewHolder extends RecyclerView.ViewHolder {
class FollowingViewHolder extends RecyclerView.ViewHolder {
private String userLoginId;
@ -41,16 +43,20 @@ public class ProfileFollowingAdapter extends RecyclerView.Adapter<ProfileFollowi
userFullName = itemView.findViewById(R.id.userFullName);
userName = itemView.findViewById(R.id.userName);
userAvatar.setOnClickListener(loginId -> {
Context context = loginId.getContext();
itemView.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userLoginId);
context.startActivity(intent);
});
itemView.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
return true;
});
}
}
public ProfileFollowingAdapter(Context ctx, List<UserInfo> followingListMain) {
public MyProfileFollowingAdapter(Context ctx, List<UserInfo> followingListMain) {
this.context = ctx;
this.followingList = followingListMain;
@ -58,14 +64,14 @@ public class ProfileFollowingAdapter extends RecyclerView.Adapter<ProfileFollowi
@NonNull
@Override
public ProfileFollowingAdapter.FollowingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
public MyProfileFollowingAdapter.FollowingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_profile_following, parent, false);
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_profile_followers_following, parent, false);
return new FollowingViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull ProfileFollowingAdapter.FollowingViewHolder holder, int position) {
public void onBindViewHolder(@NonNull MyProfileFollowingAdapter.FollowingViewHolder holder, int position) {
UserInfo currentItem = followingList.get(position);
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);

View File

@ -16,6 +16,7 @@ import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.models.PullRequests;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
@ -38,7 +39,6 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
private boolean isLoading = false, isMoreDataAvailable = true;
public PullRequestsAdapter(Context context, List<PullRequests> prListMain) {
this.context = context;
this.prList = prListMain;
}
@ -84,7 +84,6 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
@Override
public int getItemCount() {
return prList.size();
}
@ -106,9 +105,6 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
prCreatedTime = itemView.findViewById(R.id.prCreatedTime);
itemView.setOnClickListener(v -> {
Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", pullRequest.getNumber());
intent.putExtra("prMergeable", pullRequest.isMergeable());
@ -135,12 +131,15 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
});
assigneeAvatar.setOnClickListener(v -> {
Context context = v.getContext();
String userLoginId = pullRequest.getUser().getLogin();
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", pullRequest.getUser().getLogin());
context.startActivity(intent);
});
assigneeAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, pullRequest.getUser().getLogin(), context.getString(R.string.copyLoginIdToClipBoard, pullRequest.getUser().getLogin()));
return true;
});
}
@SuppressLint("SetTextI18n")
@ -176,38 +175,30 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(PullRequestsAdapter.OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<PullRequests> list) {
prList = list;
notifyDataSetChanged();
}
}

View File

@ -1,6 +1,7 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.Intent;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
@ -14,6 +15,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.Releases;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
@ -35,6 +37,8 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
static class ReleasesViewHolder extends RecyclerView.ViewHolder {
private Releases releases;
private final TextView releaseType;
private final TextView releaseName;
private final ImageView authorAvatar;
@ -70,6 +74,14 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
downloadList.setHasFixedSize(true);
downloadList.setLayoutManager(new LinearLayoutManager(itemView.getContext()));
authorAvatar.setOnClickListener(loginId -> {
Context context = loginId.getContext();
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", releases.getAuthor().getLogin());
context.startActivity(intent);
});
}
}
@ -94,6 +106,7 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
Releases currentItem = releasesList.get(position);
holder.releases = currentItem;
holder.releaseName.setText(currentItem.getName());

View File

@ -2,6 +2,7 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
@ -11,6 +12,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
@ -26,7 +28,9 @@ public class RepoStargazersAdapter extends BaseAdapter {
private final List<UserInfo> stargazersList;
private final Context context;
private static class ViewHolder {
private class ViewHolder {
private UserInfo userInfo;
private final ImageView memberAvatar;
private final TextView memberName;
@ -34,6 +38,17 @@ public class RepoStargazersAdapter extends BaseAdapter {
ViewHolder(View v) {
memberAvatar = v.findViewById(R.id.memberAvatar);
memberName = v.findViewById(R.id.memberName);
memberAvatar.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userInfo.getLogin());
context.startActivity(intent);
});
memberAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userInfo.getLogin(), context.getString(R.string.copyLoginIdToClipBoard, userInfo.getLogin()));
return true;
});
}
}
@ -80,6 +95,7 @@ public class RepoStargazersAdapter extends BaseAdapter {
private void initData(RepoStargazersAdapter.ViewHolder viewHolder, int position) {
UserInfo currentItem = stargazersList.get(position);
viewHolder.userInfo = currentItem;
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
PicassoService.getInstance(context).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(180, 180).centerCrop().into(viewHolder.memberAvatar);

View File

@ -2,6 +2,7 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
@ -11,6 +12,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
@ -26,7 +28,9 @@ public class RepoWatchersAdapter extends BaseAdapter {
private final List<UserInfo> watchersList;
private final Context context;
private static class ViewHolder {
private class ViewHolder {
private UserInfo userInfo;
private final ImageView memberAvatar;
private final TextView memberName;
@ -34,6 +38,17 @@ public class RepoWatchersAdapter extends BaseAdapter {
ViewHolder(View v) {
memberAvatar = v.findViewById(R.id.memberAvatar);
memberName = v.findViewById(R.id.memberName);
memberAvatar.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userInfo.getLogin());
context.startActivity(intent);
});
memberAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userInfo.getLogin(), context.getString(R.string.copyLoginIdToClipBoard, userInfo.getLogin()));
return true;
});
}
}
@ -80,6 +95,7 @@ public class RepoWatchersAdapter extends BaseAdapter {
private void initData(RepoWatchersAdapter.ViewHolder viewHolder, int position) {
UserInfo currentItem = watchersList.get(position);
viewHolder.userInfo = currentItem;
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
PicassoService.getInstance(context).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(180, 180).centerCrop().into(viewHolder.memberAvatar);

View File

@ -2,6 +2,7 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.text.Html;
import android.view.LayoutInflater;
@ -12,6 +13,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
@ -27,7 +29,7 @@ public class TeamMembersByOrgAdapter extends BaseAdapter {
private final List<UserInfo> teamMembersList;
private final Context context;
private static class ViewHolder {
private class ViewHolder {
private String userLoginId;
@ -40,10 +42,14 @@ public class TeamMembersByOrgAdapter extends BaseAdapter {
memberName = v.findViewById(R.id.memberName);
memberAvatar.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userLoginId);
context.startActivity(intent);
});
Context context = loginId.getContext();
memberAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
return true;
});
}
}

View File

@ -1,6 +1,7 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.util.Log;
import android.view.LayoutInflater;
@ -16,6 +17,7 @@ import org.gitnex.tea4j.models.Collaborators;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.CollaboratorActions;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
@ -42,7 +44,7 @@ public class UserSearchAdapter extends RecyclerView.Adapter<UserSearchAdapter.Us
this.usersSearchList = dataList;
}
static class UserSearchViewHolder extends RecyclerView.ViewHolder {
class UserSearchViewHolder extends RecyclerView.ViewHolder {
private UserInfo userInfo;
@ -65,9 +67,6 @@ public class UserSearchAdapter extends RecyclerView.Adapter<UserSearchAdapter.Us
addCollaboratorButtonRemove = itemView.findViewById(R.id.addCollaboratorButtonRemove);
addCollaboratorButtonAdd.setOnClickListener(v -> {
final Context context = v.getContext();
AlertDialog.Builder pBuilder = new AlertDialog.Builder(context);
pBuilder.setTitle(R.string.newTeamPermission);
@ -89,9 +88,6 @@ public class UserSearchAdapter extends RecyclerView.Adapter<UserSearchAdapter.Us
});
addCollaboratorButtonRemove.setOnClickListener(v -> {
Context context = v.getContext();
AlertDialogs.collaboratorRemoveDialog(context, userInfo.getUsername(),
context.getResources().getString(R.string.removeCollaboratorTitle),
context.getResources().getString(R.string.removeCollaboratorMessage),
@ -99,6 +95,16 @@ public class UserSearchAdapter extends RecyclerView.Adapter<UserSearchAdapter.Us
context.getResources().getString(R.string.cancelButton), "fa");
});
userAvatar.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userInfo.getLogin());
context.startActivity(intent);
});
userAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userInfo.getLogin(), context.getString(R.string.copyLoginIdToClipBoard, userInfo.getLogin()));
return true;
});
}
}

View File

@ -1,6 +1,7 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
@ -11,6 +12,7 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
@ -40,7 +42,7 @@ public class UserSearchForTeamMemberAdapter extends RecyclerView.Adapter<UserSea
UserSearchForTeamMemberAdapter.teamId = teamId;
}
static class UserSearchViewHolder extends RecyclerView.ViewHolder {
class UserSearchViewHolder extends RecyclerView.ViewHolder {
private UserInfo userInfo;
@ -60,9 +62,6 @@ public class UserSearchForTeamMemberAdapter extends RecyclerView.Adapter<UserSea
addMemberButtonRemove = itemView.findViewById(R.id.addCollaboratorButtonRemove);
addMemberButtonAdd.setOnClickListener(v -> {
Context context = v.getContext();
AlertDialogs.addMemberDialog(context, userInfo.getLogin(),
context.getResources().getString(R.string.addTeamMemberTitle),
context.getResources().getString(R.string.addTeamMemberMessage),
@ -71,15 +70,23 @@ public class UserSearchForTeamMemberAdapter extends RecyclerView.Adapter<UserSea
});
addMemberButtonRemove.setOnClickListener(v -> {
Context context = v.getContext();
AlertDialogs.removeMemberDialog(context, userInfo.getLogin(),
context.getResources().getString(R.string.removeTeamMemberTitle),
context.getResources().getString(R.string.removeTeamMemberMessage),
context.getResources().getString(R.string.removeButton),
context.getResources().getString(R.string.cancelButton), Integer.parseInt(String.valueOf(teamId)));
});
userAvatar.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userInfo.getLogin());
context.startActivity(intent);
});
userAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userInfo.getLogin(), context.getString(R.string.copyLoginIdToClipBoard, userInfo.getLogin()));
return true;
});
}
}

View File

@ -0,0 +1,166 @@
package org.mian.gitnex.adapters.profile;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
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.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import java.util.List;
/**
* Author M M Arif
*/
public class FollowersAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private final int TYPE_LOAD = 0;
private List<UserInfo> usersList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public FollowersAdapter(Context ctx, List<UserInfo> usersListMain) {
this.context = ctx;
this.usersList = usersListMain;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new UsersHolder(inflater.inflate(R.layout.list_profile_followers_following, parent, false));
}
else {
return new LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position) == TYPE_LOAD) {
((UsersHolder) holder).bindData(usersList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(usersList.get(position).getUsername() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return usersList.size();
}
class UsersHolder extends RecyclerView.ViewHolder {
private UserInfo userInfo;
private final ImageView userAvatar;
private final TextView userFullName;
private final TextView userName;
UsersHolder(View itemView) {
super(itemView);
Context context = itemView.getContext();
userAvatar = itemView.findViewById(R.id.userAvatar);
userFullName = itemView.findViewById(R.id.userFullName);
userName = itemView.findViewById(R.id.userName);
itemView.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userInfo.getLogin());
context.startActivity(intent);
});
itemView.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userInfo.getLogin(), context.getString(R.string.copyLoginIdToClipBoard, userInfo.getLogin()));
return true;
});
}
@SuppressLint("SetTextI18n")
void bindData(UserInfo userInfo) {
this.userInfo = userInfo;
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
//Locale locale = context.getResources().getConfiguration().locale;
if(!userInfo.getFullname().equals("")) {
userFullName.setText(Html.fromHtml(userInfo.getFullname()));
userName.setText(context.getResources().getString(R.string.usernameWithAt, userInfo.getUsername()));
}
else {
userFullName.setText(userInfo.getUsername());
userName.setVisibility(View.GONE);
}
PicassoService.getInstance(context)
.get()
.load(userInfo.getAvatar())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(imgRadius, 0))
.resize(120, 120)
.centerCrop()
.into(userAvatar);
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<UserInfo> list) {
usersList = list;
notifyDataSetChanged();
}
}

View File

@ -0,0 +1,166 @@
package org.mian.gitnex.adapters.profile;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
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.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import java.util.List;
/**
* Author M M Arif
*/
public class FollowingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private final int TYPE_LOAD = 0;
private List<UserInfo> usersList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public FollowingAdapter(Context ctx, List<UserInfo> usersListMain) {
this.context = ctx;
this.usersList = usersListMain;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new UsersHolder(inflater.inflate(R.layout.list_profile_followers_following, parent, false));
}
else {
return new LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position) == TYPE_LOAD) {
((UsersHolder) holder).bindData(usersList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(usersList.get(position).getUsername() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return usersList.size();
}
class UsersHolder extends RecyclerView.ViewHolder {
private UserInfo userInfo;
private final ImageView userAvatar;
private final TextView userFullName;
private final TextView userName;
UsersHolder(View itemView) {
super(itemView);
Context context = itemView.getContext();
userAvatar = itemView.findViewById(R.id.userAvatar);
userFullName = itemView.findViewById(R.id.userFullName);
userName = itemView.findViewById(R.id.userName);
itemView.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userInfo.getLogin());
context.startActivity(intent);
});
itemView.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userInfo.getLogin(), context.getString(R.string.copyLoginIdToClipBoard, userInfo.getLogin()));
return true;
});
}
@SuppressLint("SetTextI18n")
void bindData(UserInfo userInfo) {
this.userInfo = userInfo;
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
//Locale locale = context.getResources().getConfiguration().locale;
if(!userInfo.getFullname().equals("")) {
userFullName.setText(Html.fromHtml(userInfo.getFullname()));
userName.setText(context.getResources().getString(R.string.usernameWithAt, userInfo.getUsername()));
}
else {
userFullName.setText(userInfo.getUsername());
userName.setVisibility(View.GONE);
}
PicassoService
.getInstance(context)
.get()
.load(userInfo.getAvatar())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(imgRadius, 0))
.resize(120, 120)
.centerCrop()
.into(userAvatar);
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<UserInfo> list) {
usersList = list;
notifyDataSetChanged();
}
}

View File

@ -0,0 +1,137 @@
package org.mian.gitnex.adapters.profile;
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.gitnex.tea4j.models.UserOrganizations;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import java.util.List;
/**
* Author M M Arif
*/
public class OrganizationsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private final int TYPE_LOAD = 0;
private List<UserOrganizations> organizationsList;
private RepositoriesAdapter.OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public OrganizationsAdapter(Context ctx, List<UserOrganizations> organizationsListMain) {
this.context = ctx;
this.organizationsList = organizationsListMain;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new OrganizationsHolder(inflater.inflate(R.layout.list_organizations, parent, false));
}
else {
return new LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position) == TYPE_LOAD) {
((OrganizationsHolder) holder).bindData(organizationsList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(organizationsList.get(position).getUsername() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return organizationsList.size();
}
class OrganizationsHolder extends RecyclerView.ViewHolder {
private UserOrganizations userOrganizations;
private final ImageView image;
private final TextView orgName;
private final TextView orgDescription;
OrganizationsHolder(View itemView) {
super(itemView);
orgName = itemView.findViewById(R.id.orgName);
orgDescription = itemView.findViewById(R.id.orgDescription);
image = itemView.findViewById(R.id.imageAvatar);
}
@SuppressLint("SetTextI18n")
void bindData(UserOrganizations userOrganizations) {
this.userOrganizations = userOrganizations;
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
orgName.setText(userOrganizations.getUsername());
PicassoService.getInstance(context).get().load(userOrganizations.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(image);
if (!userOrganizations.getDescription().equals("")) {
orgDescription.setText(userOrganizations.getDescription());
}
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(RepositoriesAdapter.OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<UserOrganizations> list) {
organizationsList = list;
notifyDataSetChanged();
}
}

View File

@ -0,0 +1,196 @@
package org.mian.gitnex.adapters.profile;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import org.gitnex.tea4j.models.UserRepositories;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import java.util.List;
import java.util.Locale;
/**
* Author M M Arif
*/
public class RepositoriesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private final int TYPE_LOAD = 0;
private List<UserRepositories> reposList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public RepositoriesAdapter(Context ctx, List<UserRepositories> reposListMain) {
this.context = ctx;
this.reposList = reposListMain;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new RepositoriesAdapter.RepositoriesHolder(inflater.inflate(R.layout.list_repositories, parent, false));
}
else {
return new RepositoriesAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position) == TYPE_LOAD) {
((RepositoriesAdapter.RepositoriesHolder) holder).bindData(reposList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(reposList.get(position).getFullName() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return reposList.size();
}
class RepositoriesHolder extends RecyclerView.ViewHolder {
private UserRepositories userRepositories;
private final ImageView avatar;
private final TextView repoName;
private final TextView orgName;
private final TextView repoDescription;
private CheckBox isRepoAdmin;
private final TextView repoStars;
private final TextView repoLastUpdated;
RepositoriesHolder(View itemView) {
super(itemView);
repoName = itemView.findViewById(R.id.repoName);
orgName = itemView.findViewById(R.id.orgName);
repoDescription = itemView.findViewById(R.id.repoDescription);
isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin);
avatar = itemView.findViewById(R.id.imageAvatar);
repoStars = itemView.findViewById(R.id.repoStars);
repoLastUpdated = itemView.findViewById(R.id.repoLastUpdated);
}
@SuppressLint("SetTextI18n")
void bindData(UserRepositories userRepositories) {
this.userRepositories = userRepositories;
TinyDB tinyDb = TinyDB.getInstance(context);
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
Locale locale = context.getResources().getConfiguration().locale;
String timeFormat = tinyDb.getString("dateFormat");
orgName.setText(userRepositories.getFullName().split("/")[0]);
repoName.setText(userRepositories.getFullName().split("/")[1]);
repoStars.setText(userRepositories.getStars_count());
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(userRepositories.getName());
String firstCharacter = String.valueOf(userRepositories.getFullName().charAt(0));
TextDrawable drawable = TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT).fontSize(18).toUpperCase().width(28).height(28).endConfig().buildRoundRect(firstCharacter, color, 3);
if(userRepositories.getAvatar_url() != null) {
if(!userRepositories.getAvatar_url().equals("")) {
PicassoService
.getInstance(context).get().load(userRepositories.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(avatar);
}
else {
avatar.setImageDrawable(drawable);
}
}
else {
avatar.setImageDrawable(drawable);
}
if(userRepositories.getUpdated_at() != null) {
repoLastUpdated.setText(context.getString(R.string.lastUpdatedAt, TimeHelper.formatTime(userRepositories.getUpdated_at(), locale, timeFormat, context)));
if(timeFormat.equals("pretty")) {
repoLastUpdated.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(userRepositories.getUpdated_at()), context));
}
}
else {
repoLastUpdated.setVisibility(View.GONE);
}
if(!userRepositories.getDescription().equals("")) {
repoDescription.setText(userRepositories.getDescription());
}
else {
repoDescription.setText(context.getString(R.string.noDataDescription));
}
if(isRepoAdmin == null) {
isRepoAdmin = new CheckBox(context);
}
isRepoAdmin.setChecked(userRepositories.getPermissions().isAdmin());
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<UserRepositories> list) {
reposList = list;
notifyDataSetChanged();
}
}

View File

@ -0,0 +1,197 @@
package org.mian.gitnex.adapters.profile;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import org.gitnex.tea4j.models.UserRepositories;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import java.util.List;
import java.util.Locale;
/**
* Author M M Arif
*/
public class StarredRepositoriesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private final int TYPE_LOAD = 0;
private List<UserRepositories> reposList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public StarredRepositoriesAdapter(Context ctx, List<UserRepositories> reposListMain) {
this.context = ctx;
this.reposList = reposListMain;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new StarredRepositoriesAdapter.StarredRepositoriesHolder(inflater.inflate(R.layout.list_repositories, parent, false));
}
else {
return new StarredRepositoriesAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position) == TYPE_LOAD) {
((StarredRepositoriesAdapter.StarredRepositoriesHolder) holder).bindData(reposList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(reposList.get(position).getFullName() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return reposList.size();
}
class StarredRepositoriesHolder extends RecyclerView.ViewHolder {
private UserRepositories userRepositories;
private final ImageView avatar;
private final TextView repoName;
private final TextView orgName;
private final TextView repoDescription;
private CheckBox isRepoAdmin;
private final TextView repoStars;
private final TextView repoLastUpdated;
StarredRepositoriesHolder(View itemView) {
super(itemView);
repoName = itemView.findViewById(R.id.repoName);
orgName = itemView.findViewById(R.id.orgName);
repoDescription = itemView.findViewById(R.id.repoDescription);
isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin);
avatar = itemView.findViewById(R.id.imageAvatar);
repoStars = itemView.findViewById(R.id.repoStars);
repoLastUpdated = itemView.findViewById(R.id.repoLastUpdated);
}
@SuppressLint("SetTextI18n")
void bindData(UserRepositories userRepositories) {
this.userRepositories = userRepositories;
TinyDB tinyDb = TinyDB.getInstance(context);
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
Locale locale = context.getResources().getConfiguration().locale;
String timeFormat = tinyDb.getString("dateFormat");
orgName.setText(userRepositories.getFullName().split("/")[0]);
repoName.setText(userRepositories.getFullName().split("/")[1]);
repoStars.setText(userRepositories.getStars_count());
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(userRepositories.getName());
String firstCharacter = String.valueOf(userRepositories.getFullName().charAt(0));
TextDrawable drawable = TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT).fontSize(18).toUpperCase().width(28).height(28).endConfig().buildRoundRect(firstCharacter, color, 3);
if(userRepositories.getAvatar_url() != null) {
if(!userRepositories.getAvatar_url().equals("")) {
PicassoService
.getInstance(context).get().load(userRepositories.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(avatar);
}
else {
avatar.setImageDrawable(drawable);
}
}
else {
avatar.setImageDrawable(drawable);
}
if(userRepositories.getUpdated_at() != null) {
repoLastUpdated.setText(context.getString(R.string.lastUpdatedAt, TimeHelper
.formatTime(userRepositories.getUpdated_at(), locale, timeFormat, context)));
if(timeFormat.equals("pretty")) {
repoLastUpdated.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(userRepositories.getUpdated_at()), context));
}
}
else {
repoLastUpdated.setVisibility(View.GONE);
}
if(!userRepositories.getDescription().equals("")) {
repoDescription.setText(userRepositories.getDescription());
}
else {
repoDescription.setText(context.getString(R.string.noDataDescription));
}
if(isRepoAdmin == null) {
isRepoAdmin = new CheckBox(context);
}
isRepoAdmin.setChecked(userRepositories.getPermissions().isAdmin());
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<UserRepositories> list) {
reposList = list;
notifyDataSetChanged();
}
}

View File

@ -8,14 +8,14 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import org.mian.gitnex.activities.ProfileEmailActivity;
import org.mian.gitnex.activities.MyProfileEmailActivity;
import org.mian.gitnex.databinding.BottomSheetProfileBinding;
/**
* Author M M Arif
*/
public class BottomSheetProfileFragment extends BottomSheetDialogFragment {
public class BottomSheetMyProfileFragment extends BottomSheetDialogFragment {
@Nullable
@Override
@ -25,7 +25,7 @@ public class BottomSheetProfileFragment extends BottomSheetDialogFragment {
bottomSheetProfileBinding.addNewEmailAddress.setOnClickListener(v1 -> {
startActivity(new Intent(getContext(), ProfileEmailActivity.class));
startActivity(new Intent(getContext(), MyProfileEmailActivity.class));
dismiss();
});

View File

@ -18,7 +18,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.gitnex.tea4j.models.Emails;
import org.mian.gitnex.adapters.ProfileEmailsAdapter;
import org.mian.gitnex.adapters.MyProfileEmailsAdapter;
import org.mian.gitnex.databinding.FragmentProfileEmailsBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.viewmodels.ProfileEmailsViewModel;
@ -28,10 +28,10 @@ import java.util.List;
* Author M M Arif
*/
public class ProfileEmailsFragment extends Fragment {
public class MyProfileEmailsFragment extends Fragment {
private ProgressBar mProgressBar;
private ProfileEmailsAdapter adapter;
private MyProfileEmailsAdapter adapter;
private RecyclerView mRecyclerView;
private TextView noDataEmails;
private static String repoNameF = "param2";
@ -42,11 +42,11 @@ public class ProfileEmailsFragment extends Fragment {
private OnFragmentInteractionListener mListener;
public ProfileEmailsFragment() {
public MyProfileEmailsFragment() {
}
public static ProfileEmailsFragment newInstance(String param1, String param2) {
ProfileEmailsFragment fragment = new ProfileEmailsFragment();
public static MyProfileEmailsFragment newInstance(String param1, String param2) {
MyProfileEmailsFragment fragment = new MyProfileEmailsFragment();
Bundle args = new Bundle();
args.putString(repoOwnerF, param1);
args.putString(repoNameF, param2);
@ -102,7 +102,7 @@ public class ProfileEmailsFragment extends Fragment {
profileEmailModel.getEmailsList(instanceToken, getContext()).observe(getViewLifecycleOwner(), new Observer<List<Emails>>() {
@Override
public void onChanged(@Nullable List<Emails> emailsListMain) {
adapter = new ProfileEmailsAdapter(getContext(), emailsListMain);
adapter = new MyProfileEmailsAdapter(getContext(), emailsListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
noDataEmails.setVisibility(View.GONE);

View File

@ -16,8 +16,8 @@ import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.mian.gitnex.adapters.ProfileFollowersAdapter;
import org.mian.gitnex.databinding.FragmentProfileFollowersBinding;
import org.mian.gitnex.adapters.MyProfileFollowersAdapter;
import org.mian.gitnex.databinding.FragmentProfileFollowersFollowingBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.viewmodels.ProfileFollowersViewModel;
@ -25,10 +25,10 @@ import org.mian.gitnex.viewmodels.ProfileFollowersViewModel;
* Author M M Arif
*/
public class ProfileFollowersFragment extends Fragment {
public class MyProfileFollowersFragment extends Fragment {
private ProgressBar mProgressBar;
private ProfileFollowersAdapter adapter;
private MyProfileFollowersAdapter adapter;
private RecyclerView mRecyclerView;
private TextView noDataFollowers;
private static String repoNameF = "param2";
@ -39,11 +39,11 @@ public class ProfileFollowersFragment extends Fragment {
private OnFragmentInteractionListener mListener;
public ProfileFollowersFragment() {
public MyProfileFollowersFragment() {
}
public static ProfileFollowersFragment newInstance(String param1, String param2) {
ProfileFollowersFragment fragment = new ProfileFollowersFragment();
public static MyProfileFollowersFragment newInstance(String param1, String param2) {
MyProfileFollowersFragment fragment = new MyProfileFollowersFragment();
Bundle args = new Bundle();
args.putString(repoOwnerF, param1);
args.putString(repoNameF, param2);
@ -64,12 +64,12 @@ public class ProfileFollowersFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
FragmentProfileFollowersBinding fragmentProfileFollowersBinding = FragmentProfileFollowersBinding.inflate(inflater, container, false);
FragmentProfileFollowersFollowingBinding fragmentProfileFollowersFollowingBinding = FragmentProfileFollowersFollowingBinding.inflate(inflater, container, false);
final SwipeRefreshLayout swipeRefresh = fragmentProfileFollowersBinding.pullToRefresh;
final SwipeRefreshLayout swipeRefresh = fragmentProfileFollowersFollowingBinding.pullToRefresh;
noDataFollowers = fragmentProfileFollowersBinding.noDataFollowers;
mRecyclerView = fragmentProfileFollowersBinding.recyclerView;
noDataFollowers = fragmentProfileFollowersFollowingBinding.noData;
mRecyclerView = fragmentProfileFollowersFollowingBinding.recyclerView;
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL);
@ -77,7 +77,7 @@ public class ProfileFollowersFragment extends Fragment {
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.addItemDecoration(dividerItemDecoration);
mProgressBar = fragmentProfileFollowersBinding.progressBar;
mProgressBar = fragmentProfileFollowersFollowingBinding.progressBar;
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
@ -88,7 +88,7 @@ public class ProfileFollowersFragment extends Fragment {
fetchDataAsync(Authorization.get(getContext()));
return fragmentProfileFollowersBinding.getRoot();
return fragmentProfileFollowersFollowingBinding.getRoot();
}
private void fetchDataAsync(String instanceToken) {
@ -97,7 +97,7 @@ public class ProfileFollowersFragment extends Fragment {
pfModel.getFollowersList(instanceToken, getContext()).observe(getViewLifecycleOwner(), pfListMain -> {
adapter = new ProfileFollowersAdapter(getContext(), pfListMain);
adapter = new MyProfileFollowersAdapter(getContext(), pfListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);

View File

@ -16,8 +16,8 @@ import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.mian.gitnex.adapters.ProfileFollowingAdapter;
import org.mian.gitnex.databinding.FragmentProfileFollowingBinding;
import org.mian.gitnex.adapters.MyProfileFollowingAdapter;
import org.mian.gitnex.databinding.FragmentProfileFollowersFollowingBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.viewmodels.ProfileFollowingViewModel;
@ -26,25 +26,25 @@ import org.mian.gitnex.viewmodels.ProfileFollowingViewModel;
* Author M M Arif
*/
public class ProfileFollowingFragment extends Fragment {
public class MyProfileFollowingFragment extends Fragment {
private ProgressBar mProgressBar;
private ProfileFollowingAdapter adapter;
private MyProfileFollowingAdapter adapter;
private RecyclerView mRecyclerView;
private TextView noDataFollowing;
private static String repoNameF = "param2";
private static String repoOwnerF = "param1";
private static final String repoNameF = "param2";
private static final String repoOwnerF = "param1";
private String repoName;
private String repoOwner;
private OnFragmentInteractionListener mListener;
public ProfileFollowingFragment() {
public MyProfileFollowingFragment() {
}
public static ProfileFollowingFragment newInstance(String param1, String param2) {
ProfileFollowingFragment fragment = new ProfileFollowingFragment();
public static MyProfileFollowingFragment newInstance(String param1, String param2) {
MyProfileFollowingFragment fragment = new MyProfileFollowingFragment();
Bundle args = new Bundle();
args.putString(repoOwnerF, param1);
args.putString(repoNameF, param2);
@ -65,14 +65,14 @@ public class ProfileFollowingFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
FragmentProfileFollowingBinding fragmentProfileFollowingBinding = FragmentProfileFollowingBinding.inflate(inflater, container, false);
FragmentProfileFollowersFollowingBinding fragmentProfileFollowersFollowingBinding = FragmentProfileFollowersFollowingBinding.inflate(inflater, container, false);
TinyDB tinyDb = TinyDB.getInstance(getContext());
final SwipeRefreshLayout swipeRefresh = fragmentProfileFollowingBinding.pullToRefresh;
final SwipeRefreshLayout swipeRefresh = fragmentProfileFollowersFollowingBinding.pullToRefresh;
noDataFollowing = fragmentProfileFollowingBinding.noDataFollowing;
mRecyclerView = fragmentProfileFollowingBinding.recyclerView;
noDataFollowing = fragmentProfileFollowersFollowingBinding.noData;
mRecyclerView = fragmentProfileFollowersFollowingBinding.recyclerView;
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL);
@ -80,7 +80,7 @@ public class ProfileFollowingFragment extends Fragment {
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.addItemDecoration(dividerItemDecoration);
mProgressBar = fragmentProfileFollowingBinding.progressBar;
mProgressBar = fragmentProfileFollowersFollowingBinding.progressBar;
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
@ -91,7 +91,7 @@ public class ProfileFollowingFragment extends Fragment {
fetchDataAsync(Authorization.get(getContext()));
return fragmentProfileFollowingBinding.getRoot();
return fragmentProfileFollowersFollowingBinding.getRoot();
}
private void fetchDataAsync(String instanceToken) {
@ -100,7 +100,7 @@ public class ProfileFollowingFragment extends Fragment {
pfModel.getFollowingList(instanceToken, getContext()).observe(getViewLifecycleOwner(), pfListMain -> {
adapter = new ProfileFollowingAdapter(getContext(), pfListMain);
adapter = new MyProfileFollowingAdapter(getContext(), pfListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);

View File

@ -36,7 +36,7 @@ import jp.wasabeef.picasso.transformations.BlurTransformation;
* Author M M Arif
*/
public class ProfileFragment extends Fragment {
public class MyProfileFragment extends Fragment {
private Context ctx;
@ -61,18 +61,14 @@ public class ProfileFragment extends Fragment {
TextView userLanguage = v.findViewById(R.id.userLanguage);
ImageView userLanguageIcon = v.findViewById(R.id.userLanguageIcon);
ViewGroup aboutFrame = v.findViewById(R.id.aboutFrame);
String[] userLanguageCodes = tinyDb.getString("userLang").split("-");
if(userLanguageCodes.length >= 2) {
Locale locale = new Locale(userLanguageCodes[0], userLanguageCodes[1]);
userLanguage.setText(locale.getDisplayLanguage());
}
else {
userLanguage.setText(R.string.notSupported);
userLanguage.setText(getResources().getConfiguration().locale.getDisplayLanguage());
}
userAvatar.setOnClickListener(loginId ->
@ -112,7 +108,7 @@ public class ProfileFragment extends Fragment {
@Override public void onError(Exception e) {}
});
ProfileFragment.SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
MyProfileFragment.SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
ViewPager mViewPager = v.findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
@ -159,7 +155,6 @@ public class ProfileFragment extends Fragment {
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
return v;
}
public static class SectionsPagerAdapter extends FragmentStatePagerAdapter {
@ -175,25 +170,23 @@ public class ProfileFragment extends Fragment {
switch (position) {
case 0: // followers
return ProfileFollowersFragment.newInstance("repoOwner", "repoName");
return MyProfileFollowersFragment.newInstance("repoOwner", "repoName");
case 1: // following
return ProfileFollowingFragment.newInstance("repoOwner", "repoName");
return MyProfileFollowingFragment.newInstance("repoOwner", "repoName");
case 2: // emails
return ProfileEmailsFragment.newInstance("repoOwner", "repoName");
return MyProfileEmailsFragment.newInstance("repoOwner", "repoName");
}
return null;
}
@Override
public int getCount() {
return 3;
}
}
@Override
@ -202,7 +195,6 @@ public class ProfileFragment extends Fragment {
menu.clear();
requireActivity().getMenuInflater().inflate(R.menu.profile_dotted_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
@ -210,21 +202,18 @@ public class ProfileFragment extends Fragment {
int id = item.getItemId();
switch (id) {
case android.R.id.home:
((MainActivity)ctx).finish();
return true;
case R.id.profileMenu:
BottomSheetProfileFragment bottomSheet = new BottomSheetProfileFragment();
bottomSheet.show(getChildFragmentManager(), "profileBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
if(id == android.R.id.home) {
((MainActivity)ctx).finish();
return true;
}
else if(id == R.id.profileMenu) {
BottomSheetMyProfileFragment bottomSheet = new BottomSheetMyProfileFragment();
bottomSheet.show(getChildFragmentManager(), "profileBottomSheet");
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
}

View File

@ -69,7 +69,6 @@ public class RepositoriesFragment extends Fragment {
createNewRepo = fragmentRepositoriesBinding.addNewRepo;
createNewRepo.setOnClickListener(view -> {
Intent intent = new Intent(view.getContext(), CreateRepoActivity.class);
startActivity(intent);
});
@ -79,9 +78,9 @@ public class RepositoriesFragment extends Fragment {
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
if (dy > 0 && createNewRepo.isShown()) {
createNewRepo.setVisibility(View.GONE);
} else if (dy < 0 ) {
}
else if (dy < 0 ) {
createNewRepo.setVisibility(View.VISIBLE);
}
}
@ -135,7 +134,6 @@ public class RepositoriesFragment extends Fragment {
}
mProgressBar.setVisibility(View.GONE);
});
}
@Override
@ -147,11 +145,6 @@ public class RepositoriesFragment extends Fragment {
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
//searchView.setQueryHint(getContext().getString(R.string.strFilter));
/*if(!connToInternet) {
return;
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
@ -167,7 +160,6 @@ public class RepositoriesFragment extends Fragment {
return false;
}
});
}
}

View File

@ -0,0 +1,160 @@
package org.mian.gitnex.fragments.profile;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentProfileDetailBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.ColorInverter;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.Locale;
import jp.wasabeef.picasso.transformations.BlurTransformation;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class DetailFragment extends Fragment {
private Context context;
private FragmentProfileDetailBinding binding;
Locale locale;
TinyDB tinyDb;
private static final String usernameBundle = "";
private String username;
public DetailFragment() {}
public static DetailFragment newInstance(String username) {
DetailFragment fragment = new DetailFragment();
Bundle args = new Bundle();
args.putString(usernameBundle, username);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
username = getArguments().getString(usernameBundle);
}
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentProfileDetailBinding.inflate(inflater, container, false);
context = getContext();
tinyDb = TinyDB.getInstance(context);
locale = getResources().getConfiguration().locale;
getProfileDetail(username);
return binding.getRoot();
}
public void getProfileDetail(String username) {
Call<UserInfo> call = RetrofitClient
.getApiInterface(context)
.getUserProfile(Authorization.get(context), username);
call.enqueue(new Callback<UserInfo>() {
@Override
public void onResponse(@NonNull Call<UserInfo> call, @NonNull retrofit2.Response<UserInfo> response) {
if(response.isSuccessful() && response.body() != null) {
switch(response.code()) {
case 200:
String username = !response.body().getFullname().isEmpty() ? response.body().getFullname() : response.body().getUsername();
String email = !response.body().getEmail().isEmpty() ? response.body().getEmail() : "";
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
String timeFormat = tinyDb.getString("dateFormat");
binding.userFullName.setText(username);
binding.userLogin.setText(getString(R.string.usernameWithAt, response.body().getLogin()));
binding.userEmail.setText(email);
String[] userLanguageCodes = response.body().getLang().split("-");
if(userLanguageCodes.length >= 2) {
Locale locale = new Locale(userLanguageCodes[0], userLanguageCodes[1]);
binding.userLang.setText(locale.getDisplayLanguage());
}
else {
binding.userLang.setText(locale.getDisplayLanguage());
}
PicassoService.getInstance(context).get()
.load(response.body().getAvatar())
.transform(new RoundedTransformation(imgRadius, 0))
.placeholder(R.drawable.loader_animated)
.resize(120, 120)
.centerCrop()
.into(binding.userAvatar);
PicassoService.getInstance(context).get()
.load(response.body().getAvatar())
.transform(new BlurTransformation(context))
.into(binding.userAvatarBackground, new com.squareup.picasso.Callback() {
@Override
public void onSuccess() {
int invertedColor = new ColorInverter().getImageViewContrastColor(binding.userAvatarBackground);
binding.userFullName.setTextColor(invertedColor);
binding.userLogin.setTextColor(invertedColor);
}
@Override public void onError(Exception e) {}
});
binding.userJoinedOn.setText(TimeHelper.formatTime(response.body().getCreated(), locale, timeFormat, context));
if(timeFormat.equals("pretty")) {
binding.userJoinedOn.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(response.body().getCreated()), context));
}
break;
case 401:
AlertDialogs
.authorizationTokenRevokedDialog(context, context.getResources().getString(R.string.alertDialogTokenRevokedTitle), context.getResources().getString(R.string.alertDialogTokenRevokedMessage), context.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), context.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(context, context.getString(R.string.authorizeError));
break;
default:
Toasty.error(context, getString(R.string.genericError));
break;
}
}
}
@Override
public void onFailure(@NonNull Call<UserInfo> call, @NonNull Throwable t) {
Toasty.error(context, context.getResources().getString(R.string.genericError));
}
});
}
}

View File

@ -0,0 +1,272 @@
package org.mian.gitnex.fragments.profile;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.profile.FollowersAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentProfileFollowersFollowingBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class FollowersFragment extends Fragment {
private Context context;
private FragmentProfileFollowersFollowingBinding fragmentProfileFollowersFollowingBinding;
private List<UserInfo> usersList;
private FollowersAdapter adapter;
private int pageSize;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private static final String usernameBundle = "";
private String username;
public FollowersFragment() {}
public static FollowersFragment newInstance(String username) {
FollowersFragment fragment = new FollowersFragment();
Bundle args = new Bundle();
args.putString(usernameBundle, username);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
username = getArguments().getString(usernameBundle);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
fragmentProfileFollowersFollowingBinding = FragmentProfileFollowersFollowingBinding.inflate(inflater, container, false);
setHasOptionsMenu(true);
context = getContext();
TinyDB tinyDb = TinyDB.getInstance(context);
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = Constants.resultLimitNewGiteaInstances;
}
usersList = new ArrayList<>();
fragmentProfileFollowersFollowingBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
fragmentProfileFollowersFollowingBinding.pullToRefresh.setRefreshing(false);
loadInitial(Authorization.get(context), username, resultLimit);
adapter.notifyDataChanged();
}, 200));
adapter = new FollowersAdapter(context, usersList);
adapter.setLoadMoreListener(() -> fragmentProfileFollowersFollowingBinding.recyclerView.post(() -> {
if(usersList.size() == resultLimit || pageSize == resultLimit) {
int page = (usersList.size() + resultLimit) / resultLimit;
loadMore(Authorization.get(context), username, page, resultLimit);
}
}));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
fragmentProfileFollowersFollowingBinding.recyclerView.setHasFixedSize(true);
fragmentProfileFollowersFollowingBinding.recyclerView.addItemDecoration(dividerItemDecoration);
fragmentProfileFollowersFollowingBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context));
fragmentProfileFollowersFollowingBinding.recyclerView.setAdapter(adapter);
loadInitial(Authorization.get(context), username, resultLimit);
return fragmentProfileFollowersFollowingBinding.getRoot();
}
private void loadInitial(String token, String username, int resultLimit) {
Call<List<UserInfo>> call = RetrofitClient
.getApiInterface(context)
.getUserFollowers(token, username, 1, resultLimit);
call.enqueue(new Callback<List<UserInfo>>() {
@Override
public void onResponse(@NonNull Call<List<UserInfo>> call, @NonNull Response<List<UserInfo>> response) {
if(response.isSuccessful()) {
switch(response.code()) {
case 200:
assert response.body() != null;
if(response.body().size() > 0) {
usersList.clear();
usersList.addAll(response.body());
adapter.notifyDataChanged();
fragmentProfileFollowersFollowingBinding.noData.setVisibility(View.GONE);
}
else {
usersList.clear();
adapter.notifyDataChanged();
fragmentProfileFollowersFollowingBinding.noData.setVisibility(View.VISIBLE);
}
fragmentProfileFollowersFollowingBinding.progressBar.setVisibility(View.GONE);
break;
case 401:
AlertDialogs.authorizationTokenRevokedDialog(context, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(context, context.getString(R.string.authorizeError));
break;
case 404:
fragmentProfileFollowersFollowingBinding.noData.setVisibility(View.VISIBLE);
fragmentProfileFollowersFollowingBinding.progressBar.setVisibility(View.GONE);
break;
default:
Toasty.error(context, getString(R.string.genericError));
break;
}
}
}
@Override
public void onFailure(@NonNull Call<List<UserInfo>> call, @NonNull Throwable t) {
Toasty.error(context, getString(R.string.genericError));
}
});
}
private void loadMore(String token, String username, int page, int resultLimit) {
fragmentProfileFollowersFollowingBinding.progressLoadMore.setVisibility(View.VISIBLE);
Call<List<UserInfo>> call = RetrofitClient
.getApiInterface(context)
.getUserFollowers(token, username, page, resultLimit);
call.enqueue(new Callback<List<UserInfo>>() {
@Override
public void onResponse(@NonNull Call<List<UserInfo>> call, @NonNull Response<List<UserInfo>> response) {
if(response.isSuccessful()) {
switch(response.code()) {
case 200:
List<UserInfo> result = response.body();
assert result != null;
if(result.size() > 0) {
pageSize = result.size();
usersList.addAll(result);
}
else {
SnackBar.info(context, fragmentProfileFollowersFollowingBinding.getRoot(), getString(R.string.noMoreData));
adapter.setMoreDataAvailable(false);
}
adapter.notifyDataChanged();
fragmentProfileFollowersFollowingBinding.progressLoadMore.setVisibility(View.GONE);
break;
case 401:
AlertDialogs.authorizationTokenRevokedDialog(context, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(context, context.getString(R.string.authorizeError));
break;
case 404:
fragmentProfileFollowersFollowingBinding.noData.setVisibility(View.VISIBLE);
fragmentProfileFollowersFollowingBinding.progressBar.setVisibility(View.GONE);
break;
default:
Toasty.error(context, getString(R.string.genericError));
break;
}
}
}
@Override
public void onFailure(@NonNull Call<List<UserInfo>> call, @NonNull Throwable t) {
Toasty.error(context, getString(R.string.genericError));
}
});
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
filter(newText);
return false;
}
});
}
private void filter(String text) {
List<UserInfo> arr = new ArrayList<>();
for(UserInfo d : usersList) {
if(d == null || d.getUsername() == null || d.getFullname() == null) {
continue;
}
if(d.getUsername().toLowerCase().contains(text) || d.getFullname().toLowerCase().contains(text)) {
arr.add(d);
}
}
adapter.updateList(arr);
}
}

View File

@ -0,0 +1,273 @@
package org.mian.gitnex.fragments.profile;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.profile.FollowersAdapter;
import org.mian.gitnex.adapters.profile.FollowingAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentProfileFollowersFollowingBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class FollowingFragment extends Fragment {
private Context context;
private FragmentProfileFollowersFollowingBinding fragmentProfileFollowersFollowingBinding;
private List<UserInfo> usersList;
private FollowingAdapter adapter;
private int pageSize;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private static final String usernameBundle = "";
private String username;
public FollowingFragment() {}
public static FollowingFragment newInstance(String username) {
FollowingFragment fragment = new FollowingFragment();
Bundle args = new Bundle();
args.putString(usernameBundle, username);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
username = getArguments().getString(usernameBundle);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
fragmentProfileFollowersFollowingBinding = FragmentProfileFollowersFollowingBinding.inflate(inflater, container, false);
setHasOptionsMenu(true);
context = getContext();
TinyDB tinyDb = TinyDB.getInstance(context);
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = Constants.resultLimitNewGiteaInstances;
}
usersList = new ArrayList<>();
fragmentProfileFollowersFollowingBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
fragmentProfileFollowersFollowingBinding.pullToRefresh.setRefreshing(false);
loadInitial(Authorization.get(context), username, resultLimit);
adapter.notifyDataChanged();
}, 200));
adapter = new FollowingAdapter(context, usersList);
adapter.setLoadMoreListener(() -> fragmentProfileFollowersFollowingBinding.recyclerView.post(() -> {
if(usersList.size() == resultLimit || pageSize == resultLimit) {
int page = (usersList.size() + resultLimit) / resultLimit;
loadMore(Authorization.get(context), username, page, resultLimit);
}
}));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
fragmentProfileFollowersFollowingBinding.recyclerView.setHasFixedSize(true);
fragmentProfileFollowersFollowingBinding.recyclerView.addItemDecoration(dividerItemDecoration);
fragmentProfileFollowersFollowingBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context));
fragmentProfileFollowersFollowingBinding.recyclerView.setAdapter(adapter);
loadInitial(Authorization.get(context), username, resultLimit);
return fragmentProfileFollowersFollowingBinding.getRoot();
}
private void loadInitial(String token, String username, int resultLimit) {
Call<List<UserInfo>> call = RetrofitClient
.getApiInterface(context)
.getUserFollowing(token, username, 1, resultLimit);
call.enqueue(new Callback<List<UserInfo>>() {
@Override
public void onResponse(@NonNull Call<List<UserInfo>> call, @NonNull Response<List<UserInfo>> response) {
if(response.isSuccessful()) {
switch(response.code()) {
case 200:
assert response.body() != null;
if(response.body().size() > 0) {
usersList.clear();
usersList.addAll(response.body());
adapter.notifyDataChanged();
fragmentProfileFollowersFollowingBinding.noData.setVisibility(View.GONE);
}
else {
usersList.clear();
adapter.notifyDataChanged();
fragmentProfileFollowersFollowingBinding.noData.setVisibility(View.VISIBLE);
}
fragmentProfileFollowersFollowingBinding.progressBar.setVisibility(View.GONE);
break;
case 401:
AlertDialogs.authorizationTokenRevokedDialog(context, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(context, context.getString(R.string.authorizeError));
break;
case 404:
fragmentProfileFollowersFollowingBinding.noData.setVisibility(View.VISIBLE);
fragmentProfileFollowersFollowingBinding.progressBar.setVisibility(View.GONE);
break;
default:
Toasty.error(context, getString(R.string.genericError));
break;
}
}
}
@Override
public void onFailure(@NonNull Call<List<UserInfo>> call, @NonNull Throwable t) {
Toasty.error(context, getString(R.string.genericError));
}
});
}
private void loadMore(String token, String username, int page, int resultLimit) {
fragmentProfileFollowersFollowingBinding.progressLoadMore.setVisibility(View.VISIBLE);
Call<List<UserInfo>> call = RetrofitClient
.getApiInterface(context)
.getUserFollowing(token, username, page, resultLimit);
call.enqueue(new Callback<List<UserInfo>>() {
@Override
public void onResponse(@NonNull Call<List<UserInfo>> call, @NonNull Response<List<UserInfo>> response) {
if(response.isSuccessful()) {
switch(response.code()) {
case 200:
List<UserInfo> result = response.body();
assert result != null;
if(result.size() > 0) {
pageSize = result.size();
usersList.addAll(result);
}
else {
SnackBar.info(context, fragmentProfileFollowersFollowingBinding.getRoot(), getString(R.string.noMoreData));
adapter.setMoreDataAvailable(false);
}
adapter.notifyDataChanged();
fragmentProfileFollowersFollowingBinding.progressLoadMore.setVisibility(View.GONE);
break;
case 401:
AlertDialogs.authorizationTokenRevokedDialog(context, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(context, context.getString(R.string.authorizeError));
break;
case 404:
fragmentProfileFollowersFollowingBinding.noData.setVisibility(View.VISIBLE);
fragmentProfileFollowersFollowingBinding.progressBar.setVisibility(View.GONE);
break;
default:
Toasty.error(context, getString(R.string.genericError));
break;
}
}
}
@Override
public void onFailure(@NonNull Call<List<UserInfo>> call, @NonNull Throwable t) {
Toasty.error(context, getString(R.string.genericError));
}
});
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
filter(newText);
return false;
}
});
}
private void filter(String text) {
List<UserInfo> arr = new ArrayList<>();
for(UserInfo d : usersList) {
if(d == null || d.getUsername() == null || d.getFullname() == null) {
continue;
}
if(d.getUsername().toLowerCase().contains(text) || d.getFullname().toLowerCase().contains(text)) {
arr.add(d);
}
}
adapter.updateList(arr);
}
}

View File

@ -0,0 +1,274 @@
package org.mian.gitnex.fragments.profile;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import org.gitnex.tea4j.models.UserOrganizations;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.profile.OrganizationsAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentOrganizationsBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class OrganizationsFragment extends Fragment {
private Context context;
private FragmentOrganizationsBinding fragmentOrganizationsBinding;
private List<UserOrganizations> organizationsList;
private OrganizationsAdapter adapter;
private int pageSize;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private static final String usernameBundle = "";
private String username;
public OrganizationsFragment() {}
public static OrganizationsFragment newInstance(String username) {
OrganizationsFragment fragment = new OrganizationsFragment();
Bundle args = new Bundle();
args.putString(usernameBundle, username);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
username = getArguments().getString(usernameBundle);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
fragmentOrganizationsBinding = FragmentOrganizationsBinding.inflate(inflater, container, false);
setHasOptionsMenu(true);
context = getContext();
TinyDB tinyDb = TinyDB.getInstance(context);
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = Constants.resultLimitNewGiteaInstances;
}
organizationsList = new ArrayList<>();
fragmentOrganizationsBinding.addNewOrganization.setVisibility(View.GONE);
fragmentOrganizationsBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
fragmentOrganizationsBinding.pullToRefresh.setRefreshing(false);
loadInitial(Authorization.get(context), username, resultLimit);
adapter.notifyDataChanged();
}, 200));
adapter = new OrganizationsAdapter(context, organizationsList);
adapter.setLoadMoreListener(() -> fragmentOrganizationsBinding.recyclerView.post(() -> {
if(organizationsList.size() == resultLimit || pageSize == resultLimit) {
int page = (organizationsList.size() + resultLimit) / resultLimit;
loadMore(Authorization.get(context), username, page, resultLimit);
}
}));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
fragmentOrganizationsBinding.recyclerView.setHasFixedSize(true);
fragmentOrganizationsBinding.recyclerView.addItemDecoration(dividerItemDecoration);
fragmentOrganizationsBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context));
fragmentOrganizationsBinding.recyclerView.setAdapter(adapter);
loadInitial(Authorization.get(context), username, resultLimit);
return fragmentOrganizationsBinding.getRoot();
}
private void loadInitial(String token, String username, int resultLimit) {
Call<List<UserOrganizations>> call = RetrofitClient
.getApiInterface(context)
.getUserProfileOrganizations(token, username, 1, resultLimit);
call.enqueue(new Callback<List<UserOrganizations>>() {
@Override
public void onResponse(@NonNull Call<List<UserOrganizations>> call, @NonNull Response<List<UserOrganizations>> response) {
if(response.isSuccessful()) {
switch(response.code()) {
case 200:
assert response.body() != null;
if(response.body().size() > 0) {
organizationsList.clear();
organizationsList.addAll(response.body());
adapter.notifyDataChanged();
fragmentOrganizationsBinding.noDataOrg.setVisibility(View.GONE);
}
else {
organizationsList.clear();
adapter.notifyDataChanged();
fragmentOrganizationsBinding.noDataOrg.setVisibility(View.VISIBLE);
}
fragmentOrganizationsBinding.progressBar.setVisibility(View.GONE);
break;
case 401:
AlertDialogs.authorizationTokenRevokedDialog(context, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(context, context.getString(R.string.authorizeError));
break;
case 404:
fragmentOrganizationsBinding.noDataOrg.setVisibility(View.VISIBLE);
fragmentOrganizationsBinding.progressBar.setVisibility(View.GONE);
break;
default:
Toasty.error(context, getString(R.string.genericError));
break;
}
}
}
@Override
public void onFailure(@NonNull Call<List<UserOrganizations>> call, @NonNull Throwable t) {
Toasty.error(context, getString(R.string.genericError));
}
});
}
private void loadMore(String token, String username, int page, int resultLimit) {
fragmentOrganizationsBinding.progressLoadMore.setVisibility(View.VISIBLE);
Call<List<UserOrganizations>> call = RetrofitClient
.getApiInterface(context)
.getUserProfileOrganizations(token, username, page, resultLimit);
call.enqueue(new Callback<List<UserOrganizations>>() {
@Override
public void onResponse(@NonNull Call<List<UserOrganizations>> call, @NonNull Response<List<UserOrganizations>> response) {
if(response.isSuccessful()) {
switch(response.code()) {
case 200:
List<UserOrganizations> result = response.body();
assert result != null;
if(result.size() > 0) {
pageSize = result.size();
organizationsList.addAll(result);
}
else {
SnackBar.info(context, fragmentOrganizationsBinding.getRoot(), getString(R.string.noMoreData));
adapter.setMoreDataAvailable(false);
}
adapter.notifyDataChanged();
fragmentOrganizationsBinding.progressLoadMore.setVisibility(View.GONE);
break;
case 401:
AlertDialogs.authorizationTokenRevokedDialog(context, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(context, context.getString(R.string.authorizeError));
break;
case 404:
fragmentOrganizationsBinding.noDataOrg.setVisibility(View.VISIBLE);
fragmentOrganizationsBinding.progressBar.setVisibility(View.GONE);
break;
default:
Toasty.error(context, getString(R.string.genericError));
break;
}
}
}
@Override
public void onFailure(@NonNull Call<List<UserOrganizations>> call, @NonNull Throwable t) {
Toasty.error(context, getString(R.string.genericError));
}
});
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
filter(newText);
return false;
}
});
}
private void filter(String text) {
List<UserOrganizations> arr = new ArrayList<>();
for(UserOrganizations d : organizationsList) {
if(d == null || d.getUsername() == null || d.getDescription() == null) {
continue;
}
if(d.getUsername().toLowerCase().contains(text) || d.getDescription().toLowerCase().contains(text)) {
arr.add(d);
}
}
adapter.updateList(arr);
}
}

View File

@ -0,0 +1,271 @@
package org.mian.gitnex.fragments.profile;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import org.gitnex.tea4j.models.UserRepositories;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.profile.RepositoriesAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentRepositoriesBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class RepositoriesFragment extends Fragment {
private Context context;
private FragmentRepositoriesBinding fragmentRepositoriesBinding;
private List<UserRepositories> reposList;
private RepositoriesAdapter adapter;
private int pageSize;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private static final String usernameBundle = "";
private String username;
public RepositoriesFragment() {}
public static RepositoriesFragment newInstance(String username) {
RepositoriesFragment fragment = new RepositoriesFragment();
Bundle args = new Bundle();
args.putString(usernameBundle, username);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
username = getArguments().getString(usernameBundle);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
fragmentRepositoriesBinding = FragmentRepositoriesBinding.inflate(inflater, container, false);
setHasOptionsMenu(true);
context = getContext();
TinyDB tinyDb = TinyDB.getInstance(context);
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = Constants.resultLimitNewGiteaInstances;
}
reposList = new ArrayList<>();
fragmentRepositoriesBinding.addNewRepo.setVisibility(View.GONE);
fragmentRepositoriesBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
fragmentRepositoriesBinding.pullToRefresh.setRefreshing(false);
loadInitial(Authorization.get(context), username, resultLimit);
adapter.notifyDataChanged();
}, 200));
adapter = new RepositoriesAdapter(context, reposList);
adapter.setLoadMoreListener(() -> fragmentRepositoriesBinding.recyclerView.post(() -> {
if(reposList.size() == resultLimit || pageSize == resultLimit) {
int page = (reposList.size() + resultLimit) / resultLimit;
loadMore(Authorization.get(context), username, page, resultLimit);
}
}));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
fragmentRepositoriesBinding.recyclerView.setHasFixedSize(true);
fragmentRepositoriesBinding.recyclerView.addItemDecoration(dividerItemDecoration);
fragmentRepositoriesBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context));
fragmentRepositoriesBinding.recyclerView.setAdapter(adapter);
loadInitial(Authorization.get(context), username, resultLimit);
return fragmentRepositoriesBinding.getRoot();
}
private void loadInitial(String token, String username, int resultLimit) {
Call<List<UserRepositories>> call = RetrofitClient
.getApiInterface(context).getUserProfileRepositories(token, username, 1, resultLimit);
call.enqueue(new Callback<List<UserRepositories>>() {
@Override
public void onResponse(@NonNull Call<List<UserRepositories>> call, @NonNull Response<List<UserRepositories>> response) {
if(response.isSuccessful()) {
switch(response.code()) {
case 200:
assert response.body() != null;
if(response.body().size() > 0) {
reposList.clear();
reposList.addAll(response.body());
adapter.notifyDataChanged();
fragmentRepositoriesBinding.noData.setVisibility(View.GONE);
}
else {
reposList.clear();
adapter.notifyDataChanged();
fragmentRepositoriesBinding.noData.setVisibility(View.VISIBLE);
}
fragmentRepositoriesBinding.progressBar.setVisibility(View.GONE);
break;
case 401:
AlertDialogs.authorizationTokenRevokedDialog(context, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(context, context.getString(R.string.authorizeError));
break;
case 404:
fragmentRepositoriesBinding.noData.setVisibility(View.VISIBLE);
fragmentRepositoriesBinding.progressBar.setVisibility(View.GONE);
break;
default:
Toasty.error(context, getString(R.string.genericError));
break;
}
}
}
@Override
public void onFailure(@NonNull Call<List<UserRepositories>> call, @NonNull Throwable t) {
Toasty.error(context, getString(R.string.genericError));
}
});
}
private void loadMore(String token, String username, int page, int resultLimit) {
fragmentRepositoriesBinding.progressLoadMore.setVisibility(View.VISIBLE);
Call<List<UserRepositories>> call = RetrofitClient.getApiInterface(context).getUserProfileRepositories(token, username, page, resultLimit);
call.enqueue(new Callback<List<UserRepositories>>() {
@Override
public void onResponse(@NonNull Call<List<UserRepositories>> call, @NonNull Response<List<UserRepositories>> response) {
if(response.isSuccessful()) {
switch(response.code()) {
case 200:
List<UserRepositories> result = response.body();
assert result != null;
if(result.size() > 0) {
pageSize = result.size();
reposList.addAll(result);
}
else {
SnackBar.info(context, fragmentRepositoriesBinding.getRoot(), getString(R.string.noMoreData));
adapter.setMoreDataAvailable(false);
}
adapter.notifyDataChanged();
fragmentRepositoriesBinding.progressLoadMore.setVisibility(View.GONE);
break;
case 401:
AlertDialogs.authorizationTokenRevokedDialog(context, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(context, context.getString(R.string.authorizeError));
break;
case 404:
fragmentRepositoriesBinding.noData.setVisibility(View.VISIBLE);
fragmentRepositoriesBinding.progressBar.setVisibility(View.GONE);
break;
default:
Toasty.error(context, getString(R.string.genericError));
break;
}
}
}
@Override
public void onFailure(@NonNull Call<List<UserRepositories>> call, @NonNull Throwable t) {
Toasty.error(context, getString(R.string.genericError));
}
});
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
filter(newText);
return false;
}
});
}
private void filter(String text) {
List<UserRepositories> arr = new ArrayList<>();
for(UserRepositories d : reposList) {
if(d == null || d.getFullName() == null || d.getDescription() == null) {
continue;
}
if(d.getFullName().toLowerCase().contains(text) || d.getDescription().toLowerCase().contains(text)) {
arr.add(d);
}
}
adapter.updateList(arr);
}
}

View File

@ -0,0 +1,273 @@
package org.mian.gitnex.fragments.profile;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import org.gitnex.tea4j.models.UserRepositories;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.profile.StarredRepositoriesAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentRepositoriesBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class StarredRepositoriesFragment extends Fragment {
private Context context;
private FragmentRepositoriesBinding fragmentRepositoriesBinding;
private List<UserRepositories> reposList;
private StarredRepositoriesAdapter adapter;
private int pageSize;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private static final String usernameBundle = "";
private String username;
public StarredRepositoriesFragment() {}
public static StarredRepositoriesFragment newInstance(String username) {
StarredRepositoriesFragment fragment = new StarredRepositoriesFragment();
Bundle args = new Bundle();
args.putString(usernameBundle, username);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
username = getArguments().getString(usernameBundle);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
fragmentRepositoriesBinding = org.mian.gitnex.databinding.FragmentRepositoriesBinding.inflate(inflater, container, false);
setHasOptionsMenu(true);
context = getContext();
TinyDB tinyDb = TinyDB.getInstance(context);
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = Constants.resultLimitNewGiteaInstances;
}
reposList = new ArrayList<>();
fragmentRepositoriesBinding.addNewRepo.setVisibility(View.GONE);
fragmentRepositoriesBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
fragmentRepositoriesBinding.pullToRefresh.setRefreshing(false);
loadInitial(Authorization.get(context), username, resultLimit);
adapter.notifyDataChanged();
}, 200));
adapter = new StarredRepositoriesAdapter(context, reposList);
adapter.setLoadMoreListener(() -> fragmentRepositoriesBinding.recyclerView.post(() -> {
if(reposList.size() == resultLimit || pageSize == resultLimit) {
int page = (reposList.size() + resultLimit) / resultLimit;
loadMore(Authorization.get(context), username, page, resultLimit);
}
}));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
fragmentRepositoriesBinding.recyclerView.setHasFixedSize(true);
fragmentRepositoriesBinding.recyclerView.addItemDecoration(dividerItemDecoration);
fragmentRepositoriesBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context));
fragmentRepositoriesBinding.recyclerView.setAdapter(adapter);
loadInitial(Authorization.get(context), username, resultLimit);
return fragmentRepositoriesBinding.getRoot();
}
private void loadInitial(String token, String username, int resultLimit) {
Call<List<UserRepositories>> call = RetrofitClient
.getApiInterface(context)
.getUserProfileStarredRepositories(token, username, 1, resultLimit);
call.enqueue(new Callback<List<UserRepositories>>() {
@Override
public void onResponse(@NonNull Call<List<UserRepositories>> call, @NonNull Response<List<UserRepositories>> response) {
if(response.isSuccessful()) {
switch(response.code()) {
case 200:
assert response.body() != null;
if(response.body().size() > 0) {
reposList.clear();
reposList.addAll(response.body());
adapter.notifyDataChanged();
fragmentRepositoriesBinding.noData.setVisibility(View.GONE);
}
else {
reposList.clear();
adapter.notifyDataChanged();
fragmentRepositoriesBinding.noData.setVisibility(View.VISIBLE);
}
fragmentRepositoriesBinding.progressBar.setVisibility(View.GONE);
break;
case 401:
AlertDialogs.authorizationTokenRevokedDialog(context, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(context, context.getString(R.string.authorizeError));
break;
case 404:
fragmentRepositoriesBinding.noData.setVisibility(View.VISIBLE);
fragmentRepositoriesBinding.progressBar.setVisibility(View.GONE);
break;
default:
Toasty.error(context, getString(R.string.genericError));
break;
}
}
}
@Override
public void onFailure(@NonNull Call<List<UserRepositories>> call, @NonNull Throwable t) {
Toasty.error(context, getString(R.string.genericError));
}
});
}
private void loadMore(String token, String username, int page, int resultLimit) {
fragmentRepositoriesBinding.progressLoadMore.setVisibility(View.VISIBLE);
Call<List<UserRepositories>> call = RetrofitClient
.getApiInterface(context)
.getUserProfileStarredRepositories(token, username, page, resultLimit);
call.enqueue(new Callback<List<UserRepositories>>() {
@Override
public void onResponse(@NonNull Call<List<UserRepositories>> call, @NonNull Response<List<UserRepositories>> response) {
if(response.isSuccessful()) {
switch(response.code()) {
case 200:
List<UserRepositories> result = response.body();
assert result != null;
if(result.size() > 0) {
pageSize = result.size();
reposList.addAll(result);
}
else {
SnackBar.info(context, fragmentRepositoriesBinding.getRoot(), getString(R.string.noMoreData));
adapter.setMoreDataAvailable(false);
}
adapter.notifyDataChanged();
fragmentRepositoriesBinding.progressLoadMore.setVisibility(View.GONE);
break;
case 401:
AlertDialogs.authorizationTokenRevokedDialog(context, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(context, context.getString(R.string.authorizeError));
break;
case 404:
fragmentRepositoriesBinding.noData.setVisibility(View.VISIBLE);
fragmentRepositoriesBinding.progressBar.setVisibility(View.GONE);
break;
default:
Toasty.error(context, getString(R.string.genericError));
break;
}
}
}
@Override
public void onFailure(@NonNull Call<List<UserRepositories>> call, @NonNull Throwable t) {
Toasty.error(context, getString(R.string.genericError));
}
});
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
filter(newText);
return false;
}
});
}
private void filter(String text) {
List<UserRepositories> arr = new ArrayList<>();
for(UserRepositories d : reposList) {
if(d == null || d.getFullName() == null || d.getDescription() == null) {
continue;
}
if(d.getFullName().toLowerCase().contains(text) || d.getDescription().toLowerCase().contains(text)) {
arr.add(d);
}
}
adapter.updateList(arr);
}
}

View File

@ -27,7 +27,6 @@ public class Constants {
public static final String tagMilestonesAdapter = "MilestonesAdapter";
public static final String draftsApi = "DraftsApi";
public static final String repositoriesApi = "RepositoriesApi";
public static final String replyToIssueActivity = "ReplyToIssueActivity";
public static final String tagDraftsBottomSheet = "BottomSheetDraftsFragment";
public static final String userAccountsApi = "UserAccountsApi";
public static final String publicOrganizations = "PublicOrganizations";

View File

@ -35,7 +35,7 @@ public class OrganizationListViewModel extends ViewModel {
Call<List<UserOrganizations>> call = RetrofitClient
.getApiInterface(ctx)
.getUserOrgs(token);
.getUserOrgs(token, 1, 50);
call.enqueue(new Callback<List<UserOrganizations>>() {

View File

@ -33,7 +33,7 @@ public class ProfileFollowersViewModel extends ViewModel {
Call<List<UserInfo>> call = RetrofitClient
.getApiInterface(ctx)
.getFollowers(token);
.getFollowers(token, 1, 50);
call.enqueue(new Callback<List<UserInfo>>() {

View File

@ -33,7 +33,7 @@ public class ProfileFollowingViewModel extends ViewModel {
Call<List<UserInfo>> call = RetrofitClient
.getApiInterface(ctx)
.getFollowing(token);
.getFollowing(token, 1, 50);
call.enqueue(new Callback<List<UserInfo>>() {

View File

@ -0,0 +1,54 @@
<?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/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="?attr/primaryBackgroundColor">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
android:theme="@style/Widget.AppCompat.SearchView">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_weight="1"
android:background="?attr/primaryBackgroundColor"
app:layout_scrollFlags="enterAlways">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:textSize="18sp"
android:textColor="?attr/primaryTextColor"
android:id="@+id/toolbarTitle" />
</com.google.android.material.appbar.MaterialToolbar>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
app:tabTextAppearance="@style/customTabLayout"
app:tabMode="scrollable"
app:tabTextColor="?attr/primaryTextColor"
android:background="?attr/primaryBackgroundColor"
app:tabIndicatorColor="?attr/pagerTabIndicatorColor"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/profileContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -9,7 +9,7 @@
android:orientation="vertical">
<RelativeLayout
android:id="@+id/aboutFrame"
android:id="@+id/profileFrame"
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="top"

View File

@ -0,0 +1,195 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:background="?attr/primaryBackgroundColor"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:orientation="vertical"
android:id="@+id/userInfoLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/profileFrame"
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="top"
android:orientation="vertical">
<ImageView
android:id="@+id/userAvatarBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/generalImgContentText"
android:scaleType="centerCrop" />
<LinearLayout
android:id="@+id/layoutFrameAccount"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/userAvatar"
android:layout_width="54dp"
android:layout_height="54dp"
android:contentDescription="@string/generalImgContentText"
tools:src="@mipmap/app_logo_round" />
<TextView
android:id="@+id/userFullName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="@color/colorWhite"
android:textIsSelectable="true"
android:textSize="18sp" />
<TextView
android:id="@+id/userLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorWhite"
android:textIsSelectable="true"
android:textSize="14sp" />
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="15dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:orientation="horizontal"
android:paddingLeft="15dp"
android:paddingRight="15dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_email" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/userEmail"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
<TextView
android:id="@+id/userEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.9"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:orientation="horizontal"
android:paddingLeft="15dp"
android:paddingRight="15dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_language" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsLanguageSelectorHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
<TextView
android:id="@+id/userLang"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.9"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:orientation="horizontal"
android:paddingLeft="15dp"
android:paddingRight="15dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_calendar" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/joined"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
<TextView
android:id="@+id/userJoinedOn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.9"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@ -19,15 +19,24 @@
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progress_bar"
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
style="@style/Widget.MaterialComponents.LinearProgressIndicator"
app:indicatorColor="?attr/progressIndicatorColor" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progressLoadMore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:indeterminate="true"
style="@style/Widget.MaterialComponents.LinearProgressIndicator"
app:indicatorColor="?attr/progressIndicatorColor" />
<TextView
android:id="@+id/noDataFollowers"
android:id="@+id/noData"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp"

View File

@ -1,40 +0,0 @@
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto">
<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.progressindicator.LinearProgressIndicator
android:id="@+id/progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
style="@style/Widget.MaterialComponents.LinearProgressIndicator"
app:indicatorColor="?attr/progressIndicatorColor" />
<TextView
android:id="@+id/noDataFollowing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp"
android:gravity="center"
android:text="@string/noDataFound"
android:textColor="?attr/primaryTextColor"
android:textSize="20sp"
android:visibility="gone" />
</RelativeLayout>

View File

@ -29,6 +29,15 @@
style="@style/Widget.MaterialComponents.LinearProgressIndicator"
app:indicatorColor="?attr/progressIndicatorColor" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progressLoadMore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:indeterminate="true"
style="@style/Widget.MaterialComponents.LinearProgressIndicator"
app:indicatorColor="?attr/progressIndicatorColor" />
<TextView
android:id="@+id/noData"
android:layout_width="match_parent"

View File

@ -1,41 +0,0 @@
<?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="wrap_content"
android:gravity="center_vertical"
android:padding="16dp">
<ImageView
android:id="@+id/userAvatar"
android:layout_width="@dimen/list_avatar_size"
android:layout_height="@dimen/list_avatar_size"
android:layout_marginEnd="10dp"
android:contentDescription="@string/generalImgContentText"
android:src="@drawable/ic_android" />
<LinearLayout
android:id="@+id/userInfoSection"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/userFullName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/userName"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/userName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/userName"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>

View File

@ -753,4 +753,5 @@
<string name="fileViewerNotificationChannelDescription">Indicates the progress of ongoing downloads</string>
<string name="lastUpdatedAt">Updated %s</string>
<string name="joined">Joined</string>
</resources>