Skip to content
Snippets Groups Projects
Commit 1a536fbb authored by John Carlson's avatar John Carlson
Browse files

Start to parse links within the app and route them to other activities

parent 22c608cd
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -47,6 +47,20 @@
<activity android:name=".activity.AddMilestoneActivity"/>
<activity android:name=".activity.SettingsActivity"/>
<activity android:name=".activity.BuildActivity"/>
<activity android:name=".activity.RoutingActivity"
android:launchMode="singleTask">
<!-- Standard Url -->
<intent-filter android:label="@string/deeplink_text">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:scheme="@string/deeplink_scheme" />
</intent-filter>
</activity>
<meta-data
android:name="io.fabric.ApiKey"
android:value="${fabric_key}" />
Loading
Loading
Loading
Loading
@@ -44,7 +44,7 @@ import timber.log.Timber;
* Thats what its all about
*/
public class AboutActivity extends BaseActivity {
private static final long REPO_ID = 473568;
private static final String REPO_ID = "473568";
 
public static Intent newInstance(Context context) {
Intent intent = new Intent(context, AboutActivity.class);
Loading
Loading
Loading
Loading
@@ -50,6 +50,8 @@ public class IssueActivity extends BaseActivity {
 
private static final String EXTRA_PROJECT = "extra_project";
private static final String EXTRA_SELECTED_ISSUE = "extra_selected_issue";
private static final String EXTRA_PROJECT_ID = "extra_project_id";
private static final String EXTRA_ISSUE_ID = "extra_issue_id";
 
public static Intent newInstance(Context context, Project project, Issue issue) {
Intent intent = new Intent(context, IssueActivity.class);
Loading
Loading
@@ -58,6 +60,13 @@ public class IssueActivity extends BaseActivity {
return intent;
}
 
public static Intent newInstance(Context context, String projectId, String issueId) {
Intent intent = new Intent(context, IssueActivity.class);
intent.putExtra(EXTRA_PROJECT_ID, projectId);
intent.putExtra(EXTRA_ISSUE_ID, issueId);
return intent;
}
@Bind(R.id.root)
ViewGroup mRoot;
@Bind(R.id.toolbar)
Loading
Loading
@@ -84,11 +93,12 @@ public class IssueActivity extends BaseActivity {
}
 
private MenuItem mOpenCloseMenuItem;
private IssueDetailsAdapter mIssueDetailsAdapter;
private LinearLayoutManager mNotesLayoutManager;
private Project mProject;
private Issue mIssue;
private String mIssueId;
private boolean mLoading;
private Uri mNextPageUrl;
 
Loading
Loading
@@ -122,6 +132,42 @@ public class IssueActivity extends BaseActivity {
}
};
 
private Callback<Project> mProjectCallback = new EasyCallback<Project>() {
@Override
public void onResponse(@NonNull Project response) {
mProject = response;
GitLabClient.instance().getIssue(mProject.getId(), mIssueId).enqueue(mIssueCallback);
}
@Override
public void onAllFailure(Throwable t) {
Timber.e(t, null);
mSwipeRefreshLayout.setRefreshing(false);
Snackbar.make(mRoot, getString(R.string.failed_to_load), Snackbar.LENGTH_SHORT)
.show();
}
};
private Callback<Issue> mIssueCallback = new EasyCallback<Issue>() {
@Override
public void onResponse(@NonNull Issue response) {
mIssue = response;
mIssueDetailsAdapter = new IssueDetailsAdapter(IssueActivity.this, mIssue);
mNotesRecyclerView.setAdapter(mIssueDetailsAdapter);
bindIssue();
bindProject();
loadNotes();
}
@Override
public void onAllFailure(Throwable t) {
Timber.e(t, null);
mSwipeRefreshLayout.setRefreshing(false);
Snackbar.make(mRoot, getString(R.string.failed_to_load), Snackbar.LENGTH_SHORT)
.show();
}
};
private Callback<List<Note>> mNotesCallback = new EasyCallback<List<Note>>() {
 
@Override
Loading
Loading
@@ -206,9 +252,6 @@ public class IssueActivity extends BaseActivity {
mEventReceiver = new EventReceiver();
LabCoatApp.bus().register(mEventReceiver);
 
mProject = Parcels.unwrap(getIntent().getParcelableExtra(EXTRA_PROJECT));
mIssue = Parcels.unwrap(getIntent().getParcelableExtra(EXTRA_SELECTED_ISSUE));
mToolbar.setNavigationIcon(R.drawable.ic_back_24dp);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
Loading
Loading
@@ -216,15 +259,12 @@ public class IssueActivity extends BaseActivity {
onBackPressed();
}
});
mToolbar.setSubtitle(mProject.getNameWithNamespace());
mToolbar.inflateMenu(R.menu.menu_issue);
mOpenCloseMenuItem = mToolbar.getMenu().findItem(R.id.action_close);
mToolbar.setOnMenuItemClickListener(mOnMenuItemClickListener);
 
mIssueDetailsAdapter = new IssueDetailsAdapter(IssueActivity.this, mIssue);
mNotesLayoutManager = new LinearLayoutManager(this);
mNotesRecyclerView.setLayoutManager(mNotesLayoutManager);
mNotesRecyclerView.setAdapter(mIssueDetailsAdapter);
mNotesRecyclerView.addOnScrollListener(mOnScrollListener);
 
mNewNoteEdit.setOnEditorActionListener(new TextView.OnEditorActionListener() {
Loading
Loading
@@ -241,8 +281,20 @@ public class IssueActivity extends BaseActivity {
loadNotes();
}
});
bindIssue();
loadNotes();
if (getIntent().hasExtra(EXTRA_SELECTED_ISSUE)) {
mProject = Parcels.unwrap(getIntent().getParcelableExtra(EXTRA_PROJECT));
mIssue = Parcels.unwrap(getIntent().getParcelableExtra(EXTRA_SELECTED_ISSUE));
mIssueDetailsAdapter = new IssueDetailsAdapter(IssueActivity.this, mIssue);
mNotesRecyclerView.setAdapter(mIssueDetailsAdapter);
bindIssue();
bindProject();
loadNotes();
} else if (getIntent().hasExtra(EXTRA_ISSUE_ID)) {
mIssueId = getIntent().getStringExtra(EXTRA_ISSUE_ID);
String projectId = getIntent().getStringExtra(EXTRA_PROJECT_ID);
GitLabClient.instance().getProject(projectId).enqueue(mProjectCallback);
}
}
 
@Override
Loading
Loading
@@ -251,6 +303,10 @@ public class IssueActivity extends BaseActivity {
LabCoatApp.bus().unregister(mEventReceiver);
}
 
private void bindProject() {
mToolbar.setSubtitle(mProject.getNameWithNamespace());
}
private void bindIssue() {
mToolbar.setTitle(getString(R.string.issue_number) + mIssue.getIid());
setOpenCloseMenuStatus();
Loading
Loading
Loading
Loading
@@ -49,7 +49,7 @@ public class ProjectActivity extends BaseActivity {
return intent;
}
 
public static Intent newInstance(Context context, long projectId) {
public static Intent newInstance(Context context, String projectId) {
Intent intent = new Intent(context, ProjectActivity.class);
intent.putExtra(EXTRA_PROJECT_ID, projectId);
return intent;
Loading
Loading
@@ -177,7 +177,7 @@ public class ProjectActivity extends BaseActivity {
mToolbar.setOnMenuItemClickListener(mOnMenuItemClickListener);
 
if (mProject == null) {
long projectId = getIntent().getLongExtra(EXTRA_PROJECT_ID, -1);
String projectId = getIntent().getStringExtra(EXTRA_PROJECT_ID);
loadProject(projectId);
} else {
setupTabs();
Loading
Loading
@@ -185,7 +185,7 @@ public class ProjectActivity extends BaseActivity {
}
}
 
private void loadProject(long projectId) {
private void loadProject(String projectId) {
mProgress.setAlpha(0.0f);
mProgress.setVisibility(View.VISIBLE);
mProgress.animate().alpha(1.0f);
Loading
Loading
package com.commit451.gitlab.activity;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Toast;
import com.commit451.gitlab.R;
import com.commit451.gitlab.util.DeepLinker;
import com.commit451.gitlab.util.IntentUtil;
import com.commit451.gitlab.util.NavigationManager;
import timber.log.Timber;
/**
* The easy way to do deep links. Just route everything here, and it does all the work.
*/
public class RoutingActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handleIntent(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (intent == null || intent.getData() == null) {
Timber.e("No url was passed. How did that happen?");
finish();
return;
}
//If it has an original uri, this means that it is an internal deep link and we
//can still fall back to what the original uri was and just show it
Uri originalUri = intent.getParcelableExtra(DeepLinker.EXTRA_ORIGINAL_URI);
Uri link = intent.getData();
Timber.d("Received deep link %s", link);
Timber.d("Original link was %s", originalUri);
boolean handled = false;
if (link.getPath().contains("issues")) {
Timber.d("Parsing as issue uri");
if (link.getPathSegments().size() == 3) {
//this means it was just a link to something like
//gitlab.com/Commit451/LabCoat/issues
launchProject(link);
handled = true;
} else if (link.getPathSegments().size() == 4) {
//this is good, it means it is a link to an actual issue
handled = true;
String projectId = link.getPathSegments().get(1);
String lastSegment = link.getPathSegments().get(3);
//We have to do this cause there can be args on the url, such as
//https://gitlab.com/Commit451/LabCoat/issues/158#note_4560580
String[] stuff = lastSegment.split("#");
String issueId = stuff[0];
Timber.d("Navigating to project %s with issue number %s", projectId, issueId);
NavigationManager.navigateToIssue(this, projectId, issueId);
}
}
if (!handled) {
if (originalUri != null) {
launchOriginalUri(originalUri);
} else {
showError();
}
}
}
private void launchProject(Uri uri) {
String projectId = uri.getPathSegments().get(2);
NavigationManager.navigateToProject(this, projectId);
}
private void launchOriginalUri(Uri uri) {
IntentUtil.openPage(this, uri.toString());
}
private void showError() {
Toast.makeText(RoutingActivity.this, R.string.deeplink_navigate_error, Toast.LENGTH_SHORT)
.show();
}
}
Loading
Loading
@@ -125,7 +125,7 @@ public interface GitLab {
Call<List<Project>> getStarredProjects();
 
@GET(API_VERSION + "/projects/{id}")
Call<Project> getProject(@Path("id") long projectId);
Call<Project> getProject(@Path("id") String projectId);
 
@GET
Call<List<Project>> getProjects(@Url String url);
Loading
Loading
@@ -241,7 +241,7 @@ public interface GitLab {
 
@GET(API_VERSION + "/projects/{id}/issues/{issue_id}")
Call<Issue> getIssue(@Path("id") long projectId,
@Path("issue_id") long issueId);
@Path("issue_id") String issueId);
 
@FormUrlEncoded
@POST(API_VERSION + "/projects/{id}/issues")
Loading
Loading
@@ -283,7 +283,7 @@ public interface GitLab {
Call<List<Branch>> getBranches(@Path("id") long projectId);
 
@GET(API_VERSION + "/projects/{id}/repository/contributors")
Call<List<Contributor>> getContributors(@Path("id") long projectId);
Call<List<Contributor>> getContributors(@Path("id") String projectId);
 
@GET(API_VERSION + "/projects/{id}/repository/tree")
Call<List<RepositoryTreeObject>> getTree(@Path("id") long projectId,
Loading
Loading
package com.commit451.gitlab.util;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import com.commit451.gitlab.R;
/**
* Generates deeplinks
*/
public class DeepLinker {
public static final String EXTRA_ORIGINAL_URI = "original_uri";
public static Intent generateDeeplinkIntentFromUri(Context context, Uri originalUri) {
Uri uri = originalUri.buildUpon()
.scheme(context.getString(R.string.deeplink_scheme))
.build();
return generatePrivateIntent(context, uri, originalUri);
}
private static Intent generatePrivateIntent(Context context, Uri uri, Uri originalUri) {
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.putExtra(EXTRA_ORIGINAL_URI, originalUri);
intent.setPackage(context.getPackageName());
return intent;
}
}
Loading
Loading
@@ -57,7 +57,7 @@ public class NavigationManager {
activity.startActivity(ProjectActivity.newInstance(activity, project));
}
 
public static void navigateToProject(Activity activity, long projectId) {
public static void navigateToProject(Activity activity, String projectId) {
activity.startActivity(ProjectActivity.newInstance(activity, projectId));
}
 
Loading
Loading
@@ -123,6 +123,10 @@ public class NavigationManager {
activity.startActivity(IssueActivity.newInstance(activity, project, issue));
}
 
public static void navigateToIssue(Activity activity, String projectId, String issueId) {
activity.startActivity(IssueActivity.newInstance(activity, projectId, issueId));
}
public static void navigateToMergeRequest(Activity activity, Project project, MergeRequest mergeRequest) {
Intent intent = MergeRequestActivity.newInstance(activity, project, mergeRequest);
activity.startActivity(intent);
Loading
Loading
@@ -197,38 +201,9 @@ public class NavigationManager {
public static void navigateToUrl(Activity activity, Uri uri, Account account) {
Timber.d("navigateToUrl: %s", uri);
if (account.getServerUrl().getHost().equals(uri.getHost())) {
boolean handled = navigateToUrl(activity, uri);
if (!handled) {
IntentUtil.openPage(activity, uri.toString());
}
activity.startActivity(DeepLinker.generateDeeplinkIntentFromUri(activity, uri));
} else {
IntentUtil.openPage(activity, uri.toString());
}
}
/**
* Attempts to map a url to an activity within the app
* @param activity the current activity
* @param uri the url we want to map
* @return true if we navigated somewhere, false otherwise
*/
private static boolean navigateToUrl(Activity activity, Uri uri) {
//TODO figure out the url to activity mapping
// if (uri.getPath().contains("issues")) {
// List<String> pathSegments = uri.getPathSegments();
// for (int i=0; i<pathSegments.size(); i++) {
// //segment == issues, and there is one more segment in the path
// if (pathSegments.get(i).equals("issues") && i != pathSegments.size()-1) {
// //TODO this would probably break if we had query params or anything else in the url
// String issueId = pathSegments.get(i+1);
// //TODO actually navigate to issue activity which will load the needed project and issue
// //navigateToIssue(activity, null, issueId);
// return true;
// }
// }
// navigateToProject(activity, -1);
// return true;
// }
return false;
}
}
Loading
Loading
@@ -370,4 +370,15 @@
<string name="build_commit_author">Author: %1$s</string>
<string name="build_commit_message">Message: %1$s</string>
<string name="no_build_artifacts_found">No build artifacts found.</string>
<!-- Deep link scheme -->
<string name="deeplink_scheme">labcoat</string>
<!-- Deep link host -->
<string name="deeplink_host">app</string>
<!-- Deep link titles -->
<string name="deeplink_text">Open with LabCoat</string>
<!-- Deep link paths -->
<string name="deeplink_path_issue">issue</string>
<string name="deeplink_navigate_error">No idea where to navigate to</string>
</resources>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment