Most visited repositories (#1178)
This is an app only feature and could be useful to some users including me. Co-authored-by: M M Arif <mmarif@swatian.com> Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1178
This commit is contained in:
parent
23df83110d
commit
387089fb26
|
@ -108,7 +108,7 @@ dependencies {
|
||||||
implementation "androidx.work:work-runtime:$work_version"
|
implementation "androidx.work:work-runtime:$work_version"
|
||||||
implementation "io.mikael:urlbuilder:2.0.9"
|
implementation "io.mikael:urlbuilder:2.0.9"
|
||||||
implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2"
|
implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2"
|
||||||
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.2.0"
|
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
|
||||||
implementation 'androidx.biometric:biometric:1.1.0'
|
implementation 'androidx.biometric:biometric:1.1.0'
|
||||||
implementation 'com.github.chrisvest:stormpot:2.4.2'
|
implementation 'com.github.chrisvest:stormpot:2.4.2'
|
||||||
implementation 'androidx.browser:browser:1.4.0'
|
implementation 'androidx.browser:browser:1.4.0'
|
||||||
|
|
|
@ -39,6 +39,7 @@ import org.mian.gitnex.fragments.BottomSheetDraftsFragment;
|
||||||
import org.mian.gitnex.fragments.BottomSheetMyIssuesFilterFragment;
|
import org.mian.gitnex.fragments.BottomSheetMyIssuesFilterFragment;
|
||||||
import org.mian.gitnex.fragments.DraftsFragment;
|
import org.mian.gitnex.fragments.DraftsFragment;
|
||||||
import org.mian.gitnex.fragments.ExploreFragment;
|
import org.mian.gitnex.fragments.ExploreFragment;
|
||||||
|
import org.mian.gitnex.fragments.MostVisitedReposFragment;
|
||||||
import org.mian.gitnex.fragments.MyIssuesFragment;
|
import org.mian.gitnex.fragments.MyIssuesFragment;
|
||||||
import org.mian.gitnex.fragments.MyProfileFragment;
|
import org.mian.gitnex.fragments.MyProfileFragment;
|
||||||
import org.mian.gitnex.fragments.MyRepositoriesFragment;
|
import org.mian.gitnex.fragments.MyRepositoriesFragment;
|
||||||
|
@ -145,6 +146,9 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
|
||||||
else if(fragmentById instanceof MyProfileFragment) {
|
else if(fragmentById instanceof MyProfileFragment) {
|
||||||
toolbarTitle.setText(getResources().getString(R.string.navProfile));
|
toolbarTitle.setText(getResources().getString(R.string.navProfile));
|
||||||
}
|
}
|
||||||
|
else if(fragmentById instanceof MostVisitedReposFragment) {
|
||||||
|
toolbarTitle.setText(getResources().getString(R.string.navMostVisited));
|
||||||
|
}
|
||||||
else if(fragmentById instanceof DraftsFragment) {
|
else if(fragmentById instanceof DraftsFragment) {
|
||||||
toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
|
toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
|
||||||
}
|
}
|
||||||
|
@ -592,6 +596,11 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
|
||||||
toolbarTitle.setText(getResources().getString(R.string.navMyIssues));
|
toolbarTitle.setText(getResources().getString(R.string.navMyIssues));
|
||||||
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyIssuesFragment()).commit();
|
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyIssuesFragment()).commit();
|
||||||
}
|
}
|
||||||
|
else if(id == R.id.nav_most_visited) {
|
||||||
|
|
||||||
|
toolbarTitle.setText(getResources().getString(R.string.navMostVisited));
|
||||||
|
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MostVisitedReposFragment()).commit();
|
||||||
|
}
|
||||||
|
|
||||||
drawer.closeDrawer(GravityCompat.START);
|
drawer.closeDrawer(GravityCompat.START);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -62,7 +62,6 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
|
||||||
DraftsApi draftsApi = BaseApi.getInstance(context, DraftsApi.class);
|
DraftsApi draftsApi = BaseApi.getInstance(context, DraftsApi.class);
|
||||||
assert draftsApi != null;
|
assert draftsApi != null;
|
||||||
draftsApi.deleteSingleDraft(getDraftId);
|
draftsApi.deleteSingleDraft(getDraftId);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
itemView.setOnClickListener(itemEdit -> {
|
itemView.setOnClickListener(itemEdit -> {
|
||||||
|
@ -98,9 +97,7 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
|
||||||
});
|
});
|
||||||
bottomSheetReplyFragment.show(fragmentManager, "replyBottomSheet");
|
bottomSheetReplyFragment.show(fragmentManager, "replyBottomSheet");
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DraftsAdapter(Context ctx, FragmentManager fragmentManager, List<DraftWithRepository> draftsListMain) {
|
public DraftsAdapter(Context ctx, FragmentManager fragmentManager, List<DraftWithRepository> draftsListMain) {
|
||||||
|
@ -152,9 +149,14 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
|
||||||
return draftsList.size();
|
return draftsList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
public void notifyDataChanged() {
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
public void updateList(List<DraftWithRepository> list) {
|
public void updateList(List<DraftWithRepository> list) {
|
||||||
|
|
||||||
draftsList = list;
|
draftsList = list;
|
||||||
notifyDataSetChanged();
|
notifyDataChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,14 +117,21 @@ public class ExploreIssuesAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
|
|
||||||
RepositoryContext repo = new RepositoryContext(repoOwner, repoName, context);
|
RepositoryContext repo = new RepositoryContext(repoOwner, repoName, context);
|
||||||
|
|
||||||
repo.saveToDB(context);
|
|
||||||
|
|
||||||
Intent intentIssueDetail = new IssueContext(issue, repo).getIntent(context, IssueDetailActivity.class);
|
Intent intentIssueDetail = new IssueContext(issue, repo).getIntent(context, IssueDetailActivity.class);
|
||||||
intentIssueDetail.putExtra("openedFromLink", "true");
|
intentIssueDetail.putExtra("openedFromLink", "true");
|
||||||
|
|
||||||
itemView.setOnClickListener(v -> context.startActivity(intentIssueDetail));
|
itemView.setOnClickListener(v -> {
|
||||||
frameLabels.setOnClickListener(v -> context.startActivity(intentIssueDetail));
|
repo.saveToDB(context);
|
||||||
frameLabelsDots.setOnClickListener(v -> context.startActivity(intentIssueDetail));
|
context.startActivity(intentIssueDetail);
|
||||||
|
});
|
||||||
|
frameLabels.setOnClickListener(v -> {
|
||||||
|
repo.saveToDB(context);
|
||||||
|
context.startActivity(intentIssueDetail);
|
||||||
|
});
|
||||||
|
frameLabelsDots.setOnClickListener(v -> {
|
||||||
|
repo.saveToDB(context);
|
||||||
|
context.startActivity(intentIssueDetail);
|
||||||
|
});
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
issueAssigneeAvatar.setOnClickListener(v -> {
|
issueAssigneeAvatar.setOnClickListener(v -> {
|
||||||
|
|
|
@ -116,7 +116,7 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<RecyclerVie
|
||||||
|
|
||||||
orgName.setText(userRepositories.getFullName().split("/")[0]);
|
orgName.setText(userRepositories.getFullName().split("/")[0]);
|
||||||
repoName.setText(userRepositories.getFullName().split("/")[1]);
|
repoName.setText(userRepositories.getFullName().split("/")[1]);
|
||||||
repoStars.setText(String.valueOf(userRepositories.getStarsCount()));
|
repoStars.setText(AppUtil.numberFormatter(userRepositories.getStarsCount()));
|
||||||
|
|
||||||
ColorGenerator generator = ColorGenerator.Companion.getMATERIAL();
|
ColorGenerator generator = ColorGenerator.Companion.getMATERIAL();
|
||||||
int color = generator.getColor(userRepositories.getName());
|
int color = generator.getColor(userRepositories.getName());
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
package org.mian.gitnex.adapters;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import com.amulyakhare.textdrawable.TextDrawable;
|
||||||
|
import com.amulyakhare.textdrawable.util.ColorGenerator;
|
||||||
|
import org.mian.gitnex.R;
|
||||||
|
import org.mian.gitnex.activities.RepoDetailActivity;
|
||||||
|
import org.mian.gitnex.database.models.Repository;
|
||||||
|
import org.mian.gitnex.helpers.AppUtil;
|
||||||
|
import org.mian.gitnex.helpers.contexts.RepositoryContext;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author M M Arif
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MostVisitedReposAdapter extends RecyclerView.Adapter<MostVisitedReposAdapter.MostVisitedViewHolder> {
|
||||||
|
|
||||||
|
private List<Repository> mostVisitedReposList;
|
||||||
|
|
||||||
|
static class MostVisitedViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
private Repository repository;
|
||||||
|
|
||||||
|
private final ImageView image;
|
||||||
|
private final TextView repoName;
|
||||||
|
private final TextView orgName;
|
||||||
|
private final TextView mostVisited;
|
||||||
|
|
||||||
|
private MostVisitedViewHolder(View itemView) {
|
||||||
|
|
||||||
|
super(itemView);
|
||||||
|
|
||||||
|
image = itemView.findViewById(R.id.image);
|
||||||
|
repoName = itemView.findViewById(R.id.repo_name);
|
||||||
|
orgName = itemView.findViewById(R.id.org_name);
|
||||||
|
mostVisited = itemView.findViewById(R.id.most_visited);
|
||||||
|
|
||||||
|
itemView.setOnClickListener(v -> {
|
||||||
|
|
||||||
|
Context context = v.getContext();
|
||||||
|
RepositoryContext repositoryContext = new RepositoryContext(repository.getRepositoryOwner(), repository.getRepositoryName(), context);
|
||||||
|
Intent intent = repositoryContext.getIntent(context, RepoDetailActivity.class);
|
||||||
|
context.startActivity(intent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MostVisitedReposAdapter(List<Repository> reposListMain) {
|
||||||
|
this.mostVisitedReposList = reposListMain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public MostVisitedViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_most_visited_repos, parent, false);
|
||||||
|
return new MostVisitedViewHolder(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull MostVisitedViewHolder holder, int position) {
|
||||||
|
|
||||||
|
Repository currentItem = mostVisitedReposList.get(position);
|
||||||
|
holder.repository = currentItem;
|
||||||
|
|
||||||
|
ColorGenerator generator = ColorGenerator.Companion.getMATERIAL();
|
||||||
|
int color = generator.getColor(currentItem.getRepositoryOwner());
|
||||||
|
String firstCharacter = String.valueOf(currentItem.getRepositoryOwner().charAt(0));
|
||||||
|
TextDrawable drawable = TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT).fontSize(18).toUpperCase().width(28).height(28).endConfig().buildRoundRect(firstCharacter, color, 14);
|
||||||
|
|
||||||
|
holder.image.setImageDrawable(drawable);
|
||||||
|
holder.orgName.setText(currentItem.getRepositoryOwner());
|
||||||
|
holder.repoName.setText(currentItem.getRepositoryName());
|
||||||
|
holder.mostVisited.setText(AppUtil.numberFormatter(currentItem.getMostVisited()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mostVisitedReposList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
public void notifyDataChanged() {
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateList(List<Repository> list) {
|
||||||
|
|
||||||
|
mostVisitedReposList = list;
|
||||||
|
notifyDataChanged();
|
||||||
|
}
|
||||||
|
}
|
|
@ -109,7 +109,7 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
||||||
this.userRepositories = forksModel;
|
this.userRepositories = forksModel;
|
||||||
orgName.setText(forksModel.getFullName().split("/")[0]);
|
orgName.setText(forksModel.getFullName().split("/")[0]);
|
||||||
repoName.setText(forksModel.getFullName().split("/")[1]);
|
repoName.setText(forksModel.getFullName().split("/")[1]);
|
||||||
repoStars.setText(String.valueOf(forksModel.getStarsCount()));
|
repoStars.setText(AppUtil.numberFormatter(forksModel.getStarsCount()));
|
||||||
|
|
||||||
ColorGenerator generator = ColorGenerator.Companion.getMATERIAL();
|
ColorGenerator generator = ColorGenerator.Companion.getMATERIAL();
|
||||||
int color = generator.getColor(forksModel.getName());
|
int color = generator.getColor(forksModel.getName());
|
||||||
|
@ -175,7 +175,6 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
||||||
|
|
||||||
Context context = v.getContext();
|
Context context = v.getContext();
|
||||||
|
|
||||||
String[] parts = userRepositories.getFullName().split("/");
|
|
||||||
RepositoryContext repo = new RepositoryContext(userRepositories, context);
|
RepositoryContext repo = new RepositoryContext(userRepositories, context);
|
||||||
repo.saveToDB(context);
|
repo.saveToDB(context);
|
||||||
Intent intent = repo.getIntent(context, RepoDetailActivity.class);
|
Intent intent = repo.getIntent(context, RepoDetailActivity.class);
|
||||||
|
@ -184,7 +183,6 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMoreDataAvailable(boolean moreDataAvailable) {
|
public void setMoreDataAvailable(boolean moreDataAvailable) {
|
||||||
|
|
|
@ -127,7 +127,7 @@ public class ReposListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
||||||
String timeFormat = tinyDb.getString("dateFormat", "pretty");
|
String timeFormat = tinyDb.getString("dateFormat", "pretty");
|
||||||
orgName.setText(repositories.getFullName().split("/")[0]);
|
orgName.setText(repositories.getFullName().split("/")[0]);
|
||||||
repoName.setText(repositories.getFullName().split("/")[1]);
|
repoName.setText(repositories.getFullName().split("/")[1]);
|
||||||
repoStars.setText(String.valueOf(repositories.getStarsCount()));
|
repoStars.setText(AppUtil.numberFormatter(repositories.getStarsCount()));
|
||||||
|
|
||||||
ColorGenerator generator = ColorGenerator.Companion.getMATERIAL();
|
ColorGenerator generator = ColorGenerator.Companion.getMATERIAL();
|
||||||
int color = generator.getColor(repositories.getName());
|
int color = generator.getColor(repositories.getName());
|
||||||
|
|
|
@ -19,12 +19,13 @@ public class RepositoriesApi extends BaseApi {
|
||||||
repositoriesDao = gitnexDatabase.repositoriesDao();
|
repositoriesDao = gitnexDatabase.repositoriesDao();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long insertRepository(int repoAccountId, String repositoryOwner, String repositoryName) {
|
public long insertRepository(int repoAccountId, String repositoryOwner, String repositoryName, int mostVisited) {
|
||||||
|
|
||||||
Repository repository = new Repository();
|
Repository repository = new Repository();
|
||||||
repository.setRepoAccountId(repoAccountId);
|
repository.setRepoAccountId(repoAccountId);
|
||||||
repository.setRepositoryOwner(repositoryOwner);
|
repository.setRepositoryOwner(repositoryOwner);
|
||||||
repository.setRepositoryName(repositoryName);
|
repository.setRepositoryName(repositoryName);
|
||||||
|
repository.setMostVisited(mostVisited);
|
||||||
|
|
||||||
return insertRepositoryAsyncTask(repository);
|
return insertRepositoryAsyncTask(repository);
|
||||||
}
|
}
|
||||||
|
@ -69,4 +70,11 @@ public class RepositoriesApi extends BaseApi {
|
||||||
executorService.execute(() -> repositoriesDao.deleteRepository(repositoryId));
|
executorService.execute(() -> repositoriesDao.deleteRepository(repositoryId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateRepositoryMostVisited(int mostVisited, int repositoryId) {
|
||||||
|
executorService.execute(() -> repositoriesDao.updateRepositoryMostVisited(mostVisited, repositoryId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<List<Repository>> fetchAllMostVisited(int repoAccountId) {
|
||||||
|
return repositoriesDao.fetchAllMostVisited(repoAccountId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,4 +44,9 @@ public interface RepositoriesDao {
|
||||||
@Query("DELETE FROM Repositories WHERE repoAccountId = :repoAccountId")
|
@Query("DELETE FROM Repositories WHERE repoAccountId = :repoAccountId")
|
||||||
void deleteRepositoriesByAccount(int repoAccountId);
|
void deleteRepositoriesByAccount(int repoAccountId);
|
||||||
|
|
||||||
|
@Query("UPDATE Repositories SET mostVisited = :mostVisited WHERE repositoryId = :repositoryId")
|
||||||
|
void updateRepositoryMostVisited(int mostVisited, int repositoryId);
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Repositories WHERE mostVisited > 0 AND repoAccountId = :repoAccountId ORDER BY mostVisited DESC LIMIT 50")
|
||||||
|
LiveData<List<Repository>> fetchAllMostVisited(int repoAccountId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,11 @@ import org.mian.gitnex.database.models.UserAccount;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Database(entities = {Draft.class, Repository.class, UserAccount.class},
|
@Database(entities = {Draft.class, Repository.class, UserAccount.class},
|
||||||
version = 5, exportSchema = false)
|
version = 6, exportSchema = false)
|
||||||
public abstract class GitnexDatabase extends RoomDatabase {
|
public abstract class GitnexDatabase extends RoomDatabase {
|
||||||
|
|
||||||
private static final String DB_NAME = "gitnex";
|
private static final String DB_NAME = "gitnex";
|
||||||
private static GitnexDatabase gitnexDatabase;
|
private static volatile GitnexDatabase gitnexDatabase;
|
||||||
|
|
||||||
public abstract DraftsDao draftsDao();
|
public abstract DraftsDao draftsDao();
|
||||||
public abstract RepositoriesDao repositoriesDao();
|
public abstract RepositoriesDao repositoriesDao();
|
||||||
|
@ -61,6 +61,14 @@ public abstract class GitnexDatabase extends RoomDatabase {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static final Migration MIGRATION_5_6 = new Migration(5, 6) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||||
|
database.execSQL("ALTER TABLE 'Repositories' ADD COLUMN 'mostVisited' INTEGER NOT NULL DEFAULT 0");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public static GitnexDatabase getDatabaseInstance(Context context) {
|
public static GitnexDatabase getDatabaseInstance(Context context) {
|
||||||
|
|
||||||
if (gitnexDatabase == null) {
|
if (gitnexDatabase == null) {
|
||||||
|
@ -68,9 +76,9 @@ public abstract class GitnexDatabase extends RoomDatabase {
|
||||||
if(gitnexDatabase == null) {
|
if(gitnexDatabase == null) {
|
||||||
|
|
||||||
gitnexDatabase = Room.databaseBuilder(context, GitnexDatabase.class, DB_NAME)
|
gitnexDatabase = Room.databaseBuilder(context, GitnexDatabase.class, DB_NAME)
|
||||||
// .fallbackToDestructiveMigration()
|
//.fallbackToDestructiveMigration()
|
||||||
.allowMainThreadQueries()
|
.allowMainThreadQueries()
|
||||||
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5)
|
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, MIGRATION_5_6)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ public class Repository implements Serializable {
|
||||||
private int repoAccountId;
|
private int repoAccountId;
|
||||||
private String repositoryOwner;
|
private String repositoryOwner;
|
||||||
private String repositoryName;
|
private String repositoryName;
|
||||||
|
private int mostVisited;
|
||||||
|
|
||||||
public int getRepositoryId() {
|
public int getRepositoryId() {
|
||||||
return repositoryId;
|
return repositoryId;
|
||||||
|
@ -56,4 +57,12 @@ public class Repository implements Serializable {
|
||||||
public void setRepositoryName(String repositoryName) {
|
public void setRepositoryName(String repositoryName) {
|
||||||
this.repositoryName = repositoryName;
|
this.repositoryName = repositoryName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMostVisited() {
|
||||||
|
return mostVisited;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMostVisited(int mostVisited) {
|
||||||
|
this.mostVisited = mostVisited;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,6 @@ public class DraftsFragment extends Fragment {
|
||||||
fetchDataAsync(currentActiveAccountId);
|
fetchDataAsync(currentActiveAccountId);
|
||||||
|
|
||||||
return fragmentDraftsBinding.getRoot();
|
return fragmentDraftsBinding.getRoot();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetchDataAsync(int accountId) {
|
private void fetchDataAsync(int accountId) {
|
||||||
|
@ -99,18 +98,14 @@ public class DraftsFragment extends Fragment {
|
||||||
draftsList_.clear();
|
draftsList_.clear();
|
||||||
noData.setVisibility(View.GONE);
|
noData.setVisibility(View.GONE);
|
||||||
draftsList_.addAll(drafts);
|
draftsList_.addAll(drafts);
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataChanged();
|
||||||
mRecyclerView.setAdapter(adapter);
|
mRecyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
noData.setVisibility(View.VISIBLE);
|
noData.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -126,9 +121,8 @@ public class DraftsFragment extends Fragment {
|
||||||
|
|
||||||
BaseApi.getInstance(ctx, DraftsApi.class).deleteAllDrafts(accountId);
|
BaseApi.getInstance(ctx, DraftsApi.class).deleteAllDrafts(accountId);
|
||||||
draftsList_.clear();
|
draftsList_.clear();
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataChanged();
|
||||||
Toasty.success(ctx, getResources().getString(R.string.draftsDeleteSuccess));
|
Toasty.success(ctx, getResources().getString(R.string.draftsDeleteSuccess));
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Toasty.warning(ctx, getResources().getString(R.string.draftsListEmpty));
|
Toasty.warning(ctx, getResources().getString(R.string.draftsListEmpty));
|
||||||
|
@ -160,10 +154,8 @@ public class DraftsFragment extends Fragment {
|
||||||
|
|
||||||
filter(newText);
|
filter(newText);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void filter(String text) {
|
private void filter(String text) {
|
||||||
|
@ -184,5 +176,4 @@ public class DraftsFragment extends Fragment {
|
||||||
|
|
||||||
adapter.updateList(arr);
|
adapter.updateList(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
package org.mian.gitnex.fragments;
|
||||||
|
|
||||||
|
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 android.widget.TextView;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
import org.mian.gitnex.R;
|
||||||
|
import org.mian.gitnex.activities.MainActivity;
|
||||||
|
import org.mian.gitnex.adapters.MostVisitedReposAdapter;
|
||||||
|
import org.mian.gitnex.database.api.BaseApi;
|
||||||
|
import org.mian.gitnex.database.api.RepositoriesApi;
|
||||||
|
import org.mian.gitnex.database.models.Repository;
|
||||||
|
import org.mian.gitnex.databinding.FragmentDraftsBinding;
|
||||||
|
import org.mian.gitnex.helpers.TinyDB;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author M M Arif
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MostVisitedReposFragment extends Fragment {
|
||||||
|
|
||||||
|
private Context ctx;
|
||||||
|
private MostVisitedReposAdapter adapter;
|
||||||
|
private RecyclerView mRecyclerView;
|
||||||
|
private RepositoriesApi repositoriesApi;
|
||||||
|
private TextView noData;
|
||||||
|
private List<Repository> mostVisitedReposList;
|
||||||
|
private int currentActiveAccountId;
|
||||||
|
private SwipeRefreshLayout swipeRefresh;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
FragmentDraftsBinding fragmentDraftsBinding = FragmentDraftsBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
|
ctx = getContext();
|
||||||
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
|
((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.navMostVisited));
|
||||||
|
|
||||||
|
TinyDB tinyDb = TinyDB.getInstance(ctx);
|
||||||
|
|
||||||
|
mostVisitedReposList = new ArrayList<>();
|
||||||
|
repositoriesApi = BaseApi.getInstance(ctx, RepositoriesApi.class);
|
||||||
|
|
||||||
|
noData = fragmentDraftsBinding.noData;
|
||||||
|
mRecyclerView = fragmentDraftsBinding.recyclerView;
|
||||||
|
swipeRefresh = fragmentDraftsBinding.pullToRefresh;
|
||||||
|
|
||||||
|
mRecyclerView.setHasFixedSize(true);
|
||||||
|
mRecyclerView.setLayoutManager(new LinearLayoutManager(ctx));
|
||||||
|
|
||||||
|
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
|
||||||
|
DividerItemDecoration.VERTICAL);
|
||||||
|
mRecyclerView.addItemDecoration(dividerItemDecoration);
|
||||||
|
|
||||||
|
adapter = new MostVisitedReposAdapter(mostVisitedReposList);
|
||||||
|
currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
|
||||||
|
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||||
|
|
||||||
|
mostVisitedReposList.clear();
|
||||||
|
fetchDataAsync(currentActiveAccountId);
|
||||||
|
}, 250));
|
||||||
|
|
||||||
|
fetchDataAsync(currentActiveAccountId);
|
||||||
|
|
||||||
|
return fragmentDraftsBinding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchDataAsync(int accountId) {
|
||||||
|
|
||||||
|
repositoriesApi.fetchAllMostVisited(accountId).observe(getViewLifecycleOwner(), mostVisitedRepos -> {
|
||||||
|
|
||||||
|
swipeRefresh.setRefreshing(false);
|
||||||
|
assert mostVisitedRepos != null;
|
||||||
|
if(mostVisitedRepos.size() > 0) {
|
||||||
|
|
||||||
|
mostVisitedReposList.clear();
|
||||||
|
noData.setVisibility(View.GONE);
|
||||||
|
mostVisitedReposList.addAll(mostVisitedRepos);
|
||||||
|
adapter.notifyDataChanged();
|
||||||
|
mRecyclerView.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
noData.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ import java.io.OutputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
@ -456,6 +457,27 @@ public class AppUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Pretty number format
|
||||||
|
* Example, 1200 = 1.2k
|
||||||
|
*/
|
||||||
|
public static String numberFormatter(Number number) {
|
||||||
|
|
||||||
|
char[] suffix = {' ', 'k', 'M', 'B', 'T'};
|
||||||
|
long numValue = number.longValue();
|
||||||
|
int value = (int) Math.floor(Math.log10(numValue));
|
||||||
|
int base = value / 3;
|
||||||
|
if(value >= 3 && base < suffix.length) {
|
||||||
|
return new DecimalFormat("#0.0").format(numValue / Math.pow(10, base * 3)) + suffix[base];
|
||||||
|
}
|
||||||
|
if(base >= suffix.length) {
|
||||||
|
return new DecimalFormat("#0").format(numValue / Math.pow(10, base * 2)) + suffix[4];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new DecimalFormat("#,##0").format(numValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
* check for ghost/restricted users/profiles
|
* check for ghost/restricted users/profiles
|
||||||
*/
|
*/
|
||||||
public static Boolean checkGhostUsers(String str) {
|
public static Boolean checkGhostUsers(String str) {
|
||||||
|
|
|
@ -33,7 +33,6 @@ public class RepositoryContext implements Serializable {
|
||||||
OPEN,
|
OPEN,
|
||||||
CLOSED;
|
CLOSED;
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
@ -243,16 +242,17 @@ public class RepositoryContext implements Serializable {
|
||||||
RepositoriesApi repositoryData = BaseApi.getInstance(context, RepositoriesApi.class);
|
RepositoriesApi repositoryData = BaseApi.getInstance(context, RepositoriesApi.class);
|
||||||
|
|
||||||
assert repositoryData != null;
|
assert repositoryData != null;
|
||||||
Integer count = repositoryData.checkRepository(currentActiveAccountId, getOwner(), getName());
|
Repository getMostVisitedValue = repositoryData.getRepository(currentActiveAccountId, getOwner(), getName());
|
||||||
|
|
||||||
if(count == 0) {
|
if(getMostVisitedValue == null) {
|
||||||
long id = repositoryData.insertRepository(currentActiveAccountId, getOwner(), getName());
|
long id = repositoryData.insertRepository(currentActiveAccountId, getOwner(), getName(), 1);
|
||||||
setRepositoryId((int) id);
|
setRepositoryId((int) id);
|
||||||
return (int) id;
|
return (int) id;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Repository data = repositoryData.getRepository(currentActiveAccountId, getOwner(), getName());
|
Repository data = repositoryData.getRepository(currentActiveAccountId, getOwner(), getName());
|
||||||
setRepositoryId(data.getRepositoryId());
|
setRepositoryId(data.getRepositoryId());
|
||||||
|
repositoryData.updateRepositoryMostVisited(getMostVisitedValue.getMostVisited() + 1, data.getRepositoryId());
|
||||||
return data.getRepositoryId();
|
return data.getRepositoryId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<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,17l6,-6l4,4l8,-8"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="2"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="?attr/iconsColor"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M14,7l7,0l0,7"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="2"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="?attr/iconsColor"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
</vector>
|
|
@ -70,7 +70,7 @@
|
||||||
android:layout_marginBottom="@dimen/dimen8dp"
|
android:layout_marginBottom="@dimen/dimen8dp"
|
||||||
android:hint="@string/protocol"
|
android:hint="@string/protocol"
|
||||||
app:endIconTint="?attr/iconsColor"
|
app:endIconTint="?attr/iconsColor"
|
||||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu">
|
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu">
|
||||||
|
|
||||||
<AutoCompleteTextView
|
<AutoCompleteTextView
|
||||||
android:id="@+id/httpsSpinner"
|
android:id="@+id/httpsSpinner"
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_margin="16dp"
|
android:layout_margin="16dp"
|
||||||
android:text="@string/draftsListEmpty"
|
android:text="@string/noDataFound"
|
||||||
android:textColor="?attr/primaryTextColor"
|
android:textColor="?attr/primaryTextColor"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout 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="wrap_content"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:focusable="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="@dimen/dimen16dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/org_info_frame"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/dimen8dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:ignore="UseCompoundDrawables">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image"
|
||||||
|
android:layout_width="@dimen/dimen24dp"
|
||||||
|
android:layout_height="@dimen/dimen24dp"
|
||||||
|
android:layout_marginStart="@dimen/dimen0dp"
|
||||||
|
android:layout_marginEnd="@dimen/dimen10dp"
|
||||||
|
android:contentDescription="@string/repoContentAvatar"
|
||||||
|
android:src="@drawable/ic_android" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/org_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?attr/primaryTextColor"
|
||||||
|
android:textSize="@dimen/dimen14sp"
|
||||||
|
tools:text="@string/orgName" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/repo_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/repoName"
|
||||||
|
android:textColor="?attr/primaryTextColor"
|
||||||
|
android:textSize="@dimen/dimen16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/spacer_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginBottom="@dimen/dimen8dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/repo_info_stars_frame"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical|start"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:ignore="UseCompoundDrawables">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="@dimen/dimen18dp"
|
||||||
|
android:layout_height="@dimen/dimen18dp"
|
||||||
|
android:layout_marginStart="@dimen/dimen0dp"
|
||||||
|
android:layout_marginEnd="@dimen/dimen6dp"
|
||||||
|
android:contentDescription="@string/generalImgContentText"
|
||||||
|
app:srcCompat="@drawable/ic_trending"
|
||||||
|
app:tint="?attr/iconsColor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/most_visited"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:textColor="?attr/primaryTextColor"
|
||||||
|
android:textSize="@dimen/dimen14sp"
|
||||||
|
tools:text="@string/repoStars" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -38,6 +38,10 @@
|
||||||
android:icon="@drawable/ic_search"
|
android:icon="@drawable/ic_search"
|
||||||
android:title="@string/pageTitleExplore" />
|
android:title="@string/pageTitleExplore" />
|
||||||
|
|
||||||
|
<item android:id="@+id/nav_most_visited"
|
||||||
|
android:icon="@drawable/ic_trending"
|
||||||
|
android:title="@string/navMostVisited" />
|
||||||
|
|
||||||
<item android:id="@+id/nav_comments_draft"
|
<item android:id="@+id/nav_comments_draft"
|
||||||
android:icon="@drawable/ic_drafts"
|
android:icon="@drawable/ic_drafts"
|
||||||
android:title="@string/titleDrafts" />
|
android:title="@string/titleDrafts" />
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<dimen name="dimen10dp">10dp</dimen>
|
<dimen name="dimen10dp">10dp</dimen>
|
||||||
<dimen name="dimen12dp">12dp</dimen>
|
<dimen name="dimen12dp">12dp</dimen>
|
||||||
<dimen name="dimen16dp">16dp</dimen>
|
<dimen name="dimen16dp">16dp</dimen>
|
||||||
|
<dimen name="dimen18dp">18dp</dimen>
|
||||||
<dimen name="dimen20dp">20dp</dimen>
|
<dimen name="dimen20dp">20dp</dimen>
|
||||||
<dimen name="dimen24dp">24dp</dimen>
|
<dimen name="dimen24dp">24dp</dimen>
|
||||||
<dimen name="dimen26dp">26dp</dimen>
|
<dimen name="dimen26dp">26dp</dimen>
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
<string name="navLogout">Logout</string>
|
<string name="navLogout">Logout</string>
|
||||||
<string name="navAdministration">Administration</string>
|
<string name="navAdministration">Administration</string>
|
||||||
<string name="navMyIssues">My Issues</string>
|
<string name="navMyIssues">My Issues</string>
|
||||||
|
<string name="navMostVisited">Most Visited Repos</string>
|
||||||
<!-- menu items -->
|
<!-- menu items -->
|
||||||
|
|
||||||
<!-- page titles -->
|
<!-- page titles -->
|
||||||
|
|
Loading…
Reference in New Issue