Various refactoring (#1115)

Various refactoring to simplify code. See separate commit for the refactorings.

~~Note to the font refactoring: it didn't work for me. The font was always `Manrope`. I don't know why - the issue is the FontsOverride.setDefaultFont` method, however, how this works hasn't changed. Maybe it was an issue with my device, could you please test it?~~

Also closes #1110 and closes #1073

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1115
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
This commit is contained in:
qwerty287 2022-04-25 07:42:52 +02:00 committed by M M Arif
parent e050a63b0d
commit 269f1fb32b
25 changed files with 146 additions and 548 deletions

View File

@ -114,10 +114,6 @@
android:name=".activities.CommitDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:theme="@android:style/Theme.NoTitleBar" />
<activity
android:name=".helpers.ssl.MemorizingActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:theme="@android:style/Theme.Material.Dialog" />
<activity
android:name=".activities.SettingsAppearanceActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation" />

View File

@ -116,17 +116,20 @@ public abstract class BaseActivity extends AppCompatActivity {
super.onAuthenticationError(errorCode, errString);
// Authentication error, close the app
if(errorCode == BiometricPrompt.ERROR_USER_CANCELED ||
errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON) {
finish();
}
finish();
}
// Authentication succeeded, continue to app
@Override public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) { super.onAuthenticationSucceeded(result); tinyDB.putBoolean("biometricLifeCycle", true); }
@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
tinyDB.putBoolean("biometricLifeCycle", true);
}
// Authentication failed, close the app
@Override public void onAuthenticationFailed() { super.onAuthenticationFailed(); }
@Override public void onAuthenticationFailed() {
super.onAuthenticationFailed();
}
});

View File

@ -184,24 +184,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
}, 500));
Typeface myTypeface;
switch(tinyDB.getInt("customFontId", -1)) {
case 1:
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(ctx).getAssets(), "fonts/manroperegular.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(ctx).getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(ctx).getAssets(), "fonts/roboto.ttf");
break;
}
Typeface myTypeface = AppUtil.getTypeface(this);
viewBinding.toolbarTitle.setTypeface(myTypeface);
viewBinding.toolbarTitle.setText(repoName);

View File

@ -117,21 +117,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
Toolbar toolbar = activityMainBinding.toolbar;
toolbarTitle = activityMainBinding.toolbarTitle;
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/manroperegular.ttf");
break;
}
myTypeface = AppUtil.getTypeface(this);
toolbarTitle.setTypeface(myTypeface);
setSupportActionBar(toolbar);

View File

@ -118,24 +118,7 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
tabLayout.removeTabAt(3);
}
Typeface myTypeface;
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
break;
}
Typeface myTypeface = AppUtil.getTypeface(this);
TextView toolbarTitle = findViewById(R.id.toolbar_title);
toolbarTitle.setTypeface(myTypeface);

View File

@ -25,6 +25,7 @@ import org.mian.gitnex.fragments.profile.FollowingFragment;
import org.mian.gitnex.fragments.profile.OrganizationsFragment;
import org.mian.gitnex.fragments.profile.RepositoriesFragment;
import org.mian.gitnex.fragments.profile.StarredRepositoriesFragment;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.structs.BottomSheetListener;
import java.util.Objects;
@ -47,7 +48,6 @@ public class ProfileActivity extends BaseActivity implements BottomSheetListener
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
Intent profileIntent = getIntent();
Typeface myTypeface;
Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = findViewById(R.id.toolbarTitle);
@ -68,18 +68,7 @@ public class ProfileActivity extends BaseActivity implements BottomSheetListener
viewPager.setOffscreenPageLimit(1);
TabLayout tabLayout = findViewById(R.id.tabs);
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
break;
}
Typeface myTypeface = AppUtil.getTypeface(this);
toolbarTitle.setTypeface(myTypeface);
toolbarTitle.setText(username);

View File

@ -142,22 +142,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
Objects.requireNonNull(getSupportActionBar()).setTitle(repository.getName());
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
break;
}
myTypeface = AppUtil.getTypeface(this);
toolbarTitle.setTypeface(myTypeface);
getRepoInfo(repository.getOwner(), repository.getName());

View File

@ -14,6 +14,8 @@ import com.google.android.material.switchmaterial.SwitchMaterial;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsAppearanceBinding;
import org.mian.gitnex.fragments.SettingsFragment;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.FontsOverride;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
@ -159,6 +161,8 @@ public class SettingsAppearanceActivity extends BaseActivity {
activitySettingsAppearanceBinding.customFontSelected.setText(customFontList[i]);
tinyDB.putString("customFontStr", customFontList[i]);
tinyDB.putInt("customFontId", i);
AppUtil.typeface = null; // reset typeface
FontsOverride.setDefaultFont(this);
SettingsFragment.refreshParent = true;
this.recreate();

View File

@ -1,124 +0,0 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.v2.models.Organization;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OrganizationDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import java.util.List;
/**
* @author M M Arif
*/
public class ExplorePublicOrganizationsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private List<Organization> organizationsList;
private Runnable loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public ExplorePublicOrganizationsAdapter(Context ctx, List<Organization> organizationsListMain) {
this.context = ctx;
this.organizationsList = organizationsListMain;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
return new ExplorePublicOrganizationsAdapter.OrganizationsHolder(inflater.inflate(R.layout.list_organizations, parent, false));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.run();
}
((ExplorePublicOrganizationsAdapter.OrganizationsHolder) holder).bindData(organizationsList.get(position));
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public int getItemCount() {
return organizationsList.size();
}
class OrganizationsHolder extends RecyclerView.ViewHolder {
private Organization organization;
private final ImageView image;
private final TextView orgName;
private final TextView orgDescription;
OrganizationsHolder(View itemView) {
super(itemView);
image = itemView.findViewById(R.id.imageAvatar);
orgName = itemView.findViewById(R.id.orgName);
orgDescription = itemView.findViewById(R.id.orgDescription);
itemView.setOnClickListener(v -> {
Context context = v.getContext();
Intent intent = new Intent(context, OrganizationDetailActivity.class);
intent.putExtra("orgName", organization.getUsername());
context.startActivity(intent);
});
}
@SuppressLint("SetTextI18n")
void bindData(Organization organization) {
this.organization = organization;
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
orgName.setText(organization.getUsername());
PicassoService.getInstance(context).get()
.load(organization.getAvatarUrl())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(imgRadius, 0))
.resize(120, 120)
.centerCrop()
.into(image);
if(!organization.getDescription().equals("")) {
orgDescription.setVisibility(View.VISIBLE);
orgDescription.setText(organization.getDescription());
}
else {
orgDescription.setVisibility(View.GONE);
}
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public void setLoadMoreListener(Runnable loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<Organization> list) {
organizationsList = list;
notifyDataChanged();
}
}

View File

@ -33,7 +33,7 @@ public class OrganizationsListAdapter extends RecyclerView.Adapter<RecyclerView.
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public OrganizationsListAdapter(List<Organization> orgListMain, Context ctx) {
public OrganizationsListAdapter(Context ctx, List<Organization> orgListMain) {
this.context = ctx;
this.orgList = orgListMain;
orgListFull = new ArrayList<>(orgList);
@ -123,9 +123,10 @@ public class OrganizationsListAdapter extends RecyclerView.Adapter<RecyclerView.
loadMoreListener.onLoadFinished();
}
public interface OnLoadMoreListener {
void onLoadMore();
void onLoadFinished();
public abstract static class OnLoadMoreListener {
protected abstract void onLoadMore();
public void onLoadFinished() {}
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {

View File

@ -1,121 +0,0 @@
package org.mian.gitnex.adapters.profile;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.v2.models.Organization;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OrganizationDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import java.util.List;
/**
* @author M M Arif
*/
public class OrganizationsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private List<Organization> organizationsList;
private Runnable loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public OrganizationsAdapter(Context ctx, List<Organization> organizationsListMain) {
this.context = ctx;
this.organizationsList = organizationsListMain;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
return new OrganizationsHolder(inflater.inflate(R.layout.list_organizations, parent, false));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.run();
}
((OrganizationsHolder) holder).bindData(organizationsList.get(position));
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public int getItemCount() {
return organizationsList.size();
}
class OrganizationsHolder extends RecyclerView.ViewHolder {
private Organization userOrganizations;
private final ImageView image;
private final TextView orgName;
private final TextView orgDescription;
OrganizationsHolder(View itemView) {
super(itemView);
orgName = itemView.findViewById(R.id.orgName);
orgDescription = itemView.findViewById(R.id.orgDescription);
image = itemView.findViewById(R.id.imageAvatar);
itemView.setOnClickListener(v -> {
Context context = v.getContext();
Intent intent = new Intent(context, OrganizationDetailActivity.class);
intent.putExtra("orgName", userOrganizations.getUsername());
context.startActivity(intent);
});
}
@SuppressLint("SetTextI18n")
void bindData(Organization userOrganizations) {
this.userOrganizations = userOrganizations;
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
orgName.setText(userOrganizations.getUsername());
PicassoService.getInstance(context).get().load(userOrganizations.getAvatarUrl()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(image);
if (!userOrganizations.getDescription().equals("")) {
orgDescription.setText(userOrganizations.getDescription());
}
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public void setLoadMoreListener(Runnable loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<Organization> list) {
organizationsList = list;
notifyDataChanged();
}
}

View File

@ -1,16 +1,14 @@
package org.mian.gitnex.core;
import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import org.acra.ACRA;
import org.acra.BuildConfig;
import org.acra.ReportField;
import org.acra.annotation.AcraCore;
import org.acra.annotation.AcraNotification;
import org.acra.config.CoreConfigurationBuilder;
import org.acra.config.LimiterConfigurationBuilder;
import org.acra.config.MailSenderConfigurationBuilder;
import org.acra.config.NotificationConfigurationBuilder;
import org.acra.data.StringFormat;
import org.mian.gitnex.R;
import org.mian.gitnex.database.models.UserAccount;
@ -19,20 +17,12 @@ import org.mian.gitnex.helpers.FontsOverride;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.contexts.AccountContext;
import org.mian.gitnex.notifications.Notifications;
import java.nio.charset.StandardCharsets;
/**
* @author opyale
*/
@SuppressLint("NonConstantResourceId")
@AcraNotification(resIcon = R.drawable.gitnex_transparent,
resTitle = R.string.crashTitle,
resChannelName = R.string.setCrashReports,
resText = R.string.crashMessage)
@AcraCore(reportContent = {
ReportField.ANDROID_VERSION, ReportField.PHONE_MODEL,
ReportField.STACK_TRACE, ReportField.AVAILABLE_MEM_SIZE, ReportField.BRAND })
public class MainApplication extends Application {
private TinyDB tinyDB;
@ -50,29 +40,7 @@ public class MainApplication extends Application {
tinyDB.putBoolean("biometricLifeCycle", false);
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
FontsOverride.setDefaultFont(this, "DEFAULT", "fonts/roboto.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "fonts/roboto.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "fonts/roboto.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "fonts/roboto.ttf");
break;
case 2:
FontsOverride.setDefaultFont(this, "DEFAULT", "fonts/sourcecodeproregular.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "fonts/sourcecodeproregular.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "fonts/sourcecodeproregular.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "fonts/sourcecodeproregular.ttf");
break;
default:
FontsOverride.setDefaultFont(this, "DEFAULT", "fonts/manroperegular.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "fonts/manroperegular.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "fonts/manroperegular.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "fonts/manroperegular.ttf");
}
FontsOverride.setDefaultFont(getBaseContext());
Notifications.createChannels(appCtx);
}
@ -88,7 +56,10 @@ public class MainApplication extends Application {
CoreConfigurationBuilder ACRABuilder = new CoreConfigurationBuilder(this);
ACRABuilder.withBuildConfigClass(BuildConfig.class).setReportFormat(StringFormat.KEY_VALUE_LIST);
ACRABuilder.withBuildConfigClass(BuildConfig.class).withReportContent(ReportField.ANDROID_VERSION, ReportField.PHONE_MODEL,
ReportField.STACK_TRACE, ReportField.AVAILABLE_MEM_SIZE, ReportField.BRAND).setReportFormat(StringFormat.KEY_VALUE_LIST);
ACRABuilder.getPluginConfigurationBuilder(NotificationConfigurationBuilder.class).withResTitle(R.string.crashTitle)
.withResIcon(R.drawable.gitnex_transparent).withResChannelName(R.string.setCrashReports).withResText(R.string.crashMessage);
ACRABuilder.getPluginConfigurationBuilder(MailSenderConfigurationBuilder.class).withMailTo(getResources().getString(R.string.appEmail))
.withSubject(getResources().getString(R.string.crashReportEmailSubject, AppUtil
.getAppBuildNo(context)))

View File

@ -16,6 +16,7 @@ import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.TinyDB;
/**
@ -41,23 +42,7 @@ public class ExploreFragment extends Fragment {
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
Typeface myTypeface;
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(ctx != null ? ctx.getAssets() : null, "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(ctx != null ? ctx.getAssets() : null, "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(ctx != null ? ctx.getAssets() : null, "fonts/manroperegular.ttf");
break;
}
Typeface myTypeface = AppUtil.getTypeface(requireContext());
viewPager.setAdapter(new ViewPagerAdapter(this));
String[] tabTitles = {getResources().getString(R.string.navRepos), getResources().getString(R.string.pageTitleIssues), getResources().getString(R.string.navOrg), getResources().getString(R.string.pageTitleUsers)};

View File

@ -15,7 +15,7 @@ import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import org.gitnex.tea4j.v2.models.Organization;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.ExplorePublicOrganizationsAdapter;
import org.mian.gitnex.adapters.OrganizationsListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentOrganizationsBinding;
import org.mian.gitnex.helpers.Constants;
@ -34,7 +34,7 @@ public class ExplorePublicOrganizationsFragment extends Fragment {
private FragmentOrganizationsBinding fragmentPublicOrgBinding;
private List<Organization> organizationsList;
private ExplorePublicOrganizationsAdapter adapter;
private OrganizationsListAdapter adapter;
private Context context;
private int pageSize;
private final String TAG = Constants.publicOrganizations;
@ -58,13 +58,18 @@ public class ExplorePublicOrganizationsFragment extends Fragment {
adapter.notifyDataChanged();
}, 200));
adapter = new ExplorePublicOrganizationsAdapter(getContext(), organizationsList);
adapter.setLoadMoreListener(() -> fragmentPublicOrgBinding.recyclerView.post(() -> {
if(organizationsList.size() == resultLimit || pageSize == resultLimit) {
int page = (organizationsList.size() + resultLimit) / resultLimit;
loadMore(page, resultLimit);
adapter = new OrganizationsListAdapter(requireContext(), organizationsList);
adapter.setLoadMoreListener(new OrganizationsListAdapter.OnLoadMoreListener() {
@Override
public void onLoadMore() {
fragmentPublicOrgBinding.recyclerView.post(() -> {
if(organizationsList.size() == resultLimit || pageSize == resultLimit) {
int page = (organizationsList.size() + resultLimit) / resultLimit;
loadMore(page, resultLimit);
}
});
}
}));
});
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(fragmentPublicOrgBinding.recyclerView.getContext(), DividerItemDecoration.VERTICAL);
fragmentPublicOrgBinding.recyclerView.setHasFixedSize(true);

View File

@ -187,24 +187,7 @@ public class MyProfileFragment extends Fragment {
ViewPager mViewPager = v.findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
Typeface myTypeface;
switch(tinyDb.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(requireContext().getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(requireContext().getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(requireContext().getAssets(), "fonts/manroperegular.ttf");
break;
}
Typeface myTypeface = AppUtil.getTypeface(requireContext());
TabLayout tabLayout = v.findViewById(R.id.tabs);
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);

View File

@ -78,7 +78,7 @@ public class OrganizationsFragment extends Fragment {
organizationsViewModel.getUserOrg(page, resultLimit, getContext()).observe(getViewLifecycleOwner(), orgListMain -> {
adapter = new OrganizationsListAdapter(orgListMain, getContext());
adapter = new OrganizationsListAdapter(requireContext(), orgListMain);
adapter.setLoadMoreListener(new OrganizationsListAdapter.OnLoadMoreListener() {
@Override

View File

@ -18,7 +18,7 @@ import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import org.gitnex.tea4j.v2.models.Organization;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.profile.OrganizationsAdapter;
import org.mian.gitnex.adapters.OrganizationsListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentOrganizationsBinding;
import org.mian.gitnex.helpers.AlertDialogs;
@ -41,7 +41,7 @@ public class OrganizationsFragment extends Fragment {
private FragmentOrganizationsBinding fragmentOrganizationsBinding;
private List<Organization> organizationsList;
private OrganizationsAdapter adapter;
private OrganizationsListAdapter adapter;
private int pageSize;
private int resultLimit;
@ -86,13 +86,19 @@ public class OrganizationsFragment extends Fragment {
adapter.notifyDataChanged();
}, 200));
adapter = new OrganizationsAdapter(context, organizationsList);
adapter.setLoadMoreListener(() -> fragmentOrganizationsBinding.recyclerView.post(() -> {
if(organizationsList.size() == resultLimit || pageSize == resultLimit) {
int page = (organizationsList.size() + resultLimit) / resultLimit;
loadMore(username, page, resultLimit);
adapter = new OrganizationsListAdapter(context, organizationsList);
adapter.setLoadMoreListener(new OrganizationsListAdapter.OnLoadMoreListener() {
@Override
protected void onLoadMore() {
fragmentOrganizationsBinding.recyclerView.post(() -> {
if(organizationsList.size() == resultLimit || pageSize == resultLimit) {
int page = (organizationsList.size() + resultLimit) / resultLimit;
loadMore(username, page, resultLimit);
}
});
}
}));
});
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
fragmentOrganizationsBinding.recyclerView.setHasFixedSize(true);

View File

@ -10,6 +10,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Build;
import android.util.Base64;
@ -437,4 +438,23 @@ public class AppUtil {
return Uri.parse(scheme+raw);
}
public static Typeface typeface;
public static Typeface getTypeface(Context context) {
if(typeface == null) {
switch(TinyDB.getInstance(context).getInt("customFontId", -1)) {
case 0:
typeface = Typeface.createFromAsset(context.getAssets(), "fonts/roboto.ttf");
break;
case 2:
typeface = Typeface.createFromAsset(context.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
typeface = Typeface.createFromAsset(context.getAssets(), "fonts/manroperegular.ttf");
break;
}
}
return typeface;
}
}

View File

@ -7,18 +7,22 @@ import java.lang.reflect.Field;
import java.util.Objects;
/**
* Author M M Arif
* @author M M Arif
*/
public class FontsOverride {
public static void setDefaultFont(Context context,
String staticTypefaceFieldName, String fontAssetName) {
final Typeface regular = Typeface.createFromAsset(context.getAssets(),
fontAssetName);
replaceFont(staticTypefaceFieldName, regular);
public static void setDefaultFont(Context context) {
final Typeface regular = AppUtil.getTypeface(context);
for(String field : new String[]{
"DEFAULT",
"MONOSPACE",
"SERIF",
"SANS_SERIF"
}) {
replaceFont(field, regular);
}
}
private static void replaceFont(String staticTypefaceFieldName,
@ -34,7 +38,7 @@ public class FontsOverride {
}
catch (NoSuchFieldException | IllegalAccessException e) {
Log.e("error", Objects.requireNonNull(e.getMessage()));
Log.e("replaceFont", Objects.requireNonNull(e.getMessage()));
}

View File

@ -187,26 +187,11 @@ public class Markdown {
private Typeface tf;
private void setupTf(Context context) {
switch(TinyDB.getInstance(context).getInt("customFontId", -1)) {
case 0:
tf = Typeface.createFromAsset(context.getAssets(), "fonts/roboto.ttf");
break;
case 2:
tf = Typeface.createFromAsset(context.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
tf = Typeface.createFromAsset(context.getAssets(), "fonts/manroperegular.ttf");
break;
}
}
@Override
public void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown) {
if(tf == null) {
setupTf(textView.getContext());
tf = AppUtil.getTypeface(textView.getContext());
}
textView.setTypeface(tf);
super.beforeSetText(textView, markdown);
@ -223,7 +208,7 @@ public class Markdown {
builder.linkColor(ResourcesCompat.getColor(context.getResources(), R.color.lightBlue, null));
if(tf == null) {
setupTf(context);
tf = AppUtil.getTypeface(context);
}
builder.headingTypeface(tf);
}
@ -319,26 +304,11 @@ public class Markdown {
private final Context context = RecyclerViewRenderer.this.context;
private Typeface tf;
private void setupTf(Context context) {
switch(TinyDB.getInstance(context).getInt("customFontId", -1)) {
case 0:
tf = Typeface.createFromAsset(context.getAssets(), "fonts/roboto.ttf");
break;
case 2:
tf = Typeface.createFromAsset(context.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
tf = Typeface.createFromAsset(context.getAssets(), "fonts/manroperegular.ttf");
break;
}
}
@Override
public void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown) {
if(tf == null) {
setupTf(textView.getContext());
tf = AppUtil.getTypeface(context);
}
textView.setTypeface(tf);
super.beforeSetText(textView, markdown);
@ -362,7 +332,7 @@ public class Markdown {
builder.linkColor(ResourcesCompat.getColor(context.getResources(), R.color.lightBlue, null));
if(tf == null) {
setupTf(context);
tf = AppUtil.getTypeface(context);
}
builder.headingTypeface(Typeface.create(tf, Typeface.BOLD));
}

View File

@ -3,6 +3,7 @@ package org.mian.gitnex.helpers;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -16,6 +17,7 @@ public class Version {
private String raw;
// the version numbers in its order (dot separated)
private List<Integer> values;
private boolean dev;
public Version(String value) {
@ -35,8 +37,8 @@ public class Version {
if(value == null) {
return false;
}
final Pattern pattern_valid = Pattern.compile("^[v,V]?(\\d+)+(\\.(\\d+))*([_,\\-,+][\\w,\\d,_,\\-,+]*)?$");
return pattern_valid.matcher(value).find();
final Pattern patternValid = Pattern.compile("^[v,V]?(\\d+)+(\\.(\\d+))*([_,\\-,+][\\w,\\d,_,\\-,+]*)?$");
return value.equals("main") || patternValid.matcher(value).find();
}
/**
@ -47,19 +49,25 @@ public class Version {
*/
private void init() {
final Pattern pattern_number_dot_number = Pattern.compile("^\\d+(\\.(\\d)+)*");
final Pattern patternNumberDotNumber = Pattern.compile("^\\d+(\\.(\\d)+)*");
if(!valid(raw)) {
throw new IllegalArgumentException("Invalid version format: " + raw);
if(!valid(raw) || raw.equals("main")) {
dev = true;
values = new ArrayList<>();
return;
}
if(raw.charAt(0) == 'v' || raw.charAt(0) == 'V') {
raw = raw.substring(1);
}
values = new ArrayList<Integer>();
Matcher match = pattern_number_dot_number.matcher(raw);
match.find();
values = new ArrayList<>();
Matcher match = patternNumberDotNumber.matcher(raw);
if(!match.find()) {
dev = true;
values = new ArrayList<>();
return;
}
for(String i : match.group().split("\\.")) {
values.add(Integer.parseInt(i));
}
@ -86,9 +94,13 @@ public class Version {
*/
public boolean equal(@NonNull Version v) {
if(dev || v.dev) { // equal if raw is equal
return Objects.equals(raw, v.raw);
}
int rounds = Math.min(this.values.size(), v.values.size());
for(int i = 0; i < rounds; i++) {
if(this.values.get(i) != v.values.get(i)) {
if(!Objects.equals(this.values.get(i), v.values.get(i))) {
return false;
}
}
@ -142,6 +154,12 @@ public class Version {
*/
public boolean higher(@NonNull Version v) {
if(dev) {
return !v.dev;
} else if(v.dev) {
return false;
}
int rounds = Math.min(this.values.size(), v.values.size());
for(int i = 0; i < rounds; i++) {
if(i + 1 == rounds) {
@ -207,6 +225,10 @@ public class Version {
*/
public boolean higherOrEqual(@NonNull Version v) {
if(dev || v.dev) { // if one is a dev version, only true if both are dev
return v.dev && dev;
}
int rounds = Math.min(this.values.size(), v.values.size());
for(int i = 0; i < rounds; i++) {
if(this.values.get(i) > v.values.get(i)) {

View File

@ -1,44 +0,0 @@
package org.mian.gitnex.helpers.ssl;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import org.mian.gitnex.R;
/**
* Author Georg Lukas, modified by opyale
*/
public class MemorizingActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
int decisionId = intent.getIntExtra("DECISION_INTENT_ID", MTMDecision.DECISION_INVALID);
int titleId = intent.getIntExtra("DECISION_TITLE_ID", R.string.mtmAcceptCert);
String cert = intent.getStringExtra("DECISION_INTENT_CERT");
AlertDialog.Builder builder = new AlertDialog.Builder(MemorizingActivity.this);
builder.setTitle(titleId);
builder.setMessage(cert);
builder.setPositiveButton(R.string.mtmDecisionAlways, (dialog, which) -> onSendResult(decisionId, MTMDecision.DECISION_ALWAYS));
builder.setNeutralButton(R.string.mtmDecisionAbort, (dialog, which) -> onSendResult(decisionId, MTMDecision.DECISION_ABORT));
builder.setOnCancelListener(dialog -> onSendResult(decisionId, MTMDecision.DECISION_ABORT));
builder.create().show();
}
private void onSendResult(int decisionId, int decision) {
MemorizingTrustManager.interactResult(decisionId, decision);
finish();
}
}

View File

@ -1,16 +1,17 @@
package org.mian.gitnex.helpers.ssl;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.util.Base64;
import android.util.SparseArray;
import androidx.core.app.NotificationCompat;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.BaseActivity;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -39,7 +40,7 @@ import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
/**
* Author Georg Lukas, modified by opyale
* @author Georg Lukas, modified by opyale
*/
public class MemorizingTrustManager implements X509TrustManager {
@ -50,10 +51,9 @@ public class MemorizingTrustManager implements X509TrustManager {
private Context context;
private NotificationManager notificationManager;
private static int decisionId = 0;
private static final SparseArray<MTMDecision> openDecisions = new SparseArray<>();
private int decisionId = 0;
private final SparseArray<MTMDecision> openDecisions = new SparseArray<>();
private Handler masterHandler;
private SharedPreferences keyStoreStorage;
private KeyStore appKeyStore;
private final X509TrustManager defaultTrustManager;
@ -103,7 +103,6 @@ public class MemorizingTrustManager implements X509TrustManager {
private void init(Context m) {
context = m;
masterHandler = new Handler(m.getMainLooper());
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
keyStoreStorage = m.getSharedPreferences(KEYSTORE_NAME, Context.MODE_PRIVATE);
@ -387,7 +386,7 @@ public class MemorizingTrustManager implements X509TrustManager {
return defaultTrustManager.getAcceptedIssuers();
}
private static int createDecisionId(MTMDecision d) {
private int createDecisionId(MTMDecision d) {
int myId;
synchronized(openDecisions) {
@ -562,24 +561,16 @@ public class MemorizingTrustManager implements X509TrustManager {
MTMDecision choice = new MTMDecision();
final int myId = createDecisionId(choice);
masterHandler.post(new Runnable() {
((BaseActivity) context).runOnUiThread(() -> {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(titleId);
builder.setMessage(message);
public void run() {
builder.setPositiveButton(R.string.mtmDecisionAlways, (dialog, which) -> interactResult(myId, MTMDecision.DECISION_ALWAYS));
builder.setNeutralButton(R.string.mtmDecisionAbort, (dialog, which) -> interactResult(myId, MTMDecision.DECISION_ABORT));
builder.setOnCancelListener(dialog -> interactResult(myId, MTMDecision.DECISION_ABORT));
Intent intent = new Intent(context, MemorizingActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.putExtra("DECISION_INTENT_ID", myId);
intent.putExtra("DECISION_INTENT_CERT", message);
intent.putExtra("DECISION_TITLE_ID", titleId);
try {
context.startActivity(intent);
}
catch(Exception e) {
startActivityNotification(intent, myId, message);
}
}
builder.create().show();
});
try {
@ -613,7 +604,7 @@ public class MemorizingTrustManager implements X509TrustManager {
return false;
}
static void interactResult(int decisionId, int choice) {
private void interactResult(int decisionId, int choice) {
MTMDecision d;

View File

@ -1,4 +1,4 @@
package org.mian.gitnex.helpers.views;
package org.mian.gitnex.views;
import android.app.Activity;
import android.content.Context;

View File

@ -96,7 +96,7 @@
</LinearLayout>
<org.mian.gitnex.helpers.views.SyntaxHighlightedArea
<org.mian.gitnex.views.SyntaxHighlightedArea
android:id="@+id/contents"
android:layout_width="match_parent"
android:layout_height="wrap_content"