UI enhacements (#1300)

Closes #1289

Closes #1277

Closes #1286

Closes #1230

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1300
Co-authored-by: M M Arif <mmarif@swatian.com>
Co-committed-by: M M Arif <mmarif@swatian.com>
This commit is contained in:
M M Arif 2023-09-20 15:30:21 +00:00 committed by M M Arif
parent 6ff10da5a7
commit 238a3a1696
68 changed files with 2017 additions and 1389 deletions

View File

@ -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"/>
<activity
android:name=".activities.MyProfileEmailActivity"
android:name=".activities.AccountSettingsEmailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
<activity
android:name=".activities.AddCollaboratorToRepositoryActivity"

View File

@ -123,6 +123,7 @@ public class RepositoryActions {
if (response.isSuccessful()) {
if (response.code() == 200) {
MainActivity.reloadRepos = true;
Toasty.success(
context,
context.getString(R.string.watchRepositorySuccess));
@ -155,7 +156,7 @@ public class RepositoryActions {
Call<Void> 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) {

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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;
}
}
}
}

View File

@ -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,

View File

@ -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<Void>() {
new Callback<>() {
@Override
public void onResponse(

View File

@ -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),

View File

@ -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)

View File

@ -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(

View File

@ -17,29 +17,29 @@ import org.mian.gitnex.R;
/**
* @author M M Arif
*/
public class MyProfileEmailsAdapter
extends RecyclerView.Adapter<MyProfileEmailsAdapter.EmailsViewHolder> {
public class AccountSettingsEmailsAdapter
extends RecyclerView.Adapter<AccountSettingsEmailsAdapter.EmailsViewHolder> {
private final List<Email> emailsList;
private final Context context;
public MyProfileEmailsAdapter(Context ctx, List<Email> emailsListMain) {
public AccountSettingsEmailsAdapter(Context ctx, List<Email> 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);

View File

@ -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<SSHKeysAdapter.KeysViewHolder> {
private final List<PublicKey> keysList;
public SSHKeysAdapter(List<PublicKey> 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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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),

View File

@ -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;
}
}
}

View File

@ -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<User> 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<List<User>> call =
RetrofitClient.getApiInterface(context).userCurrentListFollowers(1, resultLimit);
call.enqueue(
new Callback<List<User>>() {
@Override
public void onResponse(
@NonNull Call<List<User>> call,
@NonNull Response<List<User>> 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<List<User>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
private void loadMore(int resultLimit, int page) {
viewBinding.progressBar.setVisibility(View.VISIBLE);
Call<List<User>> call =
RetrofitClient.getApiInterface(context).userCurrentListFollowers(page, resultLimit);
call.enqueue(
new Callback<List<User>>() {
@Override
public void onResponse(
@NonNull Call<List<User>> call,
@NonNull Response<List<User>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
List<User> 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<List<User>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
}

View File

@ -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<User> 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<List<User>> call =
RetrofitClient.getApiInterface(context).userCurrentListFollowing(1, resultLimit);
call.enqueue(
new Callback<List<User>>() {
@Override
public void onResponse(
@NonNull Call<List<User>> call,
@NonNull Response<List<User>> 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<List<User>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
private void loadMore(int resultLimit, int page) {
viewBinding.progressBar.setVisibility(View.VISIBLE);
Call<List<User>> call =
RetrofitClient.getApiInterface(context).userCurrentListFollowing(page, resultLimit);
call.enqueue(
new Callback<List<User>>() {
@Override
public void onResponse(
@NonNull Call<List<User>> call,
@NonNull Response<List<User>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
List<User> 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<List<User>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
}

View File

@ -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;
}
}
}

View File

@ -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,

View File

@ -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);
});
}
}

View File

@ -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;
}
}
}

View File

@ -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<Repository> call =
RetrofitClient.getApiInterface(context).repoGet(username, ".profile");
call.enqueue(
new Callback<>() {
@Override
public void onResponse(
@NonNull Call<Repository> call,
@NonNull retrofit2.Response<Repository> response) {
if (response.isSuccessful() && response.body() != null) {
switch (response.code()) {
case 200:
String defBranch = response.body().getDefaultBranch();
binding.profileRepoView.setVisibility(View.VISIBLE);
Call<ResponseBody> call_profile =
RetrofitClient.getWebInterface(getContext())
.getFileContents(
username,
".profile",
defBranch,
"README.md");
call_profile.enqueue(
new Callback<>() {
@Override
public void onResponse(
@NonNull Call<ResponseBody> call_profile,
@NonNull retrofit2.Response<ResponseBody>
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<ResponseBody> 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<Repository> call, @NonNull Throwable t) {
binding.profileRepoView.setVisibility(View.GONE);
}
});
}
}

View File

@ -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);
}
}
}
}

View File

@ -17,7 +17,7 @@ import retrofit2.Response;
/**
* @author M M Arif
*/
public class ProfileEmailsViewModel extends ViewModel {
public class AccountSettingsEmailsViewModel extends ViewModel {
private MutableLiveData<List<Email>> emailsList;

View File

@ -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<List<PublicKey>> keysList;
private int resultLimit;
public LiveData<List<PublicKey>> getKeysList(Context ctx) {
keysList = new MutableLiveData<>();
resultLimit = Constants.getCurrentResultLimit(ctx);
loadKeysList(ctx);
return keysList;
}
public void loadKeysList(Context ctx) {
Call<List<PublicKey>> call =
RetrofitClient.getApiInterface(ctx).userCurrentListKeys("", 1, resultLimit);
call.enqueue(
new Callback<>() {
@Override
public void onResponse(
@NonNull Call<List<PublicKey>> call,
@NonNull Response<List<PublicKey>> response) {
if (response.isSuccessful()) {
keysList.postValue(response.body());
} else {
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(
@NonNull Call<List<PublicKey>> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
}
});
}
}

View File

@ -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;

View File

@ -0,0 +1,16 @@
<vector android:height="108dp" android:viewportHeight="135.47"
android:viewportWidth="135.47" android:width="108dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ececec" android:pathData="M45.28,55.47a4.85,5.71 89.82,1 0,7.97 -6.96a4.85,5.71 89.82,1 0,-7.97 6.96z"/>
<path android:fillColor="#ececec" android:pathData="M45.36,92.58a4.85,5.71 89.82,1 0,7.97 -6.96a4.85,5.71 89.82,1 0,-7.97 6.96z"/>
<path android:fillColor="#ececec" android:pathData="M63.76,74.16a4.85,5.71 89.82,1 0,7.97 -6.96a4.85,5.71 89.82,1 0,-7.97 6.96z"/>
<path android:fillColor="#ececec" android:pathData="M46.92,41.51l4.39,0l-0.06,45.47l-4.39,-0z"/>
<path android:fillColor="#00000000"
android:pathData="M49.11,52.02C68.91,52.09 67.58,49.67 67.65,71.4"
android:strokeColor="#ececec" android:strokeWidth="5.02"/>
<path android:fillColor="#00000000"
android:pathData="M86.2,89.35C66.39,89.28 67.72,91.7 67.65,69.98"
android:strokeColor="#ececec" android:strokeWidth="5.02"/>
<path android:fillColor="#ececec" android:pathData="M82.23,55.47a4.85,5.71 89.82,1 0,7.97 -6.96a4.85,5.71 89.82,1 0,-7.97 6.96z"/>
<path android:fillColor="#ececec" android:pathData="M82.22,92.58a4.85,5.71 89.82,1 0,7.97 -6.96a4.85,5.71 89.82,1 0,-7.97 6.96z"/>
<path android:fillColor="#ececec" android:pathData="M84.04,50.39l4.39,0l-0.06,36.59l-4.39,-0z"/>
</vector>

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M20,7h-9"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M14,17H5"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M17,17m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M7,7m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -1,5 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp"
android:height="24dp" android:tint="#FFFFFF"
android:viewportWidth="24.0" android:viewportHeight="24.0">
<path android:fillColor="#FF000000" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M5,12h14"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M12,5v14"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -1,6 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp"
android:height="24dp" android:tint="?attr/iconsColor"
android:viewportWidth="24.0" android:viewportHeight="24.0">
<path android:fillColor="#FF000000"
android:pathData="M18,7l-1.41,-1.41 -6.34,6.34 1.41,1.41L18,7zM22.24,5.59L11.66,16.17 7.48,12l-1.41,1.41L11.66,19l12,-12 -1.42,-1.41zM0.41,13.41L6,19l1.41,-1.41L1.83,12 0.41,13.41z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M18,6 L7,17l-5,-5"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="m22,10 l-7.5,7.5L13,16"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -1,6 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp"
android:height="24dp" android:tint="?attr/iconsColor"
android:viewportWidth="24.0" android:viewportHeight="24.0">
<path android:fillColor="#FF000000"
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56 1.84,0.63 3.37,1.91 4.33,3.56zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82c0.43,-1.43 1.08,-2.76 1.91,-3.96zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2 0,0.68 0.06,1.34 0.14,2L4.26,14zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56 -1.84,-0.63 -3.37,-1.9 -4.33,-3.56zM8.03,8L5.08,8c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8zM12,19.96c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96h3.82c-0.43,1.43 -1.08,2.76 -1.91,3.96zM14.34,14L9.66,14c-0.09,-0.66 -0.16,-1.32 -0.16,-2 0,-0.68 0.07,-1.35 0.16,-2h4.68c0.09,0.65 0.16,1.32 0.16,2 0,0.68 -0.07,1.34 -0.16,2zM14.59,19.56c0.6,-1.11 1.06,-2.31 1.38,-3.56h2.95c-0.96,1.65 -2.49,2.93 -4.33,3.56zM16.36,14c0.08,-0.66 0.14,-1.32 0.14,-2 0,-0.68 -0.06,-1.34 -0.14,-2h3.38c0.16,0.64 0.26,1.31 0.26,2s-0.1,1.36 -0.26,2h-3.38z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,12m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M2,12L22,12"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M12,2a15.3,15.3 0,0 1,4 10,15.3 15.3,0 0,1 -4,10 15.3,15.3 0,0 1,-4 -10,15.3 15.3,0 0,1 4,-10z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -1,5 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp"
android:height="24dp" android:viewportWidth="16" android:viewportHeight="16">
<path android:fillColor="?attr/iconsColor" android:fillType="evenOdd"
android:pathData="M14.85,3L1.15,3C0.52,3 0,3.52 0,4.15v7.69C0,12.48 0.52,13 1.15,13h13.69c0.64,0 1.15,-0.52 1.15,-1.15v-7.7C16,3.52 15.48,3 14.85,3zM9,11L7,11L7,8L5.5,9.92 4,8v3L2,11L2,5h2l1.5,2L7,5h2v6zM11.99,11.5L9.5,8L11,8L11,5h2v3h1.5l-2.51,3.5z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M3,5m0,2a2,2 0,0 1,2 -2h14a2,2 0,0 1,2 2v10a2,2 0,0 1,-2 2h-14a2,2 0,0 1,-2 -2z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M7,15v-6l2,2l2,-2v6"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M14,13l2,2l2,-2m-2,2v-6"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -1,11 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/iconsColor"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:fillType="evenOdd"
android:pathData="M7.886,1.553a1.75,1.75 0,0 1,2.869 0.604l0.633,1.629a5.666,5.666 0,0 0,3.725 3.395l3.959,1.131a1.75,1.75 0,0 1,0.757 2.92L16.06,15l5.594,5.595a0.75,0.75 0,1 1,-1.06 1.06L15,16.061l-3.768,3.768a1.75,1.75 0,0 1,-2.92 -0.757l-1.131,-3.96a5.667,5.667 0,0 0,-3.395 -3.724l-1.63,-0.633a1.75,1.75 0,0 1,-0.603 -2.869l6.333,-6.333zM14.475,14.465l-0.005,0.005 -0.005,0.005 -4.294,4.293a0.25,0.25 0,0 1,-0.417 -0.108l-1.13,-3.96A7.166,7.166 0,0 0,4.33 9.99L2.7,9.356a0.25,0.25 0,0 1,-0.086 -0.41l6.333,-6.332a0.25,0.25 0,0 1,0.41 0.086l0.633,1.63a7.167,7.167 0,0 0,4.71 4.293l3.96,1.131a0.25,0.25 0,0 1,0.108 0.417l-4.293,4.294z"/>
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,17L12,22"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M5,17h14v-1.76a2,2 0,0 0,-1.11 -1.79l-1.78,-0.9A2,2 0,0 1,15 10.76V6h1a2,2 0,0 0,0 -4H8a2,2 0,0 0,0 4h1v4.76a2,2 0,0 1,-1.11 1.79l-1.78,0.9A2,2 0,0 0,5 15.24Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -1,5 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp"
android:height="24dp" android:tint="#FFFFFF"
android:viewportWidth="24.0" android:viewportHeight="24.0">
<path android:fillColor="#FF000000" android:pathData="M19,13H5v-2h14v2z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M5,12h14"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -1,5 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp"
android:height="24dp" android:tint="?attr/iconsColor"
android:viewportWidth="24.0" android:viewportHeight="24.0">
<path android:fillColor="#FF000000" android:pathData="M10,9V5l-7,7 7,7v-4.1c5,0 8.5,1.6 11,5.1 -1,-5 -4,-10 -11,-11z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M9,17l-5,-5l5,-5"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M20,18v-2a4,4 0,0 0,-4 -4H4"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -2,7 +2,6 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/iconsColor"

View File

@ -2,7 +2,6 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#00000000"

View File

@ -1,20 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#00000000"
android:pathData="M1,12s4,-8 11,-8 11,8 11,8 -4,8 -11,8 -11,-8 -11,-8z"
android:strokeWidth="2"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"
android:strokeLineJoin="round"/>
<path
android:fillColor="#00000000"
android:pathData="M12,12m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
android:strokeWidth="2"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"
android:strokeLineJoin="round"/>
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M9.88,9.88a3,3 0,1 0,4.24 4.24"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M10.73,5.08A10.43,10.43 0,0 1,12 5c7,0 10,7 10,7a13.16,13.16 0,0 1,-1.67 2.68"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M6.61,6.61A13.526,13.526 0,0 0,2 12s3,7 10,7a9.74,9.74 0,0 0,5.39 -1.61"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M2,2L22,22"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -1,6 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp"
android:height="24dp" android:tint="?attr/iconsColor"
android:viewportWidth="24.0" android:viewportHeight="24.0">
<path android:fillColor="#FF000000"
android:pathData="M12,1L3,5v6c0,5.55 3.84,10.74 9,12 5.16,-1.26 9,-6.45 9,-12L21,5l-9,-4zM10,17l-4,-4 1.41,-1.41L10,14.17l6.59,-6.59L18,9l-8,8z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,22s8,-4 8,-10V5l-8,-3 -8,3v7c0,6 8,10 8,10"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="m9,12 l2,2 4,-4"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -1,5 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp"
android:height="24dp" android:tint="?attr/iconsColor"
android:viewportWidth="24.0" android:viewportHeight="24.0">
<path android:fillColor="#FF000000" android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="m21.73,18 l-8,-14a2,2 0,0 0,-3.48 0l-8,14A2,2 0,0 0,4 21h16a2,2 0,0 0,1.73 -3Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M12,9v4"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M12,17h0.01"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -1,6 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp"
android:height="24dp" android:tint="?attr/iconsColor"
android:viewportWidth="24.0" android:viewportHeight="24.0">
<path android:fillColor="#FF000000"
android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M2,12s3,-7 10,-7 10,7 10,7 -3,7 -10,7 -10,-7 -10,-7Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M12,12m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -3,10 +3,10 @@
android:shape="rectangle">
<corners
android:topLeftRadius="@dimen/dimen16dp"
android:topRightRadius="@dimen/dimen16dp"/>
android:topLeftRadius="@dimen/dimen32dp"
android:topRightRadius="@dimen/dimen32dp"/>
<padding android:top="@dimen/dimen12dp"/>
<padding android:top="@dimen/dimen24dp"/>
<solid android:color="?attr/primaryBackgroundColor"/>

View File

@ -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"

View File

@ -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">
<com.google.android.material.tabs.TabItem
android:id="@+id/tabItemInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tabTextInfo"/>
<com.google.android.material.tabs.TabItem
android:id="@+id/tabItem_repos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/navRepos"/>
<com.google.android.material.tabs.TabItem
android:id="@+id/tabItem_labels"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/newIssueLabelsTitle"/>
<com.google.android.material.tabs.TabItem
android:id="@+id/tabItem_teams"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/orgTabTeams"/>
<com.google.android.material.tabs.TabItem
android:id="@+id/tabItem_members"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/orgTabMembers"/>
</com.google.android.material.tabs.TabLayout>
app:tabTextColor="?attr/primaryTextColor"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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">

View File

@ -180,6 +180,39 @@
</LinearLayout>
<LinearLayout
android:id="@+id/fragmentTabsAnimationFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/fragmentTabsAnimationFrameHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/fragmentTabsAnimationHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
<TextView
android:id="@+id/fragmentTabsAnimationFrameSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/fadeOut"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
</LinearLayout>
<RelativeLayout
android:id="@+id/counterBadgeFrame"
android:layout_width="match_parent"

View File

@ -85,7 +85,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/generalDeepLinkSelectedText"
android:text="@string/none"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
app:tabIndicatorColor="?attr/pagerTabIndicatorColor"
app:tabIndicatorFullWidth="true"
app:tabMode="auto"
app:tabIndicatorHeight="@dimen/dimen4dp"
app:tabTextAppearance="@style/customTabLayout"
app:tabMinWidth="@dimen/dimen100dp"
app:tabTextColor="?attr/primaryTextColor">
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/accountSettingsContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/dimen8dp">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/pullToRefresh"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="@dimen/dimen72dp" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</FrameLayout>
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
style="@style/Widget.Material3.LinearProgressIndicator"
app:indicatorColor="?attr/progressIndicatorColor" />
<TextView
android:id="@+id/no_data"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/dimen16dp"
android:gravity="center"
android:text="@string/noDataFound"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"
android:visibility="gone" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -1,273 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/loadingIndicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone" />
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay"
android:background="?attr/primaryBackgroundColor"
app:elevation="@dimen/dimen0dp">
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?attr/materialCardViewFilledStyle"
android:layout_marginStart="@dimen/dimen8dp"
android:layout_marginEnd="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen12dp"
app:cardElevation="@dimen/dimen0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackground"
android:background="?attr/materialCardBackgroundColor"
android:padding="@dimen/dimen24dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<com.google.android.material.card.MaterialCardView
android:layout_width="@dimen/dimen80dp"
android:layout_height="@dimen/dimen80dp"
style="?attr/materialCardViewFilledStyle"
android:layout_marginBottom="@dimen/dimen8dp"
app:cardElevation="@dimen/dimen0dp"
app:cardCornerRadius="@dimen/dimen40dp">
<ImageView
android:id="@+id/userAvatar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/generalImgContentText"
android:src="@mipmap/app_logo_round" />
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/dimen24dp"
android:paddingEnd="@dimen/dimen10dp"
android:orientation="vertical">
<TextView
android:id="@+id/userFullName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textIsSelectable="true"
android:textSize="@dimen/dimen18sp" />
<TextView
android:id="@+id/userLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen10dp"
android:textColor="?attr/primaryTextColor"
android:textIsSelectable="true"
android:textSize="@dimen/dimen14sp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/userLanguageIcon"
android:layout_width="@dimen/dimen16dp"
android:layout_height="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen4dp"
android:contentDescription="@string/generalImgContentText"
android:src="@drawable/ic_language"
app:tint="?attr/iconsColor" />
<TextView
android:id="@+id/userLanguage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textIsSelectable="true"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen20dp"
android:layout_marginBottom="@dimen/dimen0dp"
android:orientation="horizontal"
android:baselineAligned="false">
<LinearLayout
android:id="@+id/followers_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:text="@string/profileTabFollowers"
android:textSize="@dimen/dimen14sp" />
<TextView
android:id="@+id/user_followers_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:paddingTop="@dimen/dimen6dp"
android:textStyle="bold"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/following_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:text="@string/profileTabFollowing"
android:textSize="@dimen/dimen14sp" />
<TextView
android:id="@+id/user_following_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:paddingTop="@dimen/dimen6dp"
android:textStyle="bold"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/starred_repos_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:text="@string/starredRepos"
android:textSize="@dimen/dimen14sp" />
<TextView
android:id="@+id/user_starred_repos_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:paddingTop="@dimen/dimen6dp"
android:textStyle="bold"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
android:layout_marginTop="@dimen/dimen200dp"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
android:id="@+id/fragmentProfileCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/dimen8dp"
app:strokeWidth="@dimen/dimen2dp"
app:cardCornerRadius="@dimen/dimen10dp"
app:strokeColor="?attr/colorPrimary"
style="?attr/materialCardViewFilledStyle">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabTextAppearance="@android:style/TextAppearance.Material.Widget.TabWidget"
app:tabIndicatorGravity="stretch"
app:tabMode="fixed"
app:tabIndicatorColor="?attr/colorPrimary"
app:tabIndicatorFullWidth="true"
android:background="?attr/primaryBackgroundColor"
app:tabSelectedTextColor="@android:color/white"
app:tabTextColor="?attr/colorPrimary">
<com.google.android.material.tabs.TabItem
android:id="@+id/profileTabFollowers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/profileTabFollowers" />
<com.google.android.material.tabs.TabItem
android:id="@+id/profileTabFollowing"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/profileTabFollowing" />
<com.google.android.material.tabs.TabItem
android:id="@+id/profileTabEmails"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/profileTabEmails" />
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen48dp"
android:background="?attr/primaryBackgroundColor"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -17,276 +17,330 @@
style="@style/Widget.Material3.LinearProgressIndicator"
app:indicatorColor="?attr/progressIndicatorColor" />
<com.google.android.material.card.MaterialCardView
<androidx.core.widget.NestedScrollView
android:orientation="vertical"
android:background="?attr/primaryBackgroundColor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?attr/materialCardViewFilledStyle"
android:layout_margin="@dimen/dimen8dp"
app:cardElevation="@dimen/dimen0dp">
android:layout_height="match_parent">
<LinearLayout
android:padding="@dimen/dimen8dp"
android:orientation="vertical"
android:id="@+id/repoInfoLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackground"
android:background="?attr/materialCardBackgroundColor"
android:padding="@dimen/dimen24dp"
android:orientation="vertical">
android:layout_height="wrap_content">
<LinearLayout
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<com.google.android.material.card.MaterialCardView
android:layout_width="@dimen/dimen80dp"
android:layout_height="@dimen/dimen80dp"
style="?attr/materialCardViewFilledStyle"
android:layout_marginBottom="@dimen/dimen8dp"
app:cardElevation="@dimen/dimen0dp"
app:cardCornerRadius="@dimen/dimen40dp">
<ImageView
android:id="@+id/userAvatar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/generalImgContentText"
android:src="@mipmap/app_logo_round" />
</com.google.android.material.card.MaterialCardView>
style="?attr/materialCardViewFilledStyle"
app:cardElevation="@dimen/dimen0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/dimen24dp"
android:paddingEnd="@dimen/dimen10dp"
android:foreground="?android:attr/selectableItemBackground"
android:background="?attr/materialCardBackgroundColor"
android:padding="@dimen/dimen24dp"
android:orientation="vertical">
<TextView
android:id="@+id/userFullName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textIsSelectable="true"
android:textSize="@dimen/dimen18sp" />
<TextView
android:id="@+id/userLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen10dp"
android:textColor="?attr/primaryTextColor"
android:textIsSelectable="true"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen20dp"
android:layout_marginBottom="@dimen/dimen0dp"
android:orientation="horizontal"
android:baselineAligned="false">
<LinearLayout
android:id="@+id/followers_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:text="@string/profileTabFollowers"
android:textSize="@dimen/dimen14sp" />
<TextView
android:id="@+id/user_followers_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:paddingTop="@dimen/dimen6dp"
android:textStyle="bold"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/following_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:text="@string/profileTabFollowing"
android:textSize="@dimen/dimen14sp" />
<TextView
android:id="@+id/user_following_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:paddingTop="@dimen/dimen6dp"
android:textStyle="bold"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/starred_repos_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:text="@string/starredRepos"
android:textSize="@dimen/dimen14sp" />
<TextView
android:id="@+id/user_starred_repos_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:paddingTop="@dimen/dimen6dp"
android:textStyle="bold"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="horizontal">
<ImageView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_email" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen16dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/userEmail"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp" />
<TextView
android:id="@+id/userEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.9"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="horizontal">
<ImageView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_language"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen16dp"
android:gravity="center_vertical"
android:orientation="vertical">
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsLanguageSelectorHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp" />
<com.google.android.material.card.MaterialCardView
android:layout_width="@dimen/dimen80dp"
android:layout_height="@dimen/dimen80dp"
style="?attr/materialCardViewFilledStyle"
android:layout_marginBottom="@dimen/dimen8dp"
app:cardElevation="@dimen/dimen0dp"
app:cardCornerRadius="@dimen/dimen40dp">
<TextView
android:id="@+id/userLang"
<ImageView
android:id="@+id/userAvatar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/generalImgContentText"
android:src="@mipmap/app_logo_round" />
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.9"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp" />
android:paddingStart="@dimen/dimen24dp"
android:paddingEnd="@dimen/dimen10dp"
android:orientation="vertical">
<TextView
android:id="@+id/userFullName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textIsSelectable="true"
android:textSize="@dimen/dimen18sp" />
<TextView
android:id="@+id/userLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen10dp"
android:textColor="?attr/primaryTextColor"
android:textIsSelectable="true"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="horizontal">
<ImageView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_calendar"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen16dp"
android:gravity="center_vertical"
android:orientation="vertical">
android:layout_marginTop="@dimen/dimen20dp"
android:layout_marginBottom="@dimen/dimen0dp"
android:orientation="horizontal"
android:baselineAligned="false">
<TextView
<LinearLayout
android:id="@+id/followers_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/joined"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp" />
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/userJoinedOn"
android:layout_width="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:text="@string/profileTabFollowers"
android:textSize="@dimen/dimen14sp" />
<TextView
android:id="@+id/user_followers_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:paddingTop="@dimen/dimen6dp"
android:textStyle="bold"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/following_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.9"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp" />
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:text="@string/profileTabFollowing"
android:textSize="@dimen/dimen14sp" />
<TextView
android:id="@+id/user_following_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:paddingTop="@dimen/dimen6dp"
android:textStyle="bold"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/starred_repos_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:text="@string/starredRepos"
android:textSize="@dimen/dimen14sp" />
<TextView
android:id="@+id/user_starred_repos_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:paddingTop="@dimen/dimen6dp"
android:textStyle="bold"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="horizontal">
<ImageView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_email" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen16dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/userEmail"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp" />
<TextView
android:id="@+id/userEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.9"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="horizontal">
<ImageView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_language"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen16dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsLanguageSelectorHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp" />
<TextView
android:id="@+id/userLang"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.9"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="horizontal">
<ImageView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_calendar"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen16dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/joined"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp" />
<TextView
android:id="@+id/userJoinedOn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.9"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/profile_repo_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?attr/materialCardViewFilledStyle"
app:cardElevation="@dimen/dimen0dp"
android:layout_marginTop="@dimen/dimen8dp"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackground"
android:background="?attr/materialCardBackgroundColor"
android:padding="@dimen/dimen24dp"
android:orientation="vertical">
<TextView
android:id="@+id/profile_repo_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true"
android:textSize="@dimen/dimen16sp"
android:textColor="?attr/primaryTextColor" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/profile_repo_content1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true"
android:textSize="@dimen/dimen16sp"
android:visibility="gone"
android:textColor="?attr/primaryTextColor" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View File

@ -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"/>
<TextView
android:id="@+id/repoMetaWatchers"

View File

@ -28,7 +28,7 @@
android:id="@+id/userEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/profileEmailTitle"
android:text="@string/accountEmailTitle"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp"/>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingTop="@dimen/dimen4dp"
android:paddingBottom="@dimen/dimen4dp"
tools:ignore="UseCompoundDrawables">
<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="?attr/primaryBackgroundColor"
style="?attr/materialCardViewFilledStyle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/materialCardBackgroundColor"
android:padding="@dimen/dimen12dp"
android:orientation="vertical">
<TextView
android:id="@+id/keyName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sshKeys"
android:textColor="?attr/primaryTextColor"
android:textIsSelectable="true"
android:textSize="@dimen/dimen16sp" />
<TextView
android:id="@+id/key"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sshKeys"
android:layout_marginTop="@dimen/dimen8dp"
android:textColor="?attr/primaryTextColor"
android:textIsSelectable="true"
android:textSize="@dimen/dimen12sp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>

View File

@ -29,6 +29,10 @@
android:icon="@drawable/ic_repo"
android:title="@string/navRepos"/>
<item android:id="@+id/nav_watched_repositories"
android:icon="@drawable/ic_watchers"
android:title="@string/navWatchedRepositories"/>
<item android:id="@+id/nav_my_issues"
android:icon="@drawable/ic_issue"
android:title="@string/navMyIssues"
@ -60,6 +64,10 @@
android:icon="@drawable/ic_person"
android:title="@string/navProfile"/>
<item android:id="@+id/nav_account_settings"
android:icon="@drawable/ic_account_settings"
android:title="@string/navAccount" />
<item android:id="@+id/nav_administration"
android:icon="@drawable/ic_tool"
android:title="@string/navAdministration"

View File

@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/app_logo_background"/>
<foreground android:drawable="@mipmap/app_logo_foreground"/>
</adaptive-icon>
<monochrome android:drawable="@drawable/app_logo_monochrome"/>
</adaptive-icon>

View File

@ -91,4 +91,50 @@
</style>
<!-- Retro theme -->
<!-- Codeberg dark theme -->
<style name="AppThemeCodebergDark" parent="Theme.Material3.Dark.NoActionBar">
<item name="android:statusBarColor">@color/codebergDarkThemeBackground</item>
<item name="android:typeface">monospace</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorSecondary">@color/codebergDarkThemeTextColor</item>
<item name="android:textColorPrimary">@color/codebergDarkThemeTextColor</item>
<item name="colorPrimary">@color/codebergDarkColorPrimary</item>
<item name="colorSecondary">@color/codebergDarkThemeTextColor</item>
<item name="colorOnSurfaceVariant">@color/codebergDarkThemeTextColor</item>
<item name="colorSecondaryContainer">@color/codebergDarkThemeColorSecondary</item>
<item name="materialCardBackgroundColor">@color/codebergDarkThemeCardBackground</item>
<item name="diffAddedColor">@color/diffAddedColor</item>
<item name="diffRemovedColor">@color/diffRemovedColor</item>
<item name="diffSelectedColor">@color/diffSelectedColor</item>
<item name="primaryTextColor">@color/codebergDarkThemeTextColor</item>
<item name="primaryBackgroundColor">@color/codebergDarkThemeBackground</item>
<item name="inputBackgroundColor">@color/codebergDarkInputBackground</item>
<item name="inputSelectedColor">@color/codebergDarkInputBackground</item>
<item name="inputTextColor">@color/codebergDarkThemeTextColor</item>
<item name="checkboxStyle">@style/AppThemeCheckBoxStyle</item>
<item name="selectedTextColor">@color/codebergDarkColorPrimary</item>
<item name="alertDialogTheme">@style/AppThemeCodebergDarkConfirmDialog</item>
<item name="popupMenuStyle">@style/AppThemeCodebergDarkPopupMenuStyle</item>
<item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item>
<item name="autoCompleteTextViewStyle">@style/AppThemeDarkSearchAutoCompleteTextView</item>
<item name="hintColor">@color/hintColor</item>
<item name="colorControlActivated">@color/codebergDarkColorPrimary</item>
<item name="dividerColor">@color/codebergDarkThemeDividerColor</item>
<item name="bottomSheetDialogTheme">@style/AppThemeDarkBottomSheetDialog</item>
<item name="searchViewStyle">@style/AppSearchViewStyle</item>
<item name="progressIndicatorColor">@color/codebergDarkColorPrimary</item>
<item name="fabColor">@color/codebergDarkThemeIconsColors</item>
<item name="iconsColor">@color/codebergDarkThemeIconsColors</item>
<item name="pagerTabIndicatorColor">@color/codebergDarkColorPrimary</item>
<item name="android:actionOverflowButtonStyle">@style/customOverflowButtonStyle</item>
<item name="actionOverflowMenuStyle">@style/customOverflowMenuStyle</item>
<item name="colorSurface">@color/codebergDarkInputBackground</item>
<item name="shapeAppearanceSmallComponent">@style/inputsMaterialComponentCorner</item>
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
<item name="materialSwitchStyle">@style/m3SwitchStyle</item>
<item name="isDark">1</item>
</style>
<!-- Codeberg dark theme -->
</resources>

View File

@ -65,4 +65,14 @@
<color name="pitchBlackThemeGeneralBackgroundColor">#151515</color>
<color name="pitchBlackThemeColorSecondary">#161918</color>
<color name="pitchBlackThemeCardBackground">#0C0C0C</color>
<color name="codebergDarkThemeBackground">#0c1a24</color>
<color name="codebergDarkThemeTextColor">#7f8699</color>
<color name="codebergDarkThemeDividerColor">#082437</color>
<color name="codebergDarkThemeGeneralBackgroundColor">#0c1a24</color>
<color name="codebergDarkThemeColorSecondary">#082437</color>
<color name="codebergDarkThemeCardBackground">#04121b</color>
<color name="codebergDarkThemeIconsColors">#9dacb6</color>
<color name="codebergDarkColorPrimary">#14507d</color>
<color name="codebergDarkInputBackground">#04121b</color>
</resources>

View File

@ -38,6 +38,7 @@
<item>Pitch Black</item>
<item>@string/followSystem</item>
<item>@string/followSystemBlack</item>
</string-array>
<string-array name="themesAndroid12">
@ -50,6 +51,7 @@
<item>@string/followSystem</item>
<item>@string/followSystemBlack</item>
<item>@string/dynamicColorsFollowSystem</item>
<item>@string/codebergDark</item>
</string-array>
<string-array name="appDefaultHomeScreen">
@ -67,7 +69,7 @@
<item>@string/pageTitleStarredRepos</item>
<item>@string/navOrg</item>
<item>@string/navRepos</item>
<item>@string/navProfile</item>
<item>@string/navAccount</item>
<item>@string/pageTitleExplore</item>
<item>@string/titleDrafts</item>
<item>@string/pageTitleNotifications</item>
@ -75,10 +77,11 @@
<item>@string/navMostVisited</item>
<item>@string/navNotes</item>
<item>@string/dashboard</item>
<item>@string/navWatchedRepositories</item>
</string-array>
<string-array name="linkHandlerDefaultScreen">
<item>@string/generalDeepLinkSelectedText</item>
<item>@string/none</item>
<item>@string/navRepos</item>
<item>@string/navOrg</item>
<item>@string/pageTitleNotifications</item>
@ -109,4 +112,10 @@
<item>6</item>
<item>8</item>
</string-array>
<string-array name="fragmentTabsAnimation">
<item>@string/fadeOut</item>
<item>@string/zoomOut</item>
<item>@string/none</item>
</string-array>
</resources>

View File

@ -35,6 +35,8 @@
<string name="navMyIssues">My Issues</string>
<string name="navMostVisited">Most Visited Repos</string>
<string name="navNotes">Notes</string>
<string name="navAccount">Account Settings</string>
<string name="navWatchedRepositories">Watched Repositories</string>
<!-- menu items -->
<!-- page titles -->
@ -246,7 +248,6 @@
<string name="generalHintText">Home screen, drafts, crash reports</string>
<string name="generalDeepLinkDefaultScreen">Default Link Handler</string>
<string name="generalDeepLinkDefaultScreenHintText">Choose what screen should be loaded if the app cannot handle external links. It will redirect you automatically.</string>
<string name="generalDeepLinkSelectedText">N/A</string>
<string name="linkSelectorDialogTitle">Select Default Link Handler Screen</string>
<string name="settingsBiometricHeader">Biometric Support</string>
<string name="settingsLabelsInListHeader">Labels With Text Support</string>
@ -255,6 +256,9 @@
<string name="ceIndentation">Indentation</string>
<string name="ceIndentationTabsWidth">Tabs Width</string>
<string name="system_font">System Default Font</string>
<string name="fragmentTabsAnimationHeader">Tabs Animation</string>
<string name="fadeOut">Fade Out</string>
<string name="zoomOut">Zoom Out</string>
<!-- settings -->
<string name="noMoreData">No more data available</string>
@ -342,16 +346,19 @@
<!-- profile section -->
<string name="profileTabFollowers">Followers</string>
<string name="profileTabFollowing">Following</string>
<string name="profileCreateNewEmailAddress">Add Email Address</string>
<string name="profileEmailTitle">Email Address</string>
<string name="usernameWithAt" translatable="false">\u0040%1$s</string>
<!-- profile section -->
<!-- account settings -->
<string name="accountEmails">Emails</string>
<string name="accountEmailTitle">Email Address</string>
<string name="emailAddedText">New email added successfully</string>
<string name="emailErrorEmpty">Email address is empty</string>
<string name="emailErrorInvalid">Email address is not valid</string>
<string name="emailErrorInUse">Email address is already in use</string>
<string name="emailTypeText">Primary</string>
<string name="profileTabEmails">Emails</string>
<string name="usernameWithAt" translatable="false">\u0040%1$s</string>
<!-- profile section -->
<string name="sshKeys">SSH Keys</string>
<!-- account settings -->
<!-- single issue section -->
<string name="singleIssueEditLabels">Add / Remove Labels</string>
@ -516,6 +523,7 @@
<string name="deleteGenericTitle">Delete %s</string>
<string name="reset">Reset</string>
<string name="beta">BETA</string>
<string name="none">None</string>
<!-- generic copy -->
<string name="exploreUsers">Explore users</string>
@ -778,6 +786,7 @@
<string name="followSystem">Follow system (Light/Dark)</string>
<string name="followSystemBlack">Follow system (Light/Pitch Black)</string>
<string name="dynamicColorsFollowSystem">Dynamic colors - Follow system (Light/Dark)</string>
<string name="codebergDark">Codeberg (Dark)</string>
<string name="repoForkOf">Fork of: %s</string>
<string name="adoptRepo">Adopt</string>
<string name="repoAdopted">Adopted repository %s</string>

View File

@ -182,6 +182,52 @@
</style>
<!-- Pitch black theme -->
<!-- Codeberg dark theme -->
<style name="AppThemeCodebergDark" parent="Theme.Material3.Dark.NoActionBar">
<item name="android:statusBarColor">@color/codebergDarkThemeBackground</item>
<item name="android:typeface">monospace</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorSecondary">@color/codebergDarkThemeTextColor</item>
<item name="android:textColorPrimary">@color/codebergDarkThemeTextColor</item>
<item name="colorPrimary">@color/codebergDarkColorPrimary</item>
<item name="colorSecondary">@color/codebergDarkThemeTextColor</item>
<item name="colorOnSurfaceVariant">@color/codebergDarkThemeTextColor</item>
<item name="colorSecondaryContainer">@color/codebergDarkThemeColorSecondary</item>
<item name="materialCardBackgroundColor">@color/codebergDarkThemeCardBackground</item>
<item name="diffAddedColor">@color/diffAddedColor</item>
<item name="diffRemovedColor">@color/diffRemovedColor</item>
<item name="diffSelectedColor">@color/diffSelectedColor</item>
<item name="primaryTextColor">@color/codebergDarkThemeTextColor</item>
<item name="primaryBackgroundColor">@color/codebergDarkThemeBackground</item>
<item name="inputBackgroundColor">@color/codebergDarkInputBackground</item>
<item name="inputSelectedColor">@color/codebergDarkInputBackground</item>
<item name="inputTextColor">@color/codebergDarkThemeTextColor</item>
<item name="checkboxStyle">@style/AppThemeCheckBoxStyle</item>
<item name="selectedTextColor">@color/codebergDarkColorPrimary</item>
<item name="alertDialogTheme">@style/AppThemeCodebergDarkConfirmDialog</item>
<item name="popupMenuStyle">@style/AppThemeCodebergDarkPopupMenuStyle</item>
<item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item>
<item name="autoCompleteTextViewStyle">@style/AppThemeDarkSearchAutoCompleteTextView</item>
<item name="hintColor">@color/hintColor</item>
<item name="colorControlActivated">@color/codebergDarkColorPrimary</item>
<item name="dividerColor">@color/codebergDarkThemeDividerColor</item>
<item name="bottomSheetDialogTheme">@style/AppThemeDarkBottomSheetDialog</item>
<item name="searchViewStyle">@style/AppSearchViewStyle</item>
<item name="progressIndicatorColor">@color/codebergDarkColorPrimary</item>
<item name="fabColor">@color/codebergDarkThemeIconsColors</item>
<item name="iconsColor">@color/codebergDarkThemeIconsColors</item>
<item name="pagerTabIndicatorColor">@color/codebergDarkColorPrimary</item>
<item name="android:actionOverflowButtonStyle">@style/customOverflowButtonStyle</item>
<item name="actionOverflowMenuStyle">@style/customOverflowMenuStyle</item>
<item name="colorSurface">@color/codebergDarkInputBackground</item>
<item name="shapeAppearanceSmallComponent">@style/inputsMaterialComponentCorner</item>
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
<item name="materialSwitchStyle">@style/m3SwitchStyle</item>
<item name="isDark">1</item>
</style>
<!-- Codeberg dark theme -->
<style name="m3SwitchStyle" parent="Widget.Material3.CompoundButton.MaterialSwitch">
<item name="thumbTint">@color/colorWhite</item>
</style>
@ -389,6 +435,28 @@
</style>
<!-- Pitch black theme styles -->
<!-- Codeberg dark theme styles -->
<style name="AppThemeCodebergDarkConfirmDialog" parent="Theme.Material3.Dark.Dialog.Alert">
<item name="android:background">@color/codebergDarkThemeGeneralBackgroundColor</item>
<item name="android:textColorPrimary">@color/codebergDarkThemeTextColor</item>
<item name="android:textColor">@color/codebergDarkThemeTextColor</item>
<item name="colorControlNormal">@color/codebergDarkThemeTextColor</item>
<item name="colorControlActivated">@color/codebergDarkThemeCardBackground</item>
<item name="buttonBarNegativeButtonStyle">@style/NegativeButtonStyle</item>
<item name="buttonBarPositiveButtonStyle">@style/PositiveButtonStyle</item>
<item name="buttonBarNeutralButtonStyle">@style/NeutralButtonStyle</item>
<item name="android:windowBackground">@drawable/shape_round_corners</item>
</style>
<style name="AppThemeCodebergDarkPopupMenuStyle" parent="Widget.Material3.PopupMenu">
<item name="android:popupBackground">@color/codebergDarkThemeGeneralBackgroundColor</item>
<item name="android:itemBackground">@color/codebergDarkThemeGeneralBackgroundColor</item>
<item name="android:textColor">@color/codebergDarkThemeTextColor</item>
<item name="android:layout_marginStart">@dimen/dimen4dp</item>
<item name="android:layout_marginEnd">@dimen/dimen4dp</item>
</style>
<!-- Codeberg dark theme styles -->
<style name="AppThemeSystem" parent="AppThemeLight"/>
<style name="AppThemeSystemPitchBlack" parent="AppThemeLight"/>