Skip to content

Commit 5bfd204

Browse files
committed
listing user & organization repositories.
1 parent 1c294c9 commit 5bfd204

28 files changed

+793
-65
lines changed

.idea/.gitignore

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mobile/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ android {
7171
}
7272
release {
7373
signingConfig signingConfigs.release
74-
manifestPlaceholders = [accessToken: ""]
74+
manifestPlaceholders = [ accessToken: "" ]
7575
proguardFile "${project.rootDir}/proguard/android.pro"
7676
proguardFile "${project.rootDir}/proguard/androidx.pro"
7777
proguardFile "${project.rootDir}/proguard/retrofit.pro"

mobile/src/main/java/io/syslogic/github/Constants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
public final class Constants {
1111

1212
@NonNull public static final String ARGUMENT_ITEM_ID = "itemId";
13+
@NonNull public static final String ARGUMENT_ITEM_NAME = "name";
1314
@NonNull public static final String ARGUMENT_REPOSITORY_TOPIC = "topic";
1415

1516
@NonNull public static final Integer REQUESTCODE_ADD_ACCESS_TOKEN = 500;

mobile/src/main/java/io/syslogic/github/activity/AuthenticatorActivity.java

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,31 @@
55
import android.accounts.AccountManager;
66
import android.os.Bundle;
77
import android.text.Editable;
8+
import android.util.Log;
89
import android.widget.Toast;
910

1011
import androidx.annotation.NonNull;
1112
import androidx.annotation.Nullable;
1213
import androidx.annotation.VisibleForTesting;
1314
import androidx.databinding.ViewDataBinding;
1415

16+
import com.google.gson.JsonObject;
17+
import com.google.gson.JsonParser;
18+
19+
import java.io.IOException;
20+
21+
import io.syslogic.github.BuildConfig;
1522
import io.syslogic.github.R;
1623
import io.syslogic.github.databinding.FragmentAccessTokenBinding;
24+
import io.syslogic.github.model.User;
1725
import io.syslogic.github.network.TokenHelper;
26+
import io.syslogic.github.retrofit.GithubClient;
27+
28+
import okhttp3.ResponseBody;
29+
30+
import retrofit2.Call;
31+
import retrofit2.Callback;
32+
import retrofit2.Response;
1833

1934
/**
2035
* The Authenticator {@link BaseActivity}
@@ -62,20 +77,60 @@ protected void onCreate(@Nullable Bundle icicle) {
6277
Editable editable = this.getDataBinding().personalAccessToken.getText();
6378
if (editable != null && !editable.toString().isEmpty()) {
6479

65-
/* TODO: add Account and return Bundle? */
66-
Account account = TokenHelper.addAccount(AccountManager.get(AuthenticatorActivity.this), editable.toString());
67-
this.mResult = new Bundle();
68-
if (account != null) {
69-
this.mResult.putInt(AccountManager.KEY_ERROR_CODE, 0);
70-
} else {
71-
Toast.makeText(AuthenticatorActivity.this, "The access token has not been added.\nOnly one token is being supported", Toast.LENGTH_SHORT).show();
72-
this.mResult.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION);
73-
}
74-
this.mResponse.onResult(this.mResult);
80+
/* Obtain the username; this also validates the access token. */
81+
String token = editable.toString();
82+
Call<User> api = GithubClient.getUser(token);
83+
if (BuildConfig.DEBUG) {Log.w(LOG_TAG, api.request().url() + "");}
84+
api.enqueue(new Callback<>() {
85+
@Override
86+
public void onResponse(@NonNull Call<User> call, @NonNull Response<User> response) {
87+
mResult = new Bundle();
88+
switch (response.code()) {
89+
90+
// OK
91+
case 200 -> {
92+
if (response.body() != null) {
93+
User item = response.body();
94+
Account account = TokenHelper.addAccount(AccountManager.get(AuthenticatorActivity.this), item.getLogin(), token);
95+
if (account != null) {
96+
mResult.putInt(AccountManager.KEY_ERROR_CODE, 0);
97+
} else {
98+
Toast.makeText(AuthenticatorActivity.this, "The access token has not been added.\nOnly one token is being supported", Toast.LENGTH_SHORT).show();
99+
mResult.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION);
100+
}
101+
}
102+
}
103+
case 401, 403, 404 -> {
104+
/* "bad credentials" means that the provided access-token is invalid. */
105+
mResult.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION);
106+
if (response.errorBody() != null) {
107+
logError(response.errorBody());
108+
}
109+
}
110+
}
111+
mResponse.onResult(mResult);
112+
}
113+
114+
@Override
115+
public void onFailure(@NonNull Call<User> call, @NonNull Throwable t) {
116+
if (BuildConfig.DEBUG) {Log.e(LOG_TAG, "" + t.getMessage());}
117+
}
118+
});
75119
}
76120
});
77121
}
78122

