diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8ff9dba3..27eafece 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,7 +14,6 @@
android:label="@string/appName"
android:networkSecurityConfig="@xml/network_security_config"
android:resizeableActivity="true"
- android:roundIcon="@mipmap/app_logo_round"
android:supportsRtl="true"
android:exported="true"
tools:targetApi="n">
@@ -53,7 +52,7 @@
android:name=".activities.CreateNewUserActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
call =
RetrofitClient.getApiInterface(context)
- .userCurrentDeleteStar(repository.getOwner(), repository.getName());
+ .userCurrentDeleteSubscription(repository.getOwner(), repository.getName());
call.enqueue(
new Callback<>() {
@@ -166,6 +167,7 @@ public class RepositoryActions {
if (response.code() == 204) {
+ MainActivity.reloadRepos = true;
Toasty.success(
context, context.getString(R.string.unWatchRepositorySuccess));
} else if (response.code() == 401) {
diff --git a/app/src/main/java/org/mian/gitnex/activities/MyProfileEmailActivity.java b/app/src/main/java/org/mian/gitnex/activities/AccountSettingsEmailActivity.java
similarity index 74%
rename from app/src/main/java/org/mian/gitnex/activities/MyProfileEmailActivity.java
rename to app/src/main/java/org/mian/gitnex/activities/AccountSettingsEmailActivity.java
index 9815ae9e..94d0c725 100644
--- a/app/src/main/java/org/mian/gitnex/activities/MyProfileEmailActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/AccountSettingsEmailActivity.java
@@ -6,19 +6,17 @@ import android.util.Log;
import android.util.Patterns;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.ImageView;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import org.gitnex.tea4j.v2.models.CreateEmailOption;
import org.gitnex.tea4j.v2.models.Email;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
-import org.mian.gitnex.databinding.ActivityProfileEmailBinding;
-import org.mian.gitnex.fragments.MyProfileEmailsFragment;
+import org.mian.gitnex.databinding.ActivityAccountSettingsEmailBinding;
+import org.mian.gitnex.fragments.AccountSettingsEmailsFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
@@ -28,44 +26,40 @@ import retrofit2.Callback;
/**
* @author M M Arif
*/
-public class MyProfileEmailActivity extends BaseActivity {
+public class AccountSettingsEmailActivity extends BaseActivity {
private View.OnClickListener onClickListener;
- private EditText userEmail;
- private Button addEmailButton;
private final View.OnClickListener addEmailListener = v -> processAddNewEmail();
+ private ActivityAccountSettingsEmailBinding activityAccountSettingsEmailBinding;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ActivityProfileEmailBinding activityProfileEmailBinding =
- ActivityProfileEmailBinding.inflate(getLayoutInflater());
- setContentView(activityProfileEmailBinding.getRoot());
+ activityAccountSettingsEmailBinding =
+ ActivityAccountSettingsEmailBinding.inflate(getLayoutInflater());
+ setContentView(activityAccountSettingsEmailBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- ImageView closeActivity = activityProfileEmailBinding.close;
- userEmail = activityProfileEmailBinding.userEmail;
- addEmailButton = activityProfileEmailBinding.addEmailButton;
-
- userEmail.requestFocus();
+ activityAccountSettingsEmailBinding.userEmail.requestFocus();
assert imm != null;
- imm.showSoftInput(userEmail, InputMethodManager.SHOW_IMPLICIT);
+ imm.showSoftInput(
+ activityAccountSettingsEmailBinding.userEmail, InputMethodManager.SHOW_IMPLICIT);
initCloseListener();
- closeActivity.setOnClickListener(onClickListener);
+ activityAccountSettingsEmailBinding.close.setOnClickListener(onClickListener);
if (!connToInternet) {
disableProcessButton();
} else {
- addEmailButton.setOnClickListener(addEmailListener);
+ activityAccountSettingsEmailBinding.addEmailButton.setOnClickListener(addEmailListener);
}
}
@@ -73,7 +67,10 @@ public class MyProfileEmailActivity extends BaseActivity {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
- String newUserEmail = userEmail.getText().toString().trim();
+ String newUserEmail =
+ Objects.requireNonNull(activityAccountSettingsEmailBinding.userEmail.getText())
+ .toString()
+ .trim();
if (!connToInternet) {
@@ -115,7 +112,7 @@ public class MyProfileEmailActivity extends BaseActivity {
if (response.code() == 201) {
Toasty.success(ctx, getString(R.string.emailAddedText));
- MyProfileEmailsFragment.refreshEmails = true;
+ AccountSettingsEmailsFragment.refreshEmails = true;
enableProcessButton();
finish();
} else if (response.code() == 401) {
@@ -157,11 +154,11 @@ public class MyProfileEmailActivity extends BaseActivity {
private void disableProcessButton() {
- addEmailButton.setEnabled(false);
+ activityAccountSettingsEmailBinding.addEmailButton.setEnabled(false);
}
private void enableProcessButton() {
- addEmailButton.setEnabled(true);
+ activityAccountSettingsEmailBinding.addEmailButton.setEnabled(true);
}
}
diff --git a/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java b/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java
index 8f1c8b29..26c2402e 100644
--- a/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java
@@ -79,6 +79,9 @@ public abstract class BaseActivity extends AppCompatActivity {
case 8:
setTheme(R.style.AppThemeDynamicSystem);
break;
+ case 9:
+ setTheme(R.style.AppThemeCodebergDark);
+ break;
default:
setTheme(R.style.AppThemeSystem);
break;
diff --git a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java
index b5464918..ef90eabf 100644
--- a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java
@@ -36,6 +36,7 @@ import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.databinding.ActivityMainBinding;
+import org.mian.gitnex.fragments.AccountSettingsFragment;
import org.mian.gitnex.fragments.AdministrationFragment;
import org.mian.gitnex.fragments.BottomSheetDraftsFragment;
import org.mian.gitnex.fragments.BottomSheetMyIssuesFilterFragment;
@@ -44,7 +45,6 @@ import org.mian.gitnex.fragments.DraftsFragment;
import org.mian.gitnex.fragments.ExploreFragment;
import org.mian.gitnex.fragments.MostVisitedReposFragment;
import org.mian.gitnex.fragments.MyIssuesFragment;
-import org.mian.gitnex.fragments.MyProfileFragment;
import org.mian.gitnex.fragments.MyRepositoriesFragment;
import org.mian.gitnex.fragments.NotesFragment;
import org.mian.gitnex.fragments.NotificationsFragment;
@@ -52,6 +52,7 @@ import org.mian.gitnex.fragments.OrganizationsFragment;
import org.mian.gitnex.fragments.RepositoriesFragment;
import org.mian.gitnex.fragments.SettingsFragment;
import org.mian.gitnex.fragments.StarredRepositoriesFragment;
+import org.mian.gitnex.fragments.WatchedRepositoriesFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ChangeLog;
@@ -71,20 +72,17 @@ public class MainActivity extends BaseActivity
public static boolean refActivity = false;
public static boolean reloadRepos = false;
-
private DrawerLayout drawer;
private TextView toolbarTitle;
private Typeface myTypeface;
-
private boolean noConnection = false;
-
private View hView;
private NavigationView navigationView;
private MenuItem navNotifications;
private TextView notificationCounter;
-
private BottomSheetListener profileInitListener;
private FragmentRefreshListener fragmentRefreshListenerMyIssues;
+ private String username;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -139,8 +137,8 @@ public class MainActivity extends BaseActivity
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
} else if (fragmentById instanceof NotificationsFragment) {
toolbarTitle.setText(R.string.pageTitleNotifications);
- } else if (fragmentById instanceof MyProfileFragment) {
- toolbarTitle.setText(getResources().getString(R.string.navProfile));
+ } else if (fragmentById instanceof AccountSettingsFragment) {
+ toolbarTitle.setText(getResources().getString(R.string.navAccount));
} else if (fragmentById instanceof MostVisitedReposFragment) {
toolbarTitle.setText(getResources().getString(R.string.navMostVisited));
} else if (fragmentById instanceof NotesFragment) {
@@ -153,6 +151,8 @@ public class MainActivity extends BaseActivity
toolbarTitle.setText(getResources().getString(R.string.navMyIssues));
} else if (fragmentById instanceof DashboardFragment) {
toolbarTitle.setText(getResources().getString(R.string.dashboard));
+ } else if (fragmentById instanceof WatchedRepositoriesFragment) {
+ toolbarTitle.setText(getResources().getString(R.string.navWatchedRepositories));
}
getNotificationsCount();
@@ -241,6 +241,7 @@ public class MainActivity extends BaseActivity
userFullName.setTypeface(myTypeface);
if (getAccount().getUserInfo() != null) {
+ username = getAccount().getUserInfo().getLogin();
String userEmailNav = getAccount().getUserInfo().getEmail();
String userFullNameNav = getAccount().getFullName();
String userAvatarNav = getAccount().getUserInfo().getAvatarUrl();
@@ -270,15 +271,9 @@ public class MainActivity extends BaseActivity
userAvatar.setOnClickListener(
v -> {
- toolbarTitle.setText(
- getResources().getString(R.string.navProfile));
- getSupportFragmentManager()
- .beginTransaction()
- .replace(
- R.id.fragment_container,
- new MyProfileFragment())
- .commit();
- navigationView.setCheckedItem(R.id.nav_profile);
+ Intent intentProfile = new Intent(ctx, ProfileActivity.class);
+ intentProfile.putExtra("username", username);
+ ctx.startActivity(intentProfile);
drawer.closeDrawers();
});
@@ -388,11 +383,9 @@ public class MainActivity extends BaseActivity
return;
case "profile":
- getSupportFragmentManager()
- .beginTransaction()
- .replace(R.id.fragment_container, new MyProfileFragment())
- .commit();
- navigationView.setCheckedItem(R.id.nav_profile);
+ Intent intentProfile = new Intent(ctx, ProfileActivity.class);
+ intentProfile.putExtra("username", username);
+ ctx.startActivity(intentProfile);
return;
case "admin":
@@ -442,12 +435,12 @@ public class MainActivity extends BaseActivity
break;
case 4:
- toolbarTitle.setText(getResources().getString(R.string.navProfile));
+ toolbarTitle.setText(getResources().getString(R.string.navAccount));
getSupportFragmentManager()
.beginTransaction()
- .replace(R.id.fragment_container, new MyProfileFragment())
+ .replace(R.id.fragment_container, new AccountSettingsFragment())
.commit();
- navigationView.setCheckedItem(R.id.nav_profile);
+ navigationView.setCheckedItem(R.id.nav_account_settings);
break;
case 5:
@@ -509,6 +502,14 @@ public class MainActivity extends BaseActivity
.commit();
navigationView.setCheckedItem(R.id.nav_dashboard);
break;
+ case 12:
+ toolbarTitle.setText(getResources().getString(R.string.navWatchedRepositories));
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(R.id.fragment_container, new WatchedRepositoriesFragment())
+ .commit();
+ navigationView.setCheckedItem(R.id.nav_watched_repositories);
+ break;
default:
toolbarTitle.setText(getResources().getString(R.string.navMyRepos));
getSupportFragmentManager()
@@ -654,11 +655,11 @@ public class MainActivity extends BaseActivity
.replace(R.id.fragment_container, new OrganizationsFragment())
.commit();
} else if (id == R.id.nav_profile) {
- toolbarTitle.setText(getResources().getString(R.string.navProfile));
- getSupportFragmentManager()
- .beginTransaction()
- .replace(R.id.fragment_container, new MyProfileFragment())
- .commit();
+
+ Intent intentProfile = new Intent(ctx, ProfileActivity.class);
+ intentProfile.putExtra("username", username);
+ ctx.startActivity(intentProfile);
+ drawer.closeDrawers();
} else if (id == R.id.nav_repositories) {
toolbarTitle.setText(getResources().getString(R.string.navRepos));
@@ -736,6 +737,20 @@ public class MainActivity extends BaseActivity
.beginTransaction()
.replace(R.id.fragment_container, new DashboardFragment())
.commit();
+ } else if (id == R.id.nav_account_settings) {
+
+ toolbarTitle.setText(getResources().getString(R.string.navAccount));
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(R.id.fragment_container, new AccountSettingsFragment())
+ .commit();
+ } else if (id == R.id.nav_watched_repositories) {
+
+ toolbarTitle.setText(getResources().getString(R.string.navWatchedRepositories));
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(R.id.fragment_container, new WatchedRepositoriesFragment())
+ .commit();
}
drawer.closeDrawer(GravityCompat.START);
diff --git a/app/src/main/java/org/mian/gitnex/activities/OrganizationDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/OrganizationDetailActivity.java
index 1f7492f6..ed2928c8 100644
--- a/app/src/main/java/org/mian/gitnex/activities/OrganizationDetailActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/OrganizationDetailActivity.java
@@ -9,17 +9,17 @@ 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.FragmentManager;
-import androidx.fragment.app.FragmentPagerAdapter;
-import androidx.viewpager.widget.ViewPager;
-import com.google.android.material.tabs.TabLayout;
+import androidx.fragment.app.FragmentActivity;
+import androidx.viewpager2.adapter.FragmentStateAdapter;
+import androidx.viewpager2.widget.ViewPager2;
+import com.google.android.material.tabs.TabLayoutMediator;
import io.mikael.urlbuilder.UrlBuilder;
import java.util.Objects;
import org.gitnex.tea4j.v2.models.OrganizationPermissions;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
+import org.mian.gitnex.databinding.ActivityOrgDetailBinding;
import org.mian.gitnex.fragments.BottomSheetOrganizationFragment;
import org.mian.gitnex.fragments.OrganizationInfoFragment;
import org.mian.gitnex.fragments.OrganizationLabelsFragment;
@@ -27,6 +27,7 @@ import org.mian.gitnex.fragments.OrganizationMembersFragment;
import org.mian.gitnex.fragments.OrganizationRepositoriesFragment;
import org.mian.gitnex.fragments.OrganizationTeamsFragment;
import org.mian.gitnex.helpers.AppUtil;
+import org.mian.gitnex.helpers.ViewPager2Transformers;
import org.mian.gitnex.structs.BottomSheetListener;
import retrofit2.Call;
import retrofit2.Callback;
@@ -41,19 +42,19 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
public OrganizationPermissions permissions;
private String orgName;
private boolean isMember = false;
+ private ActivityOrgDetailBinding activityOrgDetailBinding;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_org_detail);
+ activityOrgDetailBinding = ActivityOrgDetailBinding.inflate(getLayoutInflater());
+ setContentView(activityOrgDetailBinding.getRoot());
orgName = getIntent().getStringExtra("orgName");
- Toolbar toolbar = findViewById(R.id.toolbar);
-
- setSupportActionBar(toolbar);
+ setSupportActionBar(activityOrgDetailBinding.toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(orgName);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@@ -112,48 +113,91 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
}
public void init() {
- OrganizationDetailActivity.SectionsPagerAdapter mSectionsPagerAdapter =
- new OrganizationDetailActivity.SectionsPagerAdapter(getSupportFragmentManager());
- ViewPager mViewPager = findViewById(R.id.container);
- mViewPager.setVisibility(View.VISIBLE);
- mViewPager.setAdapter(mSectionsPagerAdapter);
+ ViewPager2 viewPager = activityOrgDetailBinding.container;
+ viewPager.setOffscreenPageLimit(1);
- TabLayout tabLayout = findViewById(R.id.tabs);
- tabLayout.setVisibility(View.VISIBLE);
+ ViewGroup vg = (ViewGroup) activityOrgDetailBinding.tabs.getChildAt(0);
+
+ Typeface myTypeface = AppUtil.getTypeface(ctx);
+
+ activityOrgDetailBinding.toolbarTitle.setTypeface(myTypeface);
+ activityOrgDetailBinding.toolbarTitle.setText(orgName);
+
+ viewPager.setAdapter(new OrganizationDetailActivity.ViewPagerAdapter(this));
+
+ ViewPager2Transformers.returnSelectedTransformer(
+ viewPager, tinyDB.getInt("fragmentTabsAnimationId", 0));
+
+ String[] tabTitles = {
+ getResources().getString(R.string.tabTextInfo),
+ getResources().getString(R.string.navRepos),
+ getResources().getString(R.string.newIssueLabelsTitle),
+ getResources().getString(R.string.orgTabTeams),
+ getResources().getString(R.string.orgTabMembers)
+ };
if (!isMember) {
- tabLayout.removeTabAt(3);
+ activityOrgDetailBinding.tabs.removeTabAt(3);
}
- Typeface myTypeface = AppUtil.getTypeface(this);
- TextView toolbarTitle = findViewById(R.id.toolbar_title);
+ new TabLayoutMediator(
+ activityOrgDetailBinding.tabs,
+ viewPager,
+ (tab, position) -> tab.setText(tabTitles[position]))
+ .attach();
- toolbarTitle.setTypeface(myTypeface);
- toolbarTitle.setText(orgName);
-
- ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
- int tabsCount = vg.getChildCount();
-
- for (int j = 0; j < tabsCount; j++) {
+ for (int j = 0; j < tabTitles.length; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
int tabChildCount = vgTab.getChildCount();
for (int i = 0; i < tabChildCount; i++) {
-
View tabViewChild = vgTab.getChildAt(i);
-
if (tabViewChild instanceof TextView) {
-
((TextView) tabViewChild).setTypeface(myTypeface);
}
}
}
+ }
- mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
- tabLayout.addOnTabSelectedListener(
- new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
+ public class ViewPagerAdapter extends FragmentStateAdapter {
+
+ public ViewPagerAdapter(@NonNull FragmentActivity fa) {
+ super(fa);
+ }
+
+ @NonNull @Override
+ public Fragment createFragment(int position) {
+ switch (position) {
+ case 0: // info
+ return OrganizationInfoFragment.newInstance(orgName);
+ case 1: // repos
+ return OrganizationRepositoriesFragment.newInstance(orgName, permissions);
+ case 2: // labels
+ return OrganizationLabelsFragment.newInstance(orgName, permissions);
+ case 3: // teams / members
+ if (isMember) {
+ return OrganizationTeamsFragment.newInstance(orgName, permissions);
+ } else {
+ return OrganizationMembersFragment.newInstance(orgName);
+ }
+ case 4: // members
+ if (isMember) {
+ return OrganizationMembersFragment.newInstance(orgName);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public int getItemCount() {
+ if (isMember) {
+ return 5;
+ } else {
+ return 4;
+ }
+ }
}
@Override
@@ -205,47 +249,4 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
break;
}
}
-
- public class SectionsPagerAdapter extends FragmentPagerAdapter {
-
- SectionsPagerAdapter(FragmentManager fm) {
- super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
- }
-
- @NonNull @Override
- public Fragment getItem(int position) {
-
- String orgName = getIntent().getStringExtra("orgName");
-
- Fragment fragment = null;
- switch (position) {
- case 0: // info
- return OrganizationInfoFragment.newInstance(orgName);
- case 1: // repos
- return OrganizationRepositoriesFragment.newInstance(orgName, permissions);
- case 2: // labels
- return OrganizationLabelsFragment.newInstance(orgName, permissions);
- case 3: // teams / members
- if (isMember) {
- return OrganizationTeamsFragment.newInstance(orgName, permissions);
- } else {
- return OrganizationMembersFragment.newInstance(orgName);
- }
- case 4: // members
- if (isMember) {
- return OrganizationMembersFragment.newInstance(orgName);
- }
- }
- return fragment;
- }
-
- @Override
- public int getCount() {
- if (isMember) {
- return 5;
- } else {
- return 4;
- }
- }
- }
}
diff --git a/app/src/main/java/org/mian/gitnex/activities/OrganizationTeamInfoActivity.java b/app/src/main/java/org/mian/gitnex/activities/OrganizationTeamInfoActivity.java
index 33eb961b..5df687c5 100644
--- a/app/src/main/java/org/mian/gitnex/activities/OrganizationTeamInfoActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/OrganizationTeamInfoActivity.java
@@ -14,6 +14,7 @@ import org.mian.gitnex.databinding.ActivityOrgTeamInfoBinding;
import org.mian.gitnex.fragments.OrganizationTeamInfoMembersFragment;
import org.mian.gitnex.fragments.OrganizationTeamInfoPermissionsFragment;
import org.mian.gitnex.fragments.OrganizationTeamInfoReposFragment;
+import org.mian.gitnex.helpers.ViewPager2Transformers;
/**
* @author M M Arif
@@ -28,7 +29,7 @@ public class OrganizationTeamInfoActivity extends BaseActivity {
super.onCreate(savedInstanceState);
- org.mian.gitnex.databinding.ActivityOrgTeamInfoBinding binding =
+ ActivityOrgTeamInfoBinding binding =
ActivityOrgTeamInfoBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
@@ -66,6 +67,9 @@ public class OrganizationTeamInfoActivity extends BaseActivity {
}
});
+ ViewPager2Transformers.returnSelectedTransformer(
+ binding.pager, tinyDB.getInt("fragmentTabsAnimationId", 0));
+
new TabLayoutMediator(
binding.tabs,
binding.pager,
diff --git a/app/src/main/java/org/mian/gitnex/activities/ProfileActivity.java b/app/src/main/java/org/mian/gitnex/activities/ProfileActivity.java
index d0eaa364..c5d71e4b 100644
--- a/app/src/main/java/org/mian/gitnex/activities/ProfileActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/ProfileActivity.java
@@ -28,6 +28,7 @@ import org.mian.gitnex.fragments.profile.RepositoriesFragment;
import org.mian.gitnex.fragments.profile.StarredRepositoriesFragment;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
+import org.mian.gitnex.helpers.ViewPager2Transformers;
import org.mian.gitnex.structs.BottomSheetListener;
import retrofit2.Call;
import retrofit2.Callback;
@@ -73,6 +74,9 @@ public class ProfileActivity extends BaseActivity implements BottomSheetListener
viewPager.setAdapter(new ViewPagerAdapter(this));
+ ViewPager2Transformers.returnSelectedTransformer(
+ viewPager, tinyDB.getInt("fragmentTabsAnimationId", 0));
+
String[] tabTitles = {
ctx.getResources().getString(R.string.tabTextInfo),
ctx.getResources().getString(R.string.navRepos),
@@ -147,7 +151,7 @@ public class ProfileActivity extends BaseActivity implements BottomSheetListener
}
call.enqueue(
- new Callback() {
+ new Callback<>() {
@Override
public void onResponse(
diff --git a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
index 7b2b6777..cf72355d 100644
--- a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
@@ -52,6 +52,7 @@ import org.mian.gitnex.fragments.RepoInfoFragment;
import org.mian.gitnex.fragments.WikiFragment;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
+import org.mian.gitnex.helpers.ViewPager2Transformers;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import org.mian.gitnex.structs.BottomSheetListener;
import org.mian.gitnex.structs.FragmentRefreshListener;
@@ -537,6 +538,9 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
viewPager.setAdapter(new ViewPagerAdapter(this));
+ ViewPager2Transformers.returnSelectedTransformer(
+ viewPager, tinyDB.getInt("fragmentTabsAnimationId", 0));
+
String[] tabTitles = {
ctx.getResources().getString(R.string.tabTextInfo),
ctx.getResources().getString(R.string.tabTextFiles),
diff --git a/app/src/main/java/org/mian/gitnex/activities/SettingsAppearanceActivity.java b/app/src/main/java/org/mian/gitnex/activities/SettingsAppearanceActivity.java
index 1f57e765..4df8b749 100644
--- a/app/src/main/java/org/mian/gitnex/activities/SettingsAppearanceActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/SettingsAppearanceActivity.java
@@ -5,8 +5,6 @@ import android.app.TimePickerDialog;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.TimePicker;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
@@ -32,6 +30,8 @@ public class SettingsAppearanceActivity extends BaseActivity {
private static int themeSelectedChoice = 0;
private View.OnClickListener onClickListener;
private static int langSelectedChoice = 0;
+ private static String[] fragmentTabsAnimationList;
+ private static int fragmentTabsAnimationSelectedChoice = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -48,16 +48,10 @@ public class SettingsAppearanceActivity extends BaseActivity {
lang.put(langCode, getLanguageDisplayName(langCode));
}
- ImageView closeActivity = activitySettingsAppearanceBinding.close;
-
- LinearLayout customFontFrame = activitySettingsAppearanceBinding.customFontFrame;
- LinearLayout themeFrame = activitySettingsAppearanceBinding.themeSelectionFrame;
- LinearLayout lightTimeFrame =
- activitySettingsAppearanceBinding.lightThemeTimeSelectionFrame;
- LinearLayout darkTimeFrame = activitySettingsAppearanceBinding.darkThemeTimeSelectionFrame;
-
customFontList = getResources().getStringArray(R.array.fonts);
+ fragmentTabsAnimationList = getResources().getStringArray(R.array.fragmentTabsAnimation);
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S || "S".equals(Build.VERSION.CODENAME)) {
themeList = getResources().getStringArray(R.array.themesAndroid12);
} else {
@@ -65,7 +59,7 @@ public class SettingsAppearanceActivity extends BaseActivity {
}
initCloseListener();
- closeActivity.setOnClickListener(onClickListener);
+ activitySettingsAppearanceBinding.close.setOnClickListener(onClickListener);
String lightMinute = String.valueOf(tinyDB.getInt("lightThemeTimeMinute"));
String lightHour = String.valueOf(tinyDB.getInt("lightThemeTimeHour"));
@@ -85,6 +79,7 @@ public class SettingsAppearanceActivity extends BaseActivity {
darkHour = "0" + darkHour;
}
+ fragmentTabsAnimationSelectedChoice = tinyDB.getInt("fragmentTabsAnimationId", 0);
customFontSelectedChoice = tinyDB.getInt("customFontId", 1);
themeSelectedChoice = tinyDB.getInt("themeId", 6); // use system theme as default
@@ -97,13 +92,17 @@ public class SettingsAppearanceActivity extends BaseActivity {
activitySettingsAppearanceBinding.customFontSelected.setText(
customFontList[customFontSelectedChoice]);
activitySettingsAppearanceBinding.themeSelected.setText(themeList[themeSelectedChoice]);
+ activitySettingsAppearanceBinding.fragmentTabsAnimationFrameSelected.setText(
+ fragmentTabsAnimationList[fragmentTabsAnimationSelectedChoice]);
if (themeList[themeSelectedChoice].startsWith("Auto")) {
- darkTimeFrame.setVisibility(View.VISIBLE);
- lightTimeFrame.setVisibility(View.VISIBLE);
+ activitySettingsAppearanceBinding.darkThemeTimeSelectionFrame.setVisibility(
+ View.VISIBLE);
+ activitySettingsAppearanceBinding.lightThemeTimeSelectionFrame.setVisibility(
+ View.VISIBLE);
} else {
- darkTimeFrame.setVisibility(View.GONE);
- lightTimeFrame.setVisibility(View.GONE);
+ activitySettingsAppearanceBinding.darkThemeTimeSelectionFrame.setVisibility(View.GONE);
+ activitySettingsAppearanceBinding.lightThemeTimeSelectionFrame.setVisibility(View.GONE);
}
activitySettingsAppearanceBinding.switchCounterBadge.setChecked(
@@ -136,7 +135,7 @@ public class SettingsAppearanceActivity extends BaseActivity {
.isChecked()));
// theme selection dialog
- themeFrame.setOnClickListener(
+ activitySettingsAppearanceBinding.themeSelectionFrame.setOnClickListener(
view -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx)
@@ -163,20 +162,20 @@ public class SettingsAppearanceActivity extends BaseActivity {
materialAlertDialogBuilder.create().show();
});
- lightTimeFrame.setOnClickListener(
+ activitySettingsAppearanceBinding.lightThemeTimeSelectionFrame.setOnClickListener(
view -> {
LightTimePicker timePicker = new LightTimePicker();
timePicker.show(getSupportFragmentManager(), "timePicker");
});
- darkTimeFrame.setOnClickListener(
+ activitySettingsAppearanceBinding.darkThemeTimeSelectionFrame.setOnClickListener(
view -> {
DarkTimePicker timePicker = new DarkTimePicker();
timePicker.show(getSupportFragmentManager(), "timePicker");
});
// custom font dialog
- customFontFrame.setOnClickListener(
+ activitySettingsAppearanceBinding.customFontFrame.setOnClickListener(
view -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx)
@@ -206,9 +205,39 @@ public class SettingsAppearanceActivity extends BaseActivity {
materialAlertDialogBuilder.create().show();
});
- // language selector dialog
- LinearLayout langFrame = activitySettingsAppearanceBinding.langFrame;
+ // fragment tabs animation dialog
+ activitySettingsAppearanceBinding.fragmentTabsAnimationFrame.setOnClickListener(
+ view -> {
+ MaterialAlertDialogBuilder materialAlertDialogBuilder =
+ new MaterialAlertDialogBuilder(ctx)
+ .setTitle(R.string.fragmentTabsAnimationHeader)
+ .setCancelable(fragmentTabsAnimationSelectedChoice != -1)
+ .setSingleChoiceItems(
+ fragmentTabsAnimationList,
+ fragmentTabsAnimationSelectedChoice,
+ (dialogInterfaceCustomFont, i) -> {
+ fragmentTabsAnimationSelectedChoice = i;
+ activitySettingsAppearanceBinding
+ .fragmentTabsAnimationFrameSelected.setText(
+ fragmentTabsAnimationList[i]);
+ tinyDB.putInt("fragmentTabsAnimationId", i);
+ AppUtil.typeface = null; // reset typeface
+ FontsOverride.setDefaultFont(this);
+ SettingsFragment.refreshParent = true;
+ this.recreate();
+ this.overridePendingTransition(0, 0);
+ dialogInterfaceCustomFont.dismiss();
+ Toasty.success(
+ appCtx,
+ appCtx.getResources()
+ .getString(R.string.settingsSave));
+ });
+
+ materialAlertDialogBuilder.create().show();
+ });
+
+ // language selector dialog
activitySettingsAppearanceBinding.helpTranslate.setOnClickListener(
v12 -> {
AppUtil.openUrlInBrowser(this, getResources().getString(R.string.crowdInLink));
@@ -219,7 +248,7 @@ public class SettingsAppearanceActivity extends BaseActivity {
lang.get(lang.keySet().toArray(new String[0])[langSelectedChoice]));
// language dialog
- langFrame.setOnClickListener(
+ activitySettingsAppearanceBinding.langFrame.setOnClickListener(
view -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx)
diff --git a/app/src/main/java/org/mian/gitnex/activities/SettingsGeneralActivity.java b/app/src/main/java/org/mian/gitnex/activities/SettingsGeneralActivity.java
index 29590950..a12c1a6d 100644
--- a/app/src/main/java/org/mian/gitnex/activities/SettingsGeneralActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/SettingsGeneralActivity.java
@@ -71,7 +71,7 @@ public class SettingsGeneralActivity extends BaseActivity {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.navRepos));
} else if (homeScreenSelectedChoice == 4) {
- viewBinding.homeScreenSelected.setText(getResources().getString(R.string.navProfile));
+ viewBinding.homeScreenSelected.setText(getResources().getString(R.string.navAccount));
} else if (homeScreenSelectedChoice == 5) {
viewBinding.homeScreenSelected.setText(
@@ -96,6 +96,10 @@ public class SettingsGeneralActivity extends BaseActivity {
} else if (homeScreenSelectedChoice == 11) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.dashboard));
+ } else if (homeScreenSelectedChoice == 12) {
+
+ viewBinding.homeScreenSelected.setText(
+ getResources().getString(R.string.navWatchedRepositories));
}
viewBinding.homeScreenFrame.setOnClickListener(
diff --git a/app/src/main/java/org/mian/gitnex/adapters/MyProfileEmailsAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/AccountSettingsEmailsAdapter.java
similarity index 80%
rename from app/src/main/java/org/mian/gitnex/adapters/MyProfileEmailsAdapter.java
rename to app/src/main/java/org/mian/gitnex/adapters/AccountSettingsEmailsAdapter.java
index ccd13c0c..20de1b8f 100644
--- a/app/src/main/java/org/mian/gitnex/adapters/MyProfileEmailsAdapter.java
+++ b/app/src/main/java/org/mian/gitnex/adapters/AccountSettingsEmailsAdapter.java
@@ -17,29 +17,29 @@ import org.mian.gitnex.R;
/**
* @author M M Arif
*/
-public class MyProfileEmailsAdapter
- extends RecyclerView.Adapter {
+public class AccountSettingsEmailsAdapter
+ extends RecyclerView.Adapter {
private final List emailsList;
private final Context context;
- public MyProfileEmailsAdapter(Context ctx, List emailsListMain) {
+ public AccountSettingsEmailsAdapter(Context ctx, List emailsListMain) {
this.context = ctx;
this.emailsList = emailsListMain;
}
@NonNull @Override
- public MyProfileEmailsAdapter.EmailsViewHolder onCreateViewHolder(
+ public AccountSettingsEmailsAdapter.EmailsViewHolder onCreateViewHolder(
@NonNull ViewGroup parent, int viewType) {
View v =
LayoutInflater.from(parent.getContext())
- .inflate(R.layout.list_profile_emails, parent, false);
- return new MyProfileEmailsAdapter.EmailsViewHolder(v);
+ .inflate(R.layout.list_account_settings_emails, parent, false);
+ return new AccountSettingsEmailsAdapter.EmailsViewHolder(v);
}
@Override
public void onBindViewHolder(
- @NonNull MyProfileEmailsAdapter.EmailsViewHolder holder, int position) {
+ @NonNull AccountSettingsEmailsAdapter.EmailsViewHolder holder, int position) {
Email currentItem = emailsList.get(position);
diff --git a/app/src/main/java/org/mian/gitnex/adapters/SSHKeysAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/SSHKeysAdapter.java
new file mode 100644
index 00000000..2cc3ef1f
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/adapters/SSHKeysAdapter.java
@@ -0,0 +1,59 @@
+package org.mian.gitnex.adapters;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+import java.util.List;
+import org.gitnex.tea4j.v2.models.PublicKey;
+import org.mian.gitnex.R;
+
+/**
+ * @author M M Arif
+ */
+public class SSHKeysAdapter extends RecyclerView.Adapter {
+
+ private final List keysList;
+
+ public SSHKeysAdapter(List keysListMain) {
+ this.keysList = keysListMain;
+ }
+
+ @NonNull @Override
+ public SSHKeysAdapter.KeysViewHolder onCreateViewHolder(
+ @NonNull ViewGroup parent, int viewType) {
+ View v =
+ LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.list_account_settings_ssh_keys, parent, false);
+ return new SSHKeysAdapter.KeysViewHolder(v);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull SSHKeysAdapter.KeysViewHolder holder, int position) {
+
+ PublicKey currentItem = keysList.get(position);
+
+ holder.keyName.setText(currentItem.getTitle());
+ holder.key.setText(currentItem.getKey());
+ }
+
+ @Override
+ public int getItemCount() {
+ return keysList.size();
+ }
+
+ static class KeysViewHolder extends RecyclerView.ViewHolder {
+
+ private final TextView keyName;
+ private final TextView key;
+
+ private KeysViewHolder(View itemView) {
+ super(itemView);
+
+ keyName = itemView.findViewById(R.id.keyName);
+ key = itemView.findViewById(R.id.key);
+ }
+ }
+}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsEmailsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsEmailsFragment.java
new file mode 100644
index 00000000..66599551
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsEmailsFragment.java
@@ -0,0 +1,104 @@
+package org.mian.gitnex.fragments;
+
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+import org.mian.gitnex.activities.AccountSettingsEmailActivity;
+import org.mian.gitnex.adapters.AccountSettingsEmailsAdapter;
+import org.mian.gitnex.databinding.FragmentAccountSettingsEmailsBinding;
+import org.mian.gitnex.viewmodels.AccountSettingsEmailsViewModel;
+
+/**
+ * @author M M Arif
+ */
+public class AccountSettingsEmailsFragment extends Fragment {
+
+ public static boolean refreshEmails = false;
+ private AccountSettingsEmailsViewModel accountSettingsEmailsViewModel;
+ private AccountSettingsEmailsAdapter adapter;
+
+ public AccountSettingsEmailsFragment() {}
+
+ private FragmentAccountSettingsEmailsBinding fragmentAccountSettingsEmailsBinding;
+
+ @Override
+ public View onCreateView(
+ @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ fragmentAccountSettingsEmailsBinding =
+ FragmentAccountSettingsEmailsBinding.inflate(inflater, container, false);
+ accountSettingsEmailsViewModel =
+ new ViewModelProvider(this).get(AccountSettingsEmailsViewModel.class);
+
+ final SwipeRefreshLayout swipeRefresh = fragmentAccountSettingsEmailsBinding.pullToRefresh;
+
+ fragmentAccountSettingsEmailsBinding.recyclerView.setHasFixedSize(true);
+ fragmentAccountSettingsEmailsBinding.recyclerView.setLayoutManager(
+ new LinearLayoutManager(getContext()));
+
+ swipeRefresh.setOnRefreshListener(
+ () ->
+ new Handler(Looper.getMainLooper())
+ .postDelayed(
+ () -> {
+ swipeRefresh.setRefreshing(false);
+ accountSettingsEmailsViewModel.loadEmailsList(
+ getContext());
+ },
+ 200));
+
+ fetchDataAsync();
+
+ fragmentAccountSettingsEmailsBinding.addNewEmailAddress.setOnClickListener(
+ v1 -> startActivity(new Intent(getContext(), AccountSettingsEmailActivity.class)));
+
+ return fragmentAccountSettingsEmailsBinding.getRoot();
+ }
+
+ @SuppressLint("NotifyDataSetChanged")
+ private void fetchDataAsync() {
+
+ accountSettingsEmailsViewModel
+ .getEmailsList(getContext())
+ .observe(
+ getViewLifecycleOwner(),
+ emailsListMain -> {
+ adapter =
+ new AccountSettingsEmailsAdapter(getContext(), emailsListMain);
+ if (adapter.getItemCount() > 0) {
+ fragmentAccountSettingsEmailsBinding.recyclerView.setAdapter(
+ adapter);
+ fragmentAccountSettingsEmailsBinding.noDataEmails.setVisibility(
+ View.GONE);
+ } else {
+ adapter.notifyDataSetChanged();
+ fragmentAccountSettingsEmailsBinding.recyclerView.setAdapter(
+ adapter);
+ fragmentAccountSettingsEmailsBinding.noDataEmails.setVisibility(
+ View.VISIBLE);
+ }
+ fragmentAccountSettingsEmailsBinding.progressBar.setVisibility(
+ View.GONE);
+ });
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ if (refreshEmails) {
+ accountSettingsEmailsViewModel.loadEmailsList(getContext());
+ refreshEmails = false;
+ }
+ }
+}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsFragment.java
new file mode 100644
index 00000000..5fa523be
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsFragment.java
@@ -0,0 +1,138 @@
+package org.mian.gitnex.fragments;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.viewpager2.adapter.FragmentStateAdapter;
+import androidx.viewpager2.widget.ViewPager2;
+import com.google.android.material.tabs.TabLayout;
+import com.google.android.material.tabs.TabLayoutMediator;
+import org.mian.gitnex.R;
+import org.mian.gitnex.activities.BaseActivity;
+import org.mian.gitnex.activities.MainActivity;
+import org.mian.gitnex.helpers.AppUtil;
+import org.mian.gitnex.helpers.TinyDB;
+import org.mian.gitnex.helpers.ViewPager2Transformers;
+import org.mian.gitnex.helpers.contexts.AccountContext;
+
+/**
+ * @author M M Arif
+ */
+public class AccountSettingsFragment extends Fragment {
+
+ public ViewPager2 viewPager;
+ private Context ctx;
+ private View view;
+ private Typeface myTypeface;
+ private TinyDB tinyDB;
+
+ @Nullable @Override
+ public View onCreateView(
+ @NonNull LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+
+ ctx = getContext();
+ tinyDB = TinyDB.getInstance(ctx);
+
+ view = inflater.inflate(R.layout.fragment_account_settings, container, false);
+ setHasOptionsMenu(false);
+
+ ((MainActivity) requireActivity())
+ .setActionBarTitle(getResources().getString(R.string.navAccount));
+
+ myTypeface = AppUtil.getTypeface(ctx);
+
+ AccountContext account = ((BaseActivity) requireActivity()).getAccount();
+ if (account.getUserInfo() != null) {
+ viewData();
+ } else {
+ ((MainActivity) requireActivity())
+ .setProfileInitListener(
+ (text) -> {
+ viewData();
+ });
+ }
+
+ return view;
+ }
+
+ public void viewData() {
+
+ TabLayout tabLayout = view.findViewById(R.id.tabs);
+
+ if (viewPager == null) {
+
+ viewPager = view.findViewById(R.id.accountSettingsContainer);
+ viewPager.setOffscreenPageLimit(1);
+
+ viewPager.setAdapter(new ViewPagerAdapter(this));
+
+ ViewPager2Transformers.returnSelectedTransformer(
+ viewPager, tinyDB.getInt("fragmentTabsAnimationId", 0));
+
+ String[] tabTitles = {
+ ctx.getResources().getString(R.string.accountEmails),
+ ctx.getResources().getString(R.string.sshKeys)
+ };
+ new TabLayoutMediator(
+ tabLayout,
+ viewPager,
+ (tab, position) -> tab.setText(tabTitles[position]))
+ .attach();
+
+ ViewGroup viewGroup = (ViewGroup) tabLayout.getChildAt(0);
+ int tabsCount_ = viewGroup.getChildCount();
+
+ for (int j = 0; j < tabsCount_; j++) {
+
+ ViewGroup vgTab = (ViewGroup) viewGroup.getChildAt(j);
+ int tabChildCount = vgTab.getChildCount();
+
+ for (int i = 0; i < tabChildCount; i++) {
+
+ View tabViewChild = vgTab.getChildAt(i);
+
+ if (tabViewChild instanceof TextView) {
+
+ ((TextView) tabViewChild).setTypeface(myTypeface);
+ }
+ }
+ }
+ }
+ }
+
+ public static class ViewPagerAdapter extends FragmentStateAdapter {
+
+ public ViewPagerAdapter(@NonNull Fragment fa) {
+ super(fa);
+ }
+
+ @NonNull @Override
+ public Fragment createFragment(int position) {
+
+ Fragment fragment = null;
+
+ switch (position) {
+ case 0: // Emails
+ return new AccountSettingsEmailsFragment();
+ case 1: // SSH keys
+ return new SSHKeysFragment();
+ }
+ assert false;
+ return fragment;
+ }
+
+ @Override
+ public int getItemCount() {
+ return 2;
+ }
+ }
+}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java b/app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java
index 8657194d..6c0520b0 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java
@@ -18,6 +18,7 @@ import org.mian.gitnex.R;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.TinyDB;
+import org.mian.gitnex.helpers.ViewPager2Transformers;
/**
* @author M M Arif
@@ -47,6 +48,9 @@ public class ExploreFragment extends Fragment {
Typeface myTypeface = AppUtil.getTypeface(requireContext());
viewPager.setAdapter(new ViewPagerAdapter(this));
+ ViewPager2Transformers.returnSelectedTransformer(
+ viewPager, tinyDB.getInt("fragmentTabsAnimationId", 0));
+
String[] tabTitles = {
getResources().getString(R.string.navRepos),
getResources().getString(R.string.pageTitleIssues),
diff --git a/app/src/main/java/org/mian/gitnex/fragments/MyProfileEmailsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/MyProfileEmailsFragment.java
deleted file mode 100644
index 18797f9f..00000000
--- a/app/src/main/java/org/mian/gitnex/fragments/MyProfileEmailsFragment.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.mian.gitnex.fragments;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import androidx.annotation.NonNull;
-import androidx.fragment.app.Fragment;
-import androidx.lifecycle.ViewModelProvider;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
-import org.mian.gitnex.activities.MyProfileEmailActivity;
-import org.mian.gitnex.adapters.MyProfileEmailsAdapter;
-import org.mian.gitnex.databinding.FragmentProfileEmailsBinding;
-import org.mian.gitnex.viewmodels.ProfileEmailsViewModel;
-
-/**
- * @author M M Arif
- */
-public class MyProfileEmailsFragment extends Fragment {
-
- public static boolean refreshEmails = false;
- private ProfileEmailsViewModel profileEmailsViewModel;
- private ProgressBar mProgressBar;
- private MyProfileEmailsAdapter adapter;
- private RecyclerView mRecyclerView;
- private TextView noDataEmails;
-
- public MyProfileEmailsFragment() {}
-
- @Override
- public View onCreateView(
- @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-
- FragmentProfileEmailsBinding fragmentProfileEmailsBinding =
- FragmentProfileEmailsBinding.inflate(inflater, container, false);
- profileEmailsViewModel = new ViewModelProvider(this).get(ProfileEmailsViewModel.class);
-
- final SwipeRefreshLayout swipeRefresh = fragmentProfileEmailsBinding.pullToRefresh;
-
- noDataEmails = fragmentProfileEmailsBinding.noDataEmails;
- mRecyclerView = fragmentProfileEmailsBinding.recyclerView;
-
- mRecyclerView.setHasFixedSize(true);
- mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
-
- mProgressBar = fragmentProfileEmailsBinding.progressBar;
-
- swipeRefresh.setOnRefreshListener(
- () ->
- new Handler(Looper.getMainLooper())
- .postDelayed(
- () -> {
- swipeRefresh.setRefreshing(false);
- profileEmailsViewModel.loadEmailsList(getContext());
- },
- 200));
-
- fetchDataAsync();
-
- fragmentProfileEmailsBinding.addNewEmailAddress.setOnClickListener(
- v1 -> startActivity(new Intent(getContext(), MyProfileEmailActivity.class)));
-
- return fragmentProfileEmailsBinding.getRoot();
- }
-
- private void fetchDataAsync() {
-
- profileEmailsViewModel
- .getEmailsList(getContext())
- .observe(
- getViewLifecycleOwner(),
- emailsListMain -> {
- adapter = new MyProfileEmailsAdapter(getContext(), emailsListMain);
- if (adapter.getItemCount() > 0) {
- mRecyclerView.setAdapter(adapter);
- noDataEmails.setVisibility(View.GONE);
- } else {
- adapter.notifyDataSetChanged();
- mRecyclerView.setAdapter(adapter);
- noDataEmails.setVisibility(View.VISIBLE);
- }
- mProgressBar.setVisibility(View.GONE);
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- if (refreshEmails) {
- profileEmailsViewModel.loadEmailsList(getContext());
- refreshEmails = false;
- }
- }
-}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowersFragment.java b/app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowersFragment.java
deleted file mode 100644
index 31586d2e..00000000
--- a/app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowersFragment.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package org.mian.gitnex.fragments;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import androidx.annotation.NonNull;
-import androidx.fragment.app.Fragment;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import java.util.ArrayList;
-import java.util.List;
-import org.gitnex.tea4j.v2.models.User;
-import org.mian.gitnex.R;
-import org.mian.gitnex.adapters.UsersAdapter;
-import org.mian.gitnex.clients.RetrofitClient;
-import org.mian.gitnex.databinding.FragmentProfileFollowersFollowingBinding;
-import org.mian.gitnex.helpers.Constants;
-import org.mian.gitnex.helpers.SnackBar;
-import retrofit2.Call;
-import retrofit2.Callback;
-import retrofit2.Response;
-
-/**
- * @author M M Arif
- */
-public class MyProfileFollowersFragment extends Fragment {
-
- private final String TAG = "MyProfileFollowersFragment";
- private FragmentProfileFollowersFollowingBinding viewBinding;
- private Context context;
- private List dataList;
- private UsersAdapter adapter;
- private int pageSize;
- private int resultLimit;
-
- @Override
- public View onCreateView(
- @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-
- viewBinding = FragmentProfileFollowersFollowingBinding.inflate(inflater, container, false);
- context = getContext();
-
- dataList = new ArrayList<>();
- adapter = new UsersAdapter(dataList, context);
- resultLimit = Constants.getCurrentResultLimit(context);
-
- viewBinding.pullToRefresh.setOnRefreshListener(
- () ->
- new Handler(Looper.getMainLooper())
- .postDelayed(
- () -> {
- viewBinding.pullToRefresh.setRefreshing(false);
- loadInitial(resultLimit);
- adapter.notifyDataChanged();
- },
- 200));
-
- adapter.setLoadMoreListener(
- () ->
- viewBinding.recyclerView.post(
- () -> {
- if (dataList.size() == resultLimit || pageSize == resultLimit) {
- int page = (dataList.size() + resultLimit) / resultLimit;
- loadMore(resultLimit, page);
- }
- }));
-
- viewBinding.recyclerView.setHasFixedSize(true);
- viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context));
- viewBinding.recyclerView.setAdapter(adapter);
-
- loadInitial(resultLimit);
-
- return viewBinding.getRoot();
- }
-
- private void loadInitial(int resultLimit) {
-
- Call> call =
- RetrofitClient.getApiInterface(context).userCurrentListFollowers(1, resultLimit);
- call.enqueue(
- new Callback>() {
- @Override
- public void onResponse(
- @NonNull Call> call,
- @NonNull Response> response) {
- if (response.isSuccessful()) {
- if (response.body() != null && response.body().size() > 0) {
- dataList.clear();
- dataList.addAll(response.body());
- adapter.notifyDataChanged();
- viewBinding.noData.setVisibility(View.GONE);
- } else {
- dataList.clear();
- adapter.notifyDataChanged();
- viewBinding.noData.setVisibility(View.VISIBLE);
- }
- viewBinding.progressBar.setVisibility(View.GONE);
- } else if (response.code() == 404) {
- viewBinding.noData.setVisibility(View.VISIBLE);
- viewBinding.progressBar.setVisibility(View.GONE);
- } else {
- Log.e(TAG, String.valueOf(response.code()));
- }
- }
-
- @Override
- public void onFailure(@NonNull Call> call, @NonNull Throwable t) {
- Log.e(TAG, t.toString());
- }
- });
- }
-
- private void loadMore(int resultLimit, int page) {
-
- viewBinding.progressBar.setVisibility(View.VISIBLE);
- Call> call =
- RetrofitClient.getApiInterface(context).userCurrentListFollowers(page, resultLimit);
- call.enqueue(
- new Callback>() {
- @Override
- public void onResponse(
- @NonNull Call> call,
- @NonNull Response> response) {
- if (response.isSuccessful()) {
- assert response.body() != null;
- List result = response.body();
- if (result.size() > 0) {
- pageSize = result.size();
- dataList.addAll(result);
- } else {
- SnackBar.info(
- context,
- viewBinding.getRoot(),
- getString(R.string.noMoreData));
- adapter.setMoreDataAvailable(false);
- }
- adapter.notifyDataChanged();
- viewBinding.progressBar.setVisibility(View.GONE);
- } else {
- Log.e(TAG, String.valueOf(response.code()));
- }
- }
-
- @Override
- public void onFailure(@NonNull Call> call, @NonNull Throwable t) {
- Log.e(TAG, t.toString());
- }
- });
- }
-}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowingFragment.java b/app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowingFragment.java
deleted file mode 100644
index 1a972c3f..00000000
--- a/app/src/main/java/org/mian/gitnex/fragments/MyProfileFollowingFragment.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package org.mian.gitnex.fragments;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import androidx.annotation.NonNull;
-import androidx.fragment.app.Fragment;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import java.util.ArrayList;
-import java.util.List;
-import org.gitnex.tea4j.v2.models.User;
-import org.mian.gitnex.R;
-import org.mian.gitnex.adapters.UsersAdapter;
-import org.mian.gitnex.clients.RetrofitClient;
-import org.mian.gitnex.databinding.FragmentProfileFollowersFollowingBinding;
-import org.mian.gitnex.helpers.Constants;
-import org.mian.gitnex.helpers.SnackBar;
-import retrofit2.Call;
-import retrofit2.Callback;
-import retrofit2.Response;
-
-/**
- * @author M M Arif
- */
-public class MyProfileFollowingFragment extends Fragment {
-
- private final String TAG = "MyProfileFollowingFragment";
- private FragmentProfileFollowersFollowingBinding viewBinding;
- private Context context;
- private List dataList;
- private UsersAdapter adapter;
- private int pageSize;
- private int resultLimit;
-
- @Override
- public View onCreateView(
- @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-
- viewBinding = FragmentProfileFollowersFollowingBinding.inflate(inflater, container, false);
- context = getContext();
-
- dataList = new ArrayList<>();
- adapter = new UsersAdapter(dataList, context);
- resultLimit = Constants.getCurrentResultLimit(context);
-
- viewBinding.pullToRefresh.setOnRefreshListener(
- () ->
- new Handler(Looper.getMainLooper())
- .postDelayed(
- () -> {
- viewBinding.pullToRefresh.setRefreshing(false);
- loadInitial(resultLimit);
- adapter.notifyDataChanged();
- },
- 200));
-
- adapter.setLoadMoreListener(
- () ->
- viewBinding.recyclerView.post(
- () -> {
- if (dataList.size() == resultLimit || pageSize == resultLimit) {
- int page = (dataList.size() + resultLimit) / resultLimit;
- loadMore(resultLimit, page);
- }
- }));
-
- viewBinding.recyclerView.setHasFixedSize(true);
- viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context));
- viewBinding.recyclerView.setAdapter(adapter);
-
- loadInitial(resultLimit);
-
- return viewBinding.getRoot();
- }
-
- private void loadInitial(int resultLimit) {
-
- Call> call =
- RetrofitClient.getApiInterface(context).userCurrentListFollowing(1, resultLimit);
- call.enqueue(
- new Callback>() {
-
- @Override
- public void onResponse(
- @NonNull Call> call,
- @NonNull Response> response) {
- if (response.isSuccessful()) {
- if (response.body() != null && response.body().size() > 0) {
- dataList.clear();
- dataList.addAll(response.body());
- adapter.notifyDataChanged();
- viewBinding.noData.setVisibility(View.GONE);
- } else {
- dataList.clear();
- adapter.notifyDataChanged();
- viewBinding.noData.setVisibility(View.VISIBLE);
- }
- viewBinding.progressBar.setVisibility(View.GONE);
- } else if (response.code() == 404) {
- viewBinding.noData.setVisibility(View.VISIBLE);
- viewBinding.progressBar.setVisibility(View.GONE);
- } else {
- Log.e(TAG, String.valueOf(response.code()));
- }
- }
-
- @Override
- public void onFailure(@NonNull Call> call, @NonNull Throwable t) {
- Log.e(TAG, t.toString());
- }
- });
- }
-
- private void loadMore(int resultLimit, int page) {
-
- viewBinding.progressBar.setVisibility(View.VISIBLE);
- Call> call =
- RetrofitClient.getApiInterface(context).userCurrentListFollowing(page, resultLimit);
- call.enqueue(
- new Callback>() {
-
- @Override
- public void onResponse(
- @NonNull Call> call,
- @NonNull Response> response) {
- if (response.isSuccessful()) {
- assert response.body() != null;
- List result = response.body();
- if (result.size() > 0) {
- pageSize = result.size();
- dataList.addAll(result);
- } else {
- SnackBar.info(
- context,
- viewBinding.getRoot(),
- getString(R.string.noMoreData));
- adapter.setMoreDataAvailable(false);
- }
- adapter.notifyDataChanged();
- viewBinding.progressBar.setVisibility(View.GONE);
- } else {
- Log.e(TAG, String.valueOf(response.code()));
- }
- }
-
- @Override
- public void onFailure(@NonNull Call> call, @NonNull Throwable t) {
- Log.e(TAG, t.toString());
- }
- });
- }
-}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/MyProfileFragment.java b/app/src/main/java/org/mian/gitnex/fragments/MyProfileFragment.java
deleted file mode 100644
index 83042f36..00000000
--- a/app/src/main/java/org/mian/gitnex/fragments/MyProfileFragment.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package org.mian.gitnex.fragments;
-
-import android.content.Context;
-import android.graphics.Typeface;
-import android.os.Bundle;
-import android.text.Html;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.FragmentStatePagerAdapter;
-import androidx.viewpager.widget.ViewPager;
-import com.google.android.material.progressindicator.LinearProgressIndicator;
-import com.google.android.material.tabs.TabLayout;
-import java.util.Locale;
-import org.mian.gitnex.R;
-import org.mian.gitnex.activities.BaseActivity;
-import org.mian.gitnex.activities.MainActivity;
-import org.mian.gitnex.clients.PicassoService;
-import org.mian.gitnex.helpers.AppUtil;
-import org.mian.gitnex.helpers.RoundedTransformation;
-import org.mian.gitnex.helpers.contexts.AccountContext;
-
-/**
- * @author M M Arif
- */
-public class MyProfileFragment extends Fragment {
-
- private Context ctx;
-
- @Nullable @Override
- public View onCreateView(
- @NonNull LayoutInflater inflater,
- @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState) {
-
- ctx = getContext();
-
- View v = inflater.inflate(R.layout.fragment_profile, container, false);
- setHasOptionsMenu(false);
-
- ((MainActivity) requireActivity())
- .setActionBarTitle(getResources().getString(R.string.navProfile));
-
- AccountContext account = ((BaseActivity) requireActivity()).getAccount();
- if (account.getUserInfo() != null) {
- viewData(v, account);
- } else {
- // we have to wait until loading is finished
- LinearProgressIndicator loading = v.findViewById(R.id.loadingIndicator);
- loading.setVisibility(View.VISIBLE);
- ((MainActivity) requireActivity())
- .setProfileInitListener(
- (text) -> {
- loading.setVisibility(View.GONE);
- viewData(v, account);
- });
- }
-
- return v;
- }
-
- public void viewData(View v, AccountContext account) {
-
- TextView userFullName = v.findViewById(R.id.userFullName);
- ImageView userAvatar = v.findViewById(R.id.userAvatar);
- TextView userLogin = v.findViewById(R.id.userLogin);
- TextView userLanguage = v.findViewById(R.id.userLanguage);
- TextView userFollowersCount = v.findViewById(R.id.user_followers_count);
- TextView userFollowingCount = v.findViewById(R.id.user_following_count);
- TextView userStarredReposCount = v.findViewById(R.id.user_starred_repos_count);
-
- String[] userLanguageCodes =
- account.getUserInfo().getLanguage() != null
- ? account.getUserInfo().getLanguage().split("-")
- : new String[] {""};
-
- if (userLanguageCodes.length >= 2) {
- Locale locale = new Locale(userLanguageCodes[0], userLanguageCodes[1]);
- userLanguage.setText(locale.getDisplayLanguage());
- } else {
- userLanguage.setText(getResources().getConfiguration().locale.getDisplayLanguage());
- }
-
- userAvatar.setOnClickListener(
- loginId ->
- AppUtil.copyToClipboard(
- ctx,
- account.getAccount().getUserName(),
- ctx.getString(
- R.string.copyLoginIdToClipBoard,
- account.getAccount().getUserName())));
-
- userFullName.setText(Html.fromHtml(account.getFullName()));
- userLogin.setText(getString(R.string.usernameWithAt, account.getAccount().getUserName()));
-
- int avatarRadius = AppUtil.getPixelsFromDensity(ctx, 60);
-
- PicassoService.getInstance(ctx)
- .get()
- .load(account.getUserInfo().getAvatarUrl())
- .transform(new RoundedTransformation(avatarRadius, 0))
- .placeholder(R.drawable.loader_animated)
- .resize(120, 120)
- .centerCrop()
- .into(userAvatar);
-
- userFollowersCount.setText(String.valueOf(account.getUserInfo().getFollowersCount()));
- userFollowingCount.setText(String.valueOf(account.getUserInfo().getFollowingCount()));
- userStarredReposCount.setText(String.valueOf(account.getUserInfo().getStarredReposCount()));
-
- MyProfileFragment.SectionsPagerAdapter mSectionsPagerAdapter =
- new SectionsPagerAdapter(getChildFragmentManager());
-
- ViewPager mViewPager = v.findViewById(R.id.container);
- mViewPager.setAdapter(mSectionsPagerAdapter);
-
- Typeface myTypeface = AppUtil.getTypeface(requireContext());
- TabLayout tabLayout = v.findViewById(R.id.tabs);
-
- ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
- int tabsCount = vg.getChildCount();
-
- for (int j = 0; j < tabsCount; j++) {
-
- ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
- int tabChildCount = vgTab.getChildCount();
-
- for (int i = 0; i < tabChildCount; i++) {
-
- View tabViewChild = vgTab.getChildAt(i);
-
- if (tabViewChild instanceof TextView) {
- ((TextView) tabViewChild).setTypeface(myTypeface);
- }
- }
- }
-
- mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
- tabLayout.addOnTabSelectedListener(
- new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
- }
-
- public static class SectionsPagerAdapter extends FragmentStatePagerAdapter {
-
- SectionsPagerAdapter(FragmentManager fm) {
- super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
- }
-
- @NonNull @Override
- public Fragment getItem(int position) {
-
- switch (position) {
- case 0: // followers
- return new MyProfileFollowersFragment();
-
- case 1: // following
- return new MyProfileFollowingFragment();
-
- case 2: // emails
- return new MyProfileEmailsFragment();
- }
-
- return null;
- }
-
- @Override
- public int getCount() {
- return 3;
- }
- }
-}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/PullRequestChangesFragment.java b/app/src/main/java/org/mian/gitnex/fragments/PullRequestChangesFragment.java
index 0ec55756..21c34218 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/PullRequestChangesFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/PullRequestChangesFragment.java
@@ -10,6 +10,8 @@ import androidx.viewpager2.adapter.FragmentStateAdapter;
import com.google.android.material.tabs.TabLayoutMediator;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.FragmentPrChangesBinding;
+import org.mian.gitnex.helpers.TinyDB;
+import org.mian.gitnex.helpers.ViewPager2Transformers;
/**
* @author qwerty287
@@ -33,6 +35,8 @@ public class PullRequestChangesFragment extends Fragment {
binding = FragmentPrChangesBinding.inflate(inflater, container, false);
+ TinyDB tinyDB = TinyDB.getInstance(getContext());
+
binding.close.setOnClickListener(v -> requireActivity().finish());
binding.container.setAdapter(
@@ -56,6 +60,10 @@ public class PullRequestChangesFragment extends Fragment {
});
String[] tabs =
new String[] {getString(R.string.tabTextFiles), getString(R.string.commits)};
+
+ ViewPager2Transformers.returnSelectedTransformer(
+ binding.container, tinyDB.getInt("fragmentTabsAnimationId", 0));
+
new TabLayoutMediator(
binding.tabs,
binding.container,
diff --git a/app/src/main/java/org/mian/gitnex/fragments/SSHKeysFragment.java b/app/src/main/java/org/mian/gitnex/fragments/SSHKeysFragment.java
new file mode 100644
index 00000000..c061dc07
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/fragments/SSHKeysFragment.java
@@ -0,0 +1,77 @@
+package org.mian.gitnex.fragments;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import org.mian.gitnex.adapters.SSHKeysAdapter;
+import org.mian.gitnex.databinding.FragmentAccountSettingsSshKeysBinding;
+import org.mian.gitnex.viewmodels.AccountSettingsSSHKeysViewModel;
+
+/**
+ * @author M M Arif
+ */
+public class SSHKeysFragment extends Fragment {
+
+ private FragmentAccountSettingsSshKeysBinding viewBinding;
+ private Context context;
+ private SSHKeysAdapter adapter;
+ private AccountSettingsSSHKeysViewModel accountSettingsSSHKeysViewModel;
+
+ @Override
+ public View onCreateView(
+ @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ viewBinding = FragmentAccountSettingsSshKeysBinding.inflate(inflater, container, false);
+ context = getContext();
+
+ accountSettingsSSHKeysViewModel =
+ new ViewModelProvider(this).get(AccountSettingsSSHKeysViewModel.class);
+
+ viewBinding.recyclerView.setHasFixedSize(true);
+ viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context));
+
+ viewBinding.pullToRefresh.setOnRefreshListener(
+ () ->
+ new Handler(Looper.getMainLooper())
+ .postDelayed(
+ () -> {
+ viewBinding.pullToRefresh.setRefreshing(false);
+ accountSettingsSSHKeysViewModel.loadKeysList(context);
+ },
+ 200));
+
+ fetchDataAsync();
+
+ return viewBinding.getRoot();
+ }
+
+ @SuppressLint("NotifyDataSetChanged")
+ private void fetchDataAsync() {
+
+ accountSettingsSSHKeysViewModel
+ .getKeysList(context)
+ .observe(
+ getViewLifecycleOwner(),
+ keysListMain -> {
+ adapter = new SSHKeysAdapter(keysListMain);
+ if (adapter.getItemCount() > 0) {
+ viewBinding.recyclerView.setAdapter(adapter);
+ viewBinding.noData.setVisibility(View.GONE);
+ } else {
+ adapter.notifyDataSetChanged();
+ viewBinding.recyclerView.setAdapter(adapter);
+ viewBinding.noData.setVisibility(View.VISIBLE);
+ }
+ viewBinding.progressBar.setVisibility(View.GONE);
+ });
+ }
+}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/WatchedRepositoriesFragment.java b/app/src/main/java/org/mian/gitnex/fragments/WatchedRepositoriesFragment.java
new file mode 100644
index 00000000..9c0d0d4f
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/fragments/WatchedRepositoriesFragment.java
@@ -0,0 +1,176 @@
+package org.mian.gitnex.fragments;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.LayoutInflater;
+import android.view.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.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import org.mian.gitnex.R;
+import org.mian.gitnex.activities.CreateRepoActivity;
+import org.mian.gitnex.activities.MainActivity;
+import org.mian.gitnex.adapters.ReposListAdapter;
+import org.mian.gitnex.databinding.FragmentRepositoriesBinding;
+import org.mian.gitnex.helpers.Constants;
+import org.mian.gitnex.viewmodels.RepositoriesViewModel;
+
+/**
+ * @author M M Arif
+ */
+public class WatchedRepositoriesFragment extends Fragment {
+
+ private RepositoriesViewModel repositoriesViewModel;
+ private FragmentRepositoriesBinding fragmentRepositoriesBinding;
+ private ReposListAdapter adapter;
+ private int page = 1;
+ private int resultLimit;
+
+ @Override
+ public View onCreateView(
+ @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ fragmentRepositoriesBinding =
+ FragmentRepositoriesBinding.inflate(inflater, container, false);
+ setHasOptionsMenu(true);
+ ((MainActivity) requireActivity())
+ .setActionBarTitle(getResources().getString(R.string.navWatchedRepositories));
+ repositoriesViewModel = new ViewModelProvider(this).get(RepositoriesViewModel.class);
+
+ resultLimit = Constants.getCurrentResultLimit(getContext());
+
+ fragmentRepositoriesBinding.addNewRepo.setOnClickListener(
+ view -> {
+ Intent intent = new Intent(view.getContext(), CreateRepoActivity.class);
+ startActivity(intent);
+ });
+
+ fragmentRepositoriesBinding.recyclerView.setHasFixedSize(true);
+ fragmentRepositoriesBinding.recyclerView.setLayoutManager(
+ new LinearLayoutManager(getContext()));
+
+ fragmentRepositoriesBinding.recyclerView.setPadding(0, 0, 0, 220);
+ fragmentRepositoriesBinding.recyclerView.setClipToPadding(false);
+
+ fragmentRepositoriesBinding.pullToRefresh.setOnRefreshListener(
+ () ->
+ new Handler(Looper.getMainLooper())
+ .postDelayed(
+ () -> {
+ page = 1;
+ fragmentRepositoriesBinding.pullToRefresh.setRefreshing(
+ false);
+ fetchDataAsync();
+ fragmentRepositoriesBinding.progressBar.setVisibility(
+ View.VISIBLE);
+ },
+ 50));
+
+ fetchDataAsync();
+
+ return fragmentRepositoriesBinding.getRoot();
+ }
+
+ private void fetchDataAsync() {
+
+ repositoriesViewModel
+ .getRepositories(
+ page,
+ resultLimit,
+ "",
+ "watched",
+ null,
+ getContext(),
+ fragmentRepositoriesBinding)
+ .observe(
+ getViewLifecycleOwner(),
+ reposListMain -> {
+ adapter = new ReposListAdapter(reposListMain, getContext());
+ adapter.setLoadMoreListener(
+ new ReposListAdapter.OnLoadMoreListener() {
+
+ @Override
+ public void onLoadMore() {
+
+ page += 1;
+ repositoriesViewModel.loadMoreRepos(
+ page,
+ resultLimit,
+ "",
+ "watched",
+ null,
+ getContext(),
+ adapter);
+ fragmentRepositoriesBinding.progressBar.setVisibility(
+ View.VISIBLE);
+ }
+
+ @Override
+ public void onLoadFinished() {
+
+ fragmentRepositoriesBinding.progressBar.setVisibility(
+ View.GONE);
+ }
+ });
+
+ if (adapter.getItemCount() > 0) {
+ fragmentRepositoriesBinding.recyclerView.setAdapter(adapter);
+ fragmentRepositoriesBinding.noData.setVisibility(View.GONE);
+ } else {
+ adapter.notifyDataChanged();
+ fragmentRepositoriesBinding.recyclerView.setAdapter(adapter);
+ fragmentRepositoriesBinding.noData.setVisibility(View.VISIBLE);
+ }
+
+ fragmentRepositoriesBinding.progressBar.setVisibility(View.GONE);
+ });
+ }
+
+ @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) {
+ if (fragmentRepositoriesBinding.recyclerView.getAdapter() != null) {
+ adapter.getFilter().filter(newText);
+ }
+ return false;
+ }
+ });
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ if (MainActivity.reloadRepos) {
+ page = 1;
+ fetchDataAsync();
+ MainActivity.reloadRepos = false;
+ }
+ }
+}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/profile/DetailFragment.java b/app/src/main/java/org/mian/gitnex/fragments/profile/DetailFragment.java
index d037dcab..7040139c 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/profile/DetailFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/profile/DetailFragment.java
@@ -7,7 +7,10 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
+import java.io.IOException;
import java.util.Locale;
+import okhttp3.ResponseBody;
+import org.gitnex.tea4j.v2.models.Repository;
import org.gitnex.tea4j.v2.models.User;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
@@ -16,6 +19,7 @@ import org.mian.gitnex.databinding.FragmentProfileDetailBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
+import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
@@ -63,6 +67,7 @@ public class DetailFragment extends Fragment {
locale = getResources().getConfiguration().locale;
getProfileDetail(username);
+ getProfileRepository(username);
return binding.getRoot();
}
@@ -162,4 +167,133 @@ public class DetailFragment extends Fragment {
}
});
}
+
+ public void getProfileRepository(String username) {
+
+ Call call =
+ RetrofitClient.getApiInterface(context).repoGet(username, ".profile");
+
+ call.enqueue(
+ new Callback<>() {
+
+ @Override
+ public void onResponse(
+ @NonNull Call call,
+ @NonNull retrofit2.Response response) {
+
+ if (response.isSuccessful() && response.body() != null) {
+
+ switch (response.code()) {
+ case 200:
+ String defBranch = response.body().getDefaultBranch();
+ binding.profileRepoView.setVisibility(View.VISIBLE);
+
+ Call call_profile =
+ RetrofitClient.getWebInterface(getContext())
+ .getFileContents(
+ username,
+ ".profile",
+ defBranch,
+ "README.md");
+
+ call_profile.enqueue(
+ new Callback<>() {
+
+ @Override
+ public void onResponse(
+ @NonNull Call call_profile,
+ @NonNull retrofit2.Response
+ response) {
+
+ if (isAdded()) {
+
+ switch (response.code()) {
+ case 200:
+ assert response.body() != null;
+ new Thread(
+ () -> {
+ try {
+ Markdown
+ .render(
+ context,
+ response.body()
+ .string(),
+ binding.profileRepoContent);
+ } catch (
+ IOException
+ e) {
+ requireActivity()
+ .runOnUiThread(
+ () ->
+ Toasty
+ .error(
+ context,
+ context
+ .getString(
+ R
+ .string
+ .genericError)));
+ }
+ })
+ .start();
+ break;
+
+ case 401:
+ binding.profileRepoView
+ .setVisibility(View.GONE);
+ AlertDialogs
+ .authorizationTokenRevokedDialog(
+ context);
+ break;
+
+ case 403:
+ binding.profileRepoView
+ .setVisibility(View.GONE);
+ Toasty.error(
+ context,
+ context.getString(
+ R.string
+ .authorizeError));
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void onFailure(
+ @NonNull Call call_profile,
+ @NonNull Throwable t) {}
+ });
+
+ break;
+
+ case 401:
+ AlertDialogs.authorizationTokenRevokedDialog(context);
+ binding.profileRepoView.setVisibility(View.GONE);
+ break;
+
+ case 403:
+ binding.profileRepoView.setVisibility(View.GONE);
+ Toasty.error(
+ context, context.getString(R.string.authorizeError));
+ break;
+
+ default:
+ binding.profileRepoView.setVisibility(View.GONE);
+ Toasty.error(context, getString(R.string.genericError));
+ break;
+ }
+ }
+ binding.progressBar.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void onFailure(@NonNull Call call, @NonNull Throwable t) {
+ binding.profileRepoView.setVisibility(View.GONE);
+ }
+ });
+ }
}
diff --git a/app/src/main/java/org/mian/gitnex/helpers/ViewPager2Transformers.java b/app/src/main/java/org/mian/gitnex/helpers/ViewPager2Transformers.java
new file mode 100644
index 00000000..86b2d4e6
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/helpers/ViewPager2Transformers.java
@@ -0,0 +1,95 @@
+package org.mian.gitnex.helpers;
+
+import android.view.View;
+import androidx.viewpager2.widget.ViewPager2;
+
+/**
+ * @author M M Arif
+ */
+public abstract class ViewPager2Transformers {
+
+ public static void returnSelectedTransformer(ViewPager2 viewPager, int selection) {
+
+ if (selection == 0) {
+ viewPager.setPageTransformer(new DepthPageTransformer());
+ } else if (selection == 1) {
+ viewPager.setPageTransformer(new ZoomOutPageTransformer());
+ } else if (selection == 2) {
+ viewPager.setPageTransformer(null);
+ }
+ }
+
+ public static class DepthPageTransformer implements ViewPager2.PageTransformer {
+ private static final float MIN_SCALE = 0.75f;
+
+ public void transformPage(View view, float position) {
+ int pageWidth = view.getWidth();
+
+ if (position < -1) { // [-Infinity,-1)
+ // This page is way off-screen to the left.
+ view.setAlpha(0f);
+
+ } else if (position <= 0) { // [-1,0]
+ // Use the default slide transition when moving to the left page
+ view.setAlpha(1f);
+ view.setTranslationX(0f);
+ view.setScaleX(1f);
+ view.setScaleY(1f);
+
+ } else if (position <= 1) { // (0,1]
+ // Fade the page out.
+ view.setAlpha(1 - position);
+
+ // Counteract the default slide transition
+ view.setTranslationX(pageWidth * -position);
+
+ // Scale the page down (between MIN_SCALE and 1)
+ float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
+ view.setScaleX(scaleFactor);
+ view.setScaleY(scaleFactor);
+
+ } else { // (1,+Infinity]
+ // This page is way off-screen to the right.
+ view.setAlpha(0f);
+ }
+ }
+ }
+
+ public static class ZoomOutPageTransformer implements ViewPager2.PageTransformer {
+ private static final float MIN_SCALE = 0.85f;
+ private static final float MIN_ALPHA = 0.5f;
+
+ public void transformPage(View view, float position) {
+ int pageWidth = view.getWidth();
+ int pageHeight = view.getHeight();
+
+ if (position < -1) { // [-Infinity,-1)
+ // This page is way off-screen to the left.
+ view.setAlpha(0f);
+
+ } else if (position <= 1) { // [-1,1]
+ // Modify the default slide transition to shrink the page as well.
+ float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
+ float vertMargin = pageHeight * (1 - scaleFactor) / 2;
+ float horzMargin = pageWidth * (1 - scaleFactor) / 2;
+ if (position < 0) {
+ view.setTranslationX(horzMargin - vertMargin / 2);
+ } else {
+ view.setTranslationX(-horzMargin + vertMargin / 2);
+ }
+
+ // Scale the page down (between MIN_SCALE and 1).
+ view.setScaleX(scaleFactor);
+ view.setScaleY(scaleFactor);
+
+ // Fade the page relative to its size.
+ view.setAlpha(
+ MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA));
+
+ } else { // (1,+Infinity]
+ // This page is way off-screen to the right.
+ view.setAlpha(0f);
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/org/mian/gitnex/viewmodels/ProfileEmailsViewModel.java b/app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsEmailsViewModel.java
similarity index 95%
rename from app/src/main/java/org/mian/gitnex/viewmodels/ProfileEmailsViewModel.java
rename to app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsEmailsViewModel.java
index c442025e..a0b7e00d 100644
--- a/app/src/main/java/org/mian/gitnex/viewmodels/ProfileEmailsViewModel.java
+++ b/app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsEmailsViewModel.java
@@ -17,7 +17,7 @@ import retrofit2.Response;
/**
* @author M M Arif
*/
-public class ProfileEmailsViewModel extends ViewModel {
+public class AccountSettingsEmailsViewModel extends ViewModel {
private MutableLiveData> emailsList;
diff --git a/app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsSSHKeysViewModel.java b/app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsSSHKeysViewModel.java
new file mode 100644
index 00000000..0ff5f8b1
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/viewmodels/AccountSettingsSSHKeysViewModel.java
@@ -0,0 +1,63 @@
+package org.mian.gitnex.viewmodels;
+
+import android.content.Context;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.ViewModel;
+import java.util.List;
+import org.gitnex.tea4j.v2.models.PublicKey;
+import org.mian.gitnex.R;
+import org.mian.gitnex.clients.RetrofitClient;
+import org.mian.gitnex.helpers.Constants;
+import org.mian.gitnex.helpers.Toasty;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+/**
+ * @author M M Arif
+ */
+public class AccountSettingsSSHKeysViewModel extends ViewModel {
+
+ private MutableLiveData> keysList;
+ private int resultLimit;
+
+ public LiveData> getKeysList(Context ctx) {
+
+ keysList = new MutableLiveData<>();
+ resultLimit = Constants.getCurrentResultLimit(ctx);
+ loadKeysList(ctx);
+
+ return keysList;
+ }
+
+ public void loadKeysList(Context ctx) {
+
+ Call> call =
+ RetrofitClient.getApiInterface(ctx).userCurrentListKeys("", 1, resultLimit);
+
+ call.enqueue(
+ new Callback<>() {
+
+ @Override
+ public void onResponse(
+ @NonNull Call> call,
+ @NonNull Response> response) {
+
+ if (response.isSuccessful()) {
+ keysList.postValue(response.body());
+ } else {
+ Toasty.error(ctx, ctx.getString(R.string.genericError));
+ }
+ }
+
+ @Override
+ public void onFailure(
+ @NonNull Call> call, @NonNull Throwable t) {
+
+ Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/org/mian/gitnex/viewmodels/RepositoriesViewModel.java b/app/src/main/java/org/mian/gitnex/viewmodels/RepositoriesViewModel.java
index b69c148e..67e65335 100644
--- a/app/src/main/java/org/mian/gitnex/viewmodels/RepositoriesViewModel.java
+++ b/app/src/main/java/org/mian/gitnex/viewmodels/RepositoriesViewModel.java
@@ -70,6 +70,11 @@ public class RepositoriesViewModel extends ViewModel {
RetrofitClient.getApiInterface(ctx)
.orgListTeamRepos(Long.valueOf(userLogin), page, resultLimit);
break;
+ case "watched":
+ call =
+ RetrofitClient.getApiInterface(ctx)
+ .userCurrentListSubscriptions(page, resultLimit);
+ break;
default:
call = RetrofitClient.getApiInterface(ctx).userCurrentListRepos(page, resultLimit);
break;
diff --git a/app/src/main/res/drawable/app_logo_monochrome.xml b/app/src/main/res/drawable/app_logo_monochrome.xml
new file mode 100644
index 00000000..5b98d2c3
--- /dev/null
+++ b/app/src/main/res/drawable/app_logo_monochrome.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_account_settings.xml b/app/src/main/res/drawable/ic_account_settings.xml
new file mode 100644
index 00000000..976c1618
--- /dev/null
+++ b/app/src/main/res/drawable/ic_account_settings.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml
index 6e1d4eda..6ebb51f6 100644
--- a/app/src/main/res/drawable/ic_add.xml
+++ b/app/src/main/res/drawable/ic_add.xml
@@ -1,5 +1,20 @@
-
-
+
+
+
diff --git a/app/src/main/res/drawable/ic_done.xml b/app/src/main/res/drawable/ic_done.xml
index 770e2652..b98ac290 100644
--- a/app/src/main/res/drawable/ic_done.xml
+++ b/app/src/main/res/drawable/ic_done.xml
@@ -1,6 +1,20 @@
-
-
+
+
+
diff --git a/app/src/main/res/drawable/ic_language.xml b/app/src/main/res/drawable/ic_language.xml
index 4d56c51a..b8760cfb 100644
--- a/app/src/main/res/drawable/ic_language.xml
+++ b/app/src/main/res/drawable/ic_language.xml
@@ -1,6 +1,27 @@
-
-
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_markdown.xml b/app/src/main/res/drawable/ic_markdown.xml
index b999100a..2ab34692 100644
--- a/app/src/main/res/drawable/ic_markdown.xml
+++ b/app/src/main/res/drawable/ic_markdown.xml
@@ -1,5 +1,27 @@
-
-
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_pin.xml b/app/src/main/res/drawable/ic_pin.xml
index 752919a6..07b1453a 100644
--- a/app/src/main/res/drawable/ic_pin.xml
+++ b/app/src/main/res/drawable/ic_pin.xml
@@ -1,11 +1,20 @@
-
+android:width="24dp"
+android:height="24dp"
+android:viewportWidth="24"
+android:viewportHeight="24">
+
+
diff --git a/app/src/main/res/drawable/ic_remove.xml b/app/src/main/res/drawable/ic_remove.xml
index 7d4ed879..d39378d2 100644
--- a/app/src/main/res/drawable/ic_remove.xml
+++ b/app/src/main/res/drawable/ic_remove.xml
@@ -1,5 +1,13 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_reply.xml b/app/src/main/res/drawable/ic_reply.xml
index 26538623..227306a2 100644
--- a/app/src/main/res/drawable/ic_reply.xml
+++ b/app/src/main/res/drawable/ic_reply.xml
@@ -1,5 +1,20 @@
-
-
+
+
+
diff --git a/app/src/main/res/drawable/ic_star.xml b/app/src/main/res/drawable/ic_star.xml
index cdf6b04e..c06bb8aa 100644
--- a/app/src/main/res/drawable/ic_star.xml
+++ b/app/src/main/res/drawable/ic_star.xml
@@ -2,7 +2,6 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
-
android:viewportHeight="24">
-
-
+android:width="24dp"
+android:height="24dp"
+android:viewportWidth="24"
+android:viewportHeight="24">
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_verified_user.xml b/app/src/main/res/drawable/ic_verified_user.xml
index ccced5da..a7723da3 100644
--- a/app/src/main/res/drawable/ic_verified_user.xml
+++ b/app/src/main/res/drawable/ic_verified_user.xml
@@ -1,6 +1,20 @@
-
-
+
+
+
diff --git a/app/src/main/res/drawable/ic_warning.xml b/app/src/main/res/drawable/ic_warning.xml
index d35666b4..b2dedfed 100644
--- a/app/src/main/res/drawable/ic_warning.xml
+++ b/app/src/main/res/drawable/ic_warning.xml
@@ -1,5 +1,27 @@
-
-
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_watchers.xml b/app/src/main/res/drawable/ic_watchers.xml
index 3a307142..82973b4c 100644
--- a/app/src/main/res/drawable/ic_watchers.xml
+++ b/app/src/main/res/drawable/ic_watchers.xml
@@ -1,6 +1,20 @@
-
-
+
+
+
diff --git a/app/src/main/res/drawable/shape_bottom_sheet_top_corners.xml b/app/src/main/res/drawable/shape_bottom_sheet_top_corners.xml
index ee5b9710..68443243 100644
--- a/app/src/main/res/drawable/shape_bottom_sheet_top_corners.xml
+++ b/app/src/main/res/drawable/shape_bottom_sheet_top_corners.xml
@@ -3,10 +3,10 @@
android:shape="rectangle">
+ android:topLeftRadius="@dimen/dimen32dp"
+ android:topRightRadius="@dimen/dimen32dp"/>
-
+
diff --git a/app/src/main/res/layout/activity_profile_email.xml b/app/src/main/res/layout/activity_account_settings_email.xml
similarity index 98%
rename from app/src/main/res/layout/activity_profile_email.xml
rename to app/src/main/res/layout/activity_account_settings_email.xml
index d1e08692..a4b5c8dd 100644
--- a/app/src/main/res/layout/activity_profile_email.xml
+++ b/app/src/main/res/layout/activity_account_settings_email.xml
@@ -60,7 +60,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
- android:hint="@string/profileEmailTitle"
+ android:hint="@string/accountEmailTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
diff --git a/app/src/main/res/layout/activity_org_detail.xml b/app/src/main/res/layout/activity_org_detail.xml
index 54e57a11..6b948f98 100644
--- a/app/src/main/res/layout/activity_org_detail.xml
+++ b/app/src/main/res/layout/activity_org_detail.xml
@@ -40,51 +40,19 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
- android:visibility="gone"
app:tabIndicatorColor="?attr/pagerTabIndicatorColor"
- app:tabMode="scrollable"
+ app:tabIndicatorFullWidth="true"
+ app:tabMode="auto"
+ app:tabIndicatorHeight="@dimen/dimen4dp"
app:tabTextAppearance="@style/customTabLayout"
- app:tabTextColor="?attr/primaryTextColor">
-
-
-
-
-
-
-
-
-
-
-
-
+ app:tabTextColor="?attr/primaryTextColor"/>
-
diff --git a/app/src/main/res/layout/activity_org_team_info.xml b/app/src/main/res/layout/activity_org_team_info.xml
index 7a74161f..e5def625 100644
--- a/app/src/main/res/layout/activity_org_team_info.xml
+++ b/app/src/main/res/layout/activity_org_team_info.xml
@@ -51,6 +51,7 @@
app:tabIndicatorColor="?attr/pagerTabIndicatorColor"
app:tabIndicatorFullWidth="true"
app:tabMode="auto"
+ app:tabIndicatorHeight="@dimen/dimen4dp"
app:tabTextAppearance="@style/customTabLayout"
app:tabTextColor="?attr/primaryTextColor"/>
diff --git a/app/src/main/res/layout/activity_profile.xml b/app/src/main/res/layout/activity_profile.xml
index 363d8a80..cb6a05c8 100644
--- a/app/src/main/res/layout/activity_profile.xml
+++ b/app/src/main/res/layout/activity_profile.xml
@@ -39,7 +39,9 @@
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
app:tabIndicatorColor="?attr/pagerTabIndicatorColor"
- app:tabMode="scrollable"
+ app:tabIndicatorFullWidth="true"
+ app:tabMode="auto"
+ app:tabIndicatorHeight="@dimen/dimen4dp"
app:tabTextAppearance="@style/customTabLayout"
app:tabTextColor="?attr/primaryTextColor"/>
diff --git a/app/src/main/res/layout/activity_repo_detail.xml b/app/src/main/res/layout/activity_repo_detail.xml
index f726decd..364b35f9 100644
--- a/app/src/main/res/layout/activity_repo_detail.xml
+++ b/app/src/main/res/layout/activity_repo_detail.xml
@@ -58,7 +58,9 @@
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
app:tabIndicatorColor="?attr/pagerTabIndicatorColor"
- app:tabMode="scrollable"
+ app:tabIndicatorFullWidth="true"
+ app:tabMode="auto"
+ app:tabIndicatorHeight="@dimen/dimen4dp"
app:tabTextAppearance="@style/customTabLayout"
app:tabTextColor="?attr/primaryTextColor">
diff --git a/app/src/main/res/layout/activity_settings_appearance.xml b/app/src/main/res/layout/activity_settings_appearance.xml
index 0d65497c..7ef42d6e 100644
--- a/app/src/main/res/layout/activity_settings_appearance.xml
+++ b/app/src/main/res/layout/activity_settings_appearance.xml
@@ -180,6 +180,39 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_account_settings.xml b/app/src/main/res/layout/fragment_account_settings.xml
new file mode 100644
index 00000000..c8160860
--- /dev/null
+++ b/app/src/main/res/layout/fragment_account_settings.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_profile_emails.xml b/app/src/main/res/layout/fragment_account_settings_emails.xml
similarity index 100%
rename from app/src/main/res/layout/fragment_profile_emails.xml
rename to app/src/main/res/layout/fragment_account_settings_emails.xml
diff --git a/app/src/main/res/layout/fragment_account_settings_ssh_keys.xml b/app/src/main/res/layout/fragment_account_settings_ssh_keys.xml
new file mode 100644
index 00000000..7c6ac3a6
--- /dev/null
+++ b/app/src/main/res/layout/fragment_account_settings_ssh_keys.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_explore.xml b/app/src/main/res/layout/fragment_explore.xml
index 332df9ed..4a14f5f7 100644
--- a/app/src/main/res/layout/fragment_explore.xml
+++ b/app/src/main/res/layout/fragment_explore.xml
@@ -20,7 +20,9 @@
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
app:tabIndicatorColor="?attr/pagerTabIndicatorColor"
- app:tabMode="scrollable"
+ app:tabIndicatorFullWidth="true"
+ app:tabMode="auto"
+ app:tabIndicatorHeight="@dimen/dimen4dp"
app:tabTextAppearance="@style/customTabLayout"
app:tabTextColor="?attr/primaryTextColor"/>
diff --git a/app/src/main/res/layout/fragment_pr_changes.xml b/app/src/main/res/layout/fragment_pr_changes.xml
index ebb85c0c..f18d3922 100644
--- a/app/src/main/res/layout/fragment_pr_changes.xml
+++ b/app/src/main/res/layout/fragment_pr_changes.xml
@@ -42,9 +42,10 @@
android:background="?attr/primaryBackgroundColor"
app:tabGravity="fill"
app:tabIndicatorColor="?attr/pagerTabIndicatorColor"
- app:tabIndicatorFullWidth="false"
app:tabMaxWidth="0dp"
- app:tabMode="fixed"
+ app:tabIndicatorFullWidth="true"
+ app:tabMode="auto"
+ app:tabIndicatorHeight="@dimen/dimen4dp"
app:tabTextAppearance="@style/customTabLayout"
app:tabTextColor="?attr/primaryTextColor"/>
diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml
deleted file mode 100644
index 04d49892..00000000
--- a/app/src/main/res/layout/fragment_profile.xml
+++ /dev/null
@@ -1,273 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/fragment_profile_detail.xml b/app/src/main/res/layout/fragment_profile_detail.xml
index 461ccd2c..f502a159 100644
--- a/app/src/main/res/layout/fragment_profile_detail.xml
+++ b/app/src/main/res/layout/fragment_profile_detail.xml
@@ -17,276 +17,330 @@
style="@style/Widget.Material3.LinearProgressIndicator"
app:indicatorColor="?attr/progressIndicatorColor" />
-
+ android:layout_height="match_parent">
+ android:layout_height="wrap_content">
-
-
-
-
-
-
-
+ style="?attr/materialCardViewFilledStyle"
+ app:cardElevation="@dimen/dimen0dp">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:orientation="horizontal"
+ tools:ignore="UseCompoundDrawables">
-
+
-
+
+
+
+
+ android:paddingStart="@dimen/dimen24dp"
+ android:paddingEnd="@dimen/dimen10dp"
+ android:orientation="vertical">
+
+
+
+
+
+
+
-
-
-
-
-
-
+ android:layout_marginTop="@dimen/dimen20dp"
+ android:layout_marginBottom="@dimen/dimen0dp"
+ android:orientation="horizontal"
+ android:baselineAligned="false">
-
+ android:layout_weight="1"
+ android:gravity="center"
+ android:orientation="vertical">
-
+
+
+
+
+
+
+ android:layout_weight="1"
+ android:gravity="center"
+ android:orientation="vertical">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/app/src/main/res/layout/fragment_repo_info.xml b/app/src/main/res/layout/fragment_repo_info.xml
index eb2edd36..0131bd08 100644
--- a/app/src/main/res/layout/fragment_repo_info.xml
+++ b/app/src/main/res/layout/fragment_repo_info.xml
@@ -254,7 +254,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/repoWatchersInMenu"
- app:srcCompat="@drawable/ic_unwatch"/>
+ app:srcCompat="@drawable/ic_watchers"/>
diff --git a/app/src/main/res/layout/list_account_settings_ssh_keys.xml b/app/src/main/res/layout/list_account_settings_ssh_keys.xml
new file mode 100644
index 00000000..5528b163
--- /dev/null
+++ b/app/src/main/res/layout/list_account_settings_ssh_keys.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/drawer_menu.xml b/app/src/main/res/menu/drawer_menu.xml
index 5be95c19..0b3e6210 100644
--- a/app/src/main/res/menu/drawer_menu.xml
+++ b/app/src/main/res/menu/drawer_menu.xml
@@ -29,6 +29,10 @@
android:icon="@drawable/ic_repo"
android:title="@string/navRepos"/>
+
+
+
+
-
-
\ No newline at end of file
+
+
diff --git a/app/src/main/res/values-v23/themes.xml b/app/src/main/res/values-v23/themes.xml
index a9b4b8cb..7ae108e8 100644
--- a/app/src/main/res/values-v23/themes.xml
+++ b/app/src/main/res/values-v23/themes.xml
@@ -91,4 +91,50 @@
+
+
+
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 11ad1b9c..142929e3 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -65,4 +65,14 @@
#151515
#161918
#0C0C0C
+
+ #0c1a24
+ #7f8699
+ #082437
+ #0c1a24
+ #082437
+ #04121b
+ #9dacb6
+ #14507d
+ #04121b
diff --git a/app/src/main/res/values/settings.xml b/app/src/main/res/values/settings.xml
index 2d985ff3..94c2649d 100644
--- a/app/src/main/res/values/settings.xml
+++ b/app/src/main/res/values/settings.xml
@@ -38,6 +38,7 @@
- Pitch Black
- @string/followSystem
- @string/followSystemBlack
+
@@ -50,6 +51,7 @@
- @string/followSystem
- @string/followSystemBlack
- @string/dynamicColorsFollowSystem
+ - @string/codebergDark
@@ -67,7 +69,7 @@
- @string/pageTitleStarredRepos
- @string/navOrg
- @string/navRepos
- - @string/navProfile
+ - @string/navAccount
- @string/pageTitleExplore
- @string/titleDrafts
- @string/pageTitleNotifications
@@ -75,10 +77,11 @@
- @string/navMostVisited
- @string/navNotes
- @string/dashboard
+ - @string/navWatchedRepositories
- - @string/generalDeepLinkSelectedText
+ - @string/none
- @string/navRepos
- @string/navOrg
- @string/pageTitleNotifications
@@ -109,4 +112,10 @@
- 6
- 8
+
+
+ - @string/fadeOut
+ - @string/zoomOut
+ - @string/none
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f2a757ae..7dbbe187 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -35,6 +35,8 @@
My Issues
Most Visited Repos
Notes
+ Account Settings
+ Watched Repositories
@@ -246,7 +248,6 @@
Home screen, drafts, crash reports
Default Link Handler
Choose what screen should be loaded if the app cannot handle external links. It will redirect you automatically.
- N/A
Select Default Link Handler Screen
Biometric Support
Labels With Text Support
@@ -255,6 +256,9 @@
Indentation
Tabs Width
System Default Font
+ Tabs Animation
+ Fade Out
+ Zoom Out
No more data available
@@ -342,16 +346,19 @@
Followers
Following
- Add Email Address
- Email Address
+ \u0040%1$s
+
+
+
+ Emails
+ Email Address
New email added successfully
Email address is empty
Email address is not valid
Email address is already in use
Primary
- Emails
- \u0040%1$s
-
+ SSH Keys
+
Add / Remove Labels
@@ -516,6 +523,7 @@
Delete %s
Reset
BETA
+ None
Explore users
@@ -778,6 +786,7 @@
Follow system (Light/Dark)
Follow system (Light/Pitch Black)
Dynamic colors - Follow system (Light/Dark)
+ Codeberg (Dark)
Fork of: %s
Adopt
Adopted repository %s
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 30dbb06a..c0cf3ca4 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -182,6 +182,52 @@
+
+
+
+
@@ -389,6 +435,28 @@
+
+
+
+
+
+