123+
void logError(@NonNull ResponseBody responseBody) {
124+
try {
125+
String errors = responseBody.string();
126+
JsonObject jsonObject = JsonParser.parseString(errors).getAsJsonObject();
127+
Toast.makeText(AuthenticatorActivity.this, jsonObject.get("message").toString(), Toast.LENGTH_LONG).show();
128+
if (BuildConfig.DEBUG) {Log.e(LOG_TAG, jsonObject.get("message").toString());}
129+
} catch (IOException e) {
130+
if (BuildConfig.DEBUG) {Log.e(LOG_TAG, "" + e.getMessage());}
131+
}
132+
}
133+
79134
/** Sends the result or a Constants.ERROR_CODE_CANCELED error if a result isn't present. */
80135
@Override
81136
public void finish() {

mobile/src/main/java/io/syslogic/github/content/RepositorySyncAdapter.java

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import io.syslogic.github.BuildConfig;
1919
import io.syslogic.github.Constants;
2020
import io.syslogic.github.model.QueryString;
21-
import io.syslogic.github.model.Repositories;
21+
import io.syslogic.github.model.RepositorySearch;
2222
import io.syslogic.github.model.Repository;
2323
import io.syslogic.github.model.User;
2424
import io.syslogic.github.network.TokenHelper;
@@ -53,10 +53,6 @@ public class RepositorySyncAdapter extends AbstractThreadedSyncAdapter {
5353

5454
private ArrayList<Repository> repositories = new ArrayList<>();
5555

56-
private List<QueryString> queryStrings;
57-
58-
private User user;
59-
6056
/** Constructor. */
6157
public RepositorySyncAdapter(@NonNull Context context, boolean autoInitialize, boolean allowParallelSyncs) {
6258
super(context, autoInitialize, allowParallelSyncs);
@@ -104,30 +100,28 @@ public void onFailure(@NonNull Call<User> call, @NonNull Throwable t) {
104100

105101
void onUser(@NonNull User item) {
106102
this.log("onUser: " + item.getLogin());
107-
this.user = item;
108103
}
109104

110105
void onQueryStrings(@NonNull List<QueryString> items) {
111106
this.log("onQueryStrings: " + items.size());
112-
this.queryStrings = items;
113107
for (QueryString item: items) {
114-
Call<Repositories> api = GithubClient.getRepositories(this.accessToken, item.toQueryString(), "forks", "desc", 1);
108+
Call<RepositorySearch> api = GithubClient.searchRepositories(this.accessToken, item.toQueryString(), "forks", "desc", 1);
115109
this.log("Building content cache for query-string: " + item.toQueryString());
116110
this.log("" + api.request().url());
117-
api.enqueue(new Callback<Repositories>() {
111+
api.enqueue(new Callback<RepositorySearch>() {
118112
@Override
119-
public void onResponse(@NonNull Call<Repositories> call, @NonNull Response<Repositories> response) {
113+
public void onResponse(@NonNull Call<RepositorySearch> call, @NonNull Response<RepositorySearch> response) {
120114
if (response.body() != null) {onRepositories(response.body());}
121115
}
122116
@Override
123-
public void onFailure(@NonNull Call<Repositories> call, @NonNull Throwable t) {
117+
public void onFailure(@NonNull Call<RepositorySearch> call, @NonNull Throwable t) {
124118
if (mDebug) {Log.e(LOG_TAG, "" + t.getMessage());}
125119
}
126120
});
127121
}
128122
}
129123

130-
void onRepositories(@NonNull Repositories item) {
124+
void onRepositories(@NonNull RepositorySearch item) {
131125
this.log("onRepositories: " + item.getRepositories().size());
132126
for (Repository repository: item.getRepositories()) {
133127
this.log("Repo: " + repository.getUrl());

mobile/src/main/java/io/syslogic/github/fragment/HomeScreenFragment.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
6464
.navigate(R.id.action_homeScreenFragment_to_repositoriesFragment));
6565

6666
/* Navigating to WorkflowFragment */
67-
this.mDataBinding.buttonWorkflow
67+
this.mDataBinding.buttonWorkflows
6868
.setOnClickListener(view -> activity.getNavController()
69-
.navigate(R.id.action_homeScreenFragment_to_workflowFragment));
69+
.navigate(R.id.action_homeScreenFragment_to_workflowsFragment));
7070

7171
/* Navigating to GitHub Sponsors */
7272
this.mDataBinding.textGitHubSponsors

mobile/src/main/java/io/syslogic/github/fragment/RepositoriesFragment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public void onNothingSelected(AdapterView<?> parent) {}
122122
this.getDataBinding().toolbarRepositories.spinnerQueryString.setVisibility(View.INVISIBLE);
123123
}
124124
} catch (IllegalStateException e) {
125-
if (mDebug) {Log.e(LOG_TAG, e.getMessage());}
125+
if (mDebug) {Log.e(LOG_TAG, "" + e.getMessage());}
126126
}
127127
});
128128
} else {
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package io.syslogic.github.fragment;
2+
3+
import android.os.Bundle;
4+
import android.view.LayoutInflater;
5+
import android.view.View;
6+
import android.view.ViewGroup;
7+
8+
import androidx.annotation.NonNull;
9+
import androidx.annotation.Nullable;
10+
import androidx.databinding.ViewDataBinding;
11+
12+
import io.syslogic.github.R;
13+
import io.syslogic.github.activity.NavHostActivity;
14+
import io.syslogic.github.databinding.FragmentWorkflowsBinding;
15+
import io.syslogic.github.provider.WorkflowsMenuProvider;
16+
import io.syslogic.github.recyclerview.WorkflowsAdapter;
17+
18+
/**
19+
* Workflows {@link BaseFragment}
20+
*
21+
* @author Martin Zeitler
22+
*/
23+
public class WorkflowsFragment extends BaseFragment {
24+
25+
/** Log Tag */
26+
@SuppressWarnings("unused")
27+
private static final String LOG_TAG = WorkflowsFragment.class.getSimpleName();
28+
29+
@SuppressWarnings("unused")
30+
private static final int resId = R.layout.fragment_workflows;
31+
32+
/** Data Binding */
33+
private FragmentWorkflowsBinding mDataBinding;
34+
35+
/** Constructor */
36+
public WorkflowsFragment() {}
37+
38+
@NonNull
39+
@Override
40+
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
41+
42+
NavHostActivity activity = ((NavHostActivity) this.requireActivity());
43+
this.setDataBinding(FragmentWorkflowsBinding.inflate(inflater, container, false));
44+
45+
/* It removes & adds {@link BaseMenuProvider} */
46+
activity.setMenuProvider(new WorkflowsMenuProvider(activity));
47+
48+
activity.setSupportActionBar(this.getDataBinding().toolbarWorkflows.toolbarWorkflows);
49+
this.mDataBinding.toolbarWorkflows.home.setOnClickListener(view -> activity.onBackPressed());
50+
51+
if (! isNetworkAvailable(this.requireContext())) {
52+
this.onNetworkLost();
53+
} else {
54+
WorkflowsAdapter adapter = new WorkflowsAdapter(requireContext());
55+
this.getDataBinding().recyclerviewWorkflows.setAdapter(adapter);
56+
adapter.fetchPage(1);
57+
}
58+
return this.getDataBinding().getRoot();
59+
}
60+
61+
@NonNull
62+
public FragmentWorkflowsBinding getDataBinding() {
63+
return this.mDataBinding;
64+
}
65+
66+
@Override
67+
protected void setDataBinding(@NonNull ViewDataBinding binding) {
68+
this.mDataBinding = (FragmentWorkflowsBinding) binding;
69+
}
70+
71+
@Override
72+
public void onNetworkAvailable() {
73+
super.onNetworkAvailable();
74+
}
75+
76+
@Override
77+
public void onNetworkLost() {
78+
super.onNetworkLost();
79+
}
80+
81+
@Override
82+
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
83+
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
84+
// if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {}
85+
}
86+
}

mobile/src/main/java/io/syslogic/github/model/Repositories.java renamed to mobile/src/main/java/io/syslogic/github/model/RepositorySearch.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
import androidx.databinding.Bindable;
99

1010
/**
11-
* Model: Repositories
11+
* Model: Repository Search
1212
*
1313
* @author Martin Zeitler
1414
*/
15-
public class Repositories extends BaseModel {
15+
public class RepositorySearch extends BaseModel {
1616

1717
@SerializedName("items")
1818
private ArrayList<Repository> mItems;

mobile/src/main/java/io/syslogic/github/model/Workflow.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.syslogic.github.model;
22

33
import androidx.annotation.NonNull;
4+
import androidx.annotation.Nullable;
45

56
import com.google.gson.annotations.SerializedName;
67

@@ -14,12 +15,24 @@ public class Workflow {
1415
@SerializedName("name")
1516
private String name;
1617

18+
@SerializedName("jobs") // ?
19+
private WorkflowJobs jobs;
20+
1721
public void setName(@NonNull String value) {
1822
this.name = value;
1923
}
2024

25+
public void setJobs(@NonNull WorkflowJobs value) {
26+
this.jobs = value;
27+
}
28+
2129
@NonNull
2230
public String getName() {
2331
return this.name;
2432
}
33+
34+
@Nullable
35+
public WorkflowJobs getJobs() {
36+
return this.jobs;
37+
}
2538
}

0 commit comments

Comments
 (0)