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

A bunch of things to get builds into the app.

parent 9961a7a3
No related branches found
No related tags found
No related merge requests found
Showing
with 1364 additions and 30 deletions
Loading
Loading
@@ -25,26 +25,17 @@
</intent-filter>
</activity>
 
<activity android:name=".activity.ProjectActivity" />
<activity android:name=".activity.LoginActivity" />
<activity android:name=".activity.ProjectsActivity"
android:launchMode="singleTask"/>
 
<activity android:name=".activity.GroupsActivity"
android:launchMode="singleTask"/>
 
<activity
android:name=".activity.FileActivity">
</activity>
<activity
android:name=".activity.IssueActivity" >
</activity>
<activity
android:name=".activity.DiffActivity" >
</activity>
<activity android:name=".activity.ProjectActivity" />
<activity android:name=".activity.LoginActivity" />
<activity android:name=".activity.FileActivity"/>
<activity android:name=".activity.IssueActivity" />
<activity android:name=".activity.DiffActivity"/>
<activity android:name=".activity.AboutActivity"/>
<activity android:name=".activity.AddUserActivity"/>
<activity android:name=".activity.UserActivity"/>
Loading
Loading
@@ -55,6 +46,7 @@
<activity android:name=".activity.MilestoneActivity"/>
<activity android:name=".activity.AddMilestoneActivity"/>
<activity android:name=".activity.SettingsActivity"/>
<activity android:name=".activity.BuildActivity"/>
<meta-data
android:name="io.fabric.ApiKey"
android:value="${fabric_key}" />
Loading
Loading
package com.commit451.gitlab.activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.commit451.gitlab.LabCoatApp;
import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.BuildSectionsPagerAdapter;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.event.BuildChangedEvent;
import com.commit451.gitlab.model.api.Build;
import com.commit451.gitlab.model.api.Project;
import org.parceler.Parcels;
import butterknife.Bind;
import butterknife.ButterKnife;
import timber.log.Timber;
/**
* Shows the details of a merge request
*/
public class BuildActivity extends BaseActivity {
private static final String KEY_PROJECT = "key_project";
private static final String KEY_BUILD = "key_merge_request";
public static Intent newInstance(Context context, Project project, Build build) {
Intent intent = new Intent(context, BuildActivity.class);
intent.putExtra(KEY_PROJECT, Parcels.wrap(project));
intent.putExtra(KEY_BUILD, Parcels.wrap(build));
return intent;
}
@Bind(R.id.root)
ViewGroup mRoot;
@Bind(R.id.toolbar)
Toolbar mToolbar;
@Bind(R.id.tabs)
TabLayout mTabLayout;
@Bind(R.id.pager)
ViewPager mViewPager;
@Bind(R.id.progress)
View mProgress;
Project mProject;
Build mBuild;
private final EasyCallback<Build> mRetryCallback = new EasyCallback<Build>() {
@Override
public void onResponse(@NonNull Build response) {
mProgress.setVisibility(View.GONE);
Snackbar.make(mRoot, R.string.build_started, Snackbar.LENGTH_LONG)
.show();
LabCoatApp.bus().post(new BuildChangedEvent(response));
}
@Override
public void onAllFailure(Throwable t) {
Timber.e(t, null);
mProgress.setVisibility(View.GONE);
Snackbar.make(mRoot, R.string.unable_to_retry_build, Snackbar.LENGTH_LONG)
.show();
}
};
private final EasyCallback<Build> mEraseCallback = new EasyCallback<Build>() {
@Override
public void onResponse(@NonNull Build response) {
mProgress.setVisibility(View.GONE);
Snackbar.make(mRoot, R.string.build_started, Snackbar.LENGTH_LONG)
.show();
LabCoatApp.bus().post(new BuildChangedEvent(response));
}
@Override
public void onAllFailure(Throwable t) {
Timber.e(t, null);
mProgress.setVisibility(View.GONE);
Snackbar.make(mRoot, R.string.unable_to_retry_build, Snackbar.LENGTH_LONG)
.show();
}
};
private final EasyCallback<Build> mCancelCallback = new EasyCallback<Build>() {
@Override
public void onResponse(@NonNull Build response) {
mProgress.setVisibility(View.GONE);
Snackbar.make(mRoot, R.string.build_canceled, Snackbar.LENGTH_LONG)
.show();
LabCoatApp.bus().post(new BuildChangedEvent(response));
}
@Override
public void onAllFailure(Throwable t) {
Timber.e(t, null);
mProgress.setVisibility(View.GONE);
Snackbar.make(mRoot, R.string.unable_to_cancel_build, Snackbar.LENGTH_LONG)
.show();
}
};
private final Toolbar.OnMenuItemClickListener mOnMenuItemClickListener = new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_retry:
mProgress.setVisibility(View.VISIBLE);
GitLabClient.instance().retryBuild(mProject.getId(), mBuild.getId()).enqueue(mRetryCallback);
return true;
case R.id.action_erase:
mProgress.setVisibility(View.VISIBLE);
GitLabClient.instance().eraseBuild(mProject.getId(), mBuild.getId()).enqueue(mEraseCallback);
return true;
case R.id.action_cancel:
mProgress.setVisibility(View.VISIBLE);
GitLabClient.instance().cancelBuild(mProject.getId(), mBuild.getId()).enqueue(mCancelCallback);
return true;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_build);
ButterKnife.bind(this);
mProject = Parcels.unwrap(getIntent().getParcelableExtra(KEY_PROJECT));
mBuild = Parcels.unwrap(getIntent().getParcelableExtra(KEY_BUILD));
mToolbar.setTitle(getString(R.string.build_number) + mBuild.getId());
mToolbar.setNavigationIcon(R.drawable.ic_back_24dp);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
mToolbar.setSubtitle(mProject.getNameWithNamespace());
mToolbar.inflateMenu(R.menu.menu_build);
mToolbar.setOnMenuItemClickListener(mOnMenuItemClickListener);
setupTabs();
}
private void setupTabs() {
BuildSectionsPagerAdapter sectionsPagerAdapter = new BuildSectionsPagerAdapter(
this,
getSupportFragmentManager(),
mProject,
mBuild);
mViewPager.setAdapter(sectionsPagerAdapter);
mTabLayout.setupWithViewPager(mViewPager);
}
}
package com.commit451.gitlab.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.PopupMenu;
import com.commit451.gitlab.R;
import com.commit451.gitlab.model.api.Artifact;
import com.commit451.gitlab.viewHolder.BuildArtifactViewHolder;
import java.util.ArrayList;
import java.util.Collection;
/**
* Show the build artifacts
*/
public class BuildArtifactsAdapter extends RecyclerView.Adapter<BuildArtifactViewHolder> {
public interface Listener {
void onFolderClicked(Artifact treeItem);
void onFileClicked(Artifact treeItem);
void onCopyClicked(Artifact treeItem);
void onShareClicked(Artifact treeItem);
void onOpenInBrowserClicked(Artifact treeItem);
}
private Listener mListener;
private ArrayList<Artifact> mValues;
private final View.OnClickListener onProjectClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = (int) v.getTag(R.id.list_position);
Artifact treeItem = getValueAt(position);
}
};
public BuildArtifactsAdapter(Listener listener) {
mListener = listener;
mValues = new ArrayList<>();
}
@Override
public BuildArtifactViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
BuildArtifactViewHolder holder = BuildArtifactViewHolder.inflate(parent);
holder.itemView.setOnClickListener(onProjectClickListener);
return holder;
}
@Override
public void onBindViewHolder(final BuildArtifactViewHolder holder, int position) {
final Artifact treeItem = getValueAt(position);
holder.bind(treeItem);
holder.itemView.setTag(R.id.list_position, position);
holder.popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_copy:
mListener.onCopyClicked(treeItem);
return true;
case R.id.action_share:
mListener.onShareClicked(treeItem);
return true;
case R.id.action_open:
mListener.onOpenInBrowserClicked(treeItem);
return true;
}
return false;
}
});
}
@Override
public int getItemCount() {
return mValues.size();
}
public void setData(Collection<Artifact> values) {
mValues.clear();
if (values != null) {
mValues.addAll(values);
}
notifyDataSetChanged();
}
public void clear() {
mValues.clear();
notifyDataSetChanged();
}
public Artifact getValueAt(int position) {
return mValues.get(position);
}
}
package com.commit451.gitlab.adapter;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import com.commit451.gitlab.R;
import com.commit451.gitlab.fragment.BuildArtifactsFragment;
import com.commit451.gitlab.fragment.BuildDescriptionFragment;
import com.commit451.gitlab.model.api.Build;
import com.commit451.gitlab.model.api.Project;
/**
* Build sections
*/
public class BuildSectionsPagerAdapter extends FragmentPagerAdapter {
private static final int SECTION_COUNT = 2;
private Project mProject;
private Build mBuild;
private String[] mTitles;
public BuildSectionsPagerAdapter(Context context, FragmentManager fm, Project project, Build build) {
super(fm);
mProject = project;
mBuild = build;
mTitles = context.getResources().getStringArray(R.array.build_tabs);
}
@Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return BuildDescriptionFragment.newInstance(mProject, mBuild);
case 1:
return BuildArtifactsFragment.newInstance(mProject, mBuild);
}
throw new IllegalStateException("Position exceeded on view pager");
}
@Override
public int getCount() {
return SECTION_COUNT;
}
@Override
public CharSequence getPageTitle(int position) {
return mTitles[position];
}
}
package com.commit451.gitlab.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import com.commit451.gitlab.R;
import com.commit451.gitlab.model.api.Build;
import com.commit451.gitlab.viewHolder.BuildViewHolder;
import com.commit451.gitlab.viewHolder.LoadingFooterViewHolder;
import java.util.ArrayList;
import java.util.Collection;
/**
* Builds adapter
*/
public class BuildsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int FOOTER_COUNT = 1;
private static final int TYPE_ITEM = 0;
private static final int TYPE_FOOTER = 1;
public interface Listener {
void onBuildClicked(Build issue);
}
private Listener mListener;
private ArrayList<Build> mValues;
private boolean mLoading = false;
public BuildsAdapter(Listener listener) {
mListener = listener;
mValues = new ArrayList<>();
}
private final View.OnClickListener onProjectClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = (int) v.getTag(R.id.list_position);
mListener.onBuildClicked(getValueAt(position));
}
};
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_ITEM:
BuildViewHolder holder = BuildViewHolder.inflate(parent);
holder.itemView.setOnClickListener(onProjectClickListener);
return holder;
case TYPE_FOOTER:
return LoadingFooterViewHolder.inflate(parent);
}
throw new IllegalStateException("No holder for view type " + viewType);
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
if (holder instanceof BuildViewHolder) {
Build build = getValueAt(position);
((BuildViewHolder) holder).bind(build);
holder.itemView.setTag(R.id.list_position, position);
} else if (holder instanceof LoadingFooterViewHolder) {
((LoadingFooterViewHolder) holder).bind(mLoading);
} else {
throw new IllegalStateException("What is this holder?");
}
}
@Override
public int getItemCount() {
return mValues.size() + FOOTER_COUNT;
}
@Override
public int getItemViewType(int position) {
if (position == mValues.size()) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}
public void setValues(Collection<Build> values) {
mValues.clear();
addValues(values);
}
public void addValues(Collection<Build> values) {
if (values != null) {
mValues.addAll(values);
}
notifyDataSetChanged();
}
public void updateBuild(Build build) {
int indexToDelete = -1;
for (int i=0; i<mValues.size(); i++) {
if (mValues.get(i).getId() == build.getId()) {
indexToDelete = i;
break;
}
}
if (indexToDelete != -1) {
mValues.remove(indexToDelete);
mValues.add(indexToDelete, build);
}
notifyItemChanged(indexToDelete);
}
public Build getValueAt(int position) {
return mValues.get(position);
}
public void setLoading(boolean loading) {
mLoading = loading;
notifyItemChanged(mValues.size());
}
}
Loading
Loading
@@ -6,6 +6,7 @@ import android.support.v4.app.FragmentPagerAdapter;
 
import com.commit451.gitlab.R;
import com.commit451.gitlab.activity.ProjectActivity;
import com.commit451.gitlab.fragment.BuildsFragment;
import com.commit451.gitlab.fragment.CommitsFragment;
import com.commit451.gitlab.fragment.FeedFragment;
import com.commit451.gitlab.fragment.FilesFragment;
Loading
Loading
@@ -13,27 +14,29 @@ import com.commit451.gitlab.fragment.IssuesFragment;
import com.commit451.gitlab.fragment.MilestonesFragment;
import com.commit451.gitlab.fragment.ProjectMembersFragment;
import com.commit451.gitlab.fragment.MergeRequestsFragment;
import com.commit451.gitlab.fragment.OverviewFragment;
import com.commit451.gitlab.fragment.ProjectFragment;
import com.commit451.gitlab.model.api.Project;
 
import java.util.HashSet;
import java.util.Set;
 
import timber.log.Timber;
/**
* Controls the sections that should be shown in a {@link com.commit451.gitlab.activity.ProjectActivity}
* Created by Jawn on 9/20/2015.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
 
private static final int SECTION_COUNT = 8;
private static final int OVERVIEW_POS = 0;
private static final int SECTION_COUNT = 9;
private static final int PROJECT_POS = 0;
private static final int ACTIVITY_POS = 1;
private static final int FILES_POS = 2;
private static final int COMMITS_POS = 3;
private static final int MILESTONES_POS = 4;
private static final int ISSUES_POS = 5;
private static final int MERGE_REQUESTS_POS = 6;
private static final int PROJECT_MEMBERS_POS = 7;
private static final int BUILDS_POS = 4;
private static final int MILESTONES_POS = 5;
private static final int ISSUES_POS = 6;
private static final int MERGE_REQUESTS_POS = 7;
private static final int PROJECT_MEMBERS_POS = 8;
 
private final Project mProject;
private final String[] mTitles;
Loading
Loading
@@ -46,13 +49,20 @@ public class SectionsPagerAdapter extends FragmentPagerAdapter {
mTitles = context.getResources().getStringArray(R.array.main_tabs);
 
Project project = context.getProject();
if (!project.isBuildEnabled()) {
Timber.d("Builds are disabled");
mDisabledSections.add(BUILDS_POS);
}
if (!project.isIssuesEnabled()) {
Timber.d("Issues are disabled");
mDisabledSections.add(ISSUES_POS);
}
if (!project.isMergeRequestsEnabled()) {
Timber.d("Merge requests are disabled");
mDisabledSections.add(MERGE_REQUESTS_POS);
}
if (!project.isIssuesEnabled() && !project.isMergeRequestsEnabled()) {
Timber.d("Milestones are disabled");
mDisabledSections.add(MILESTONES_POS);
}
}
Loading
Loading
@@ -74,14 +84,16 @@ public class SectionsPagerAdapter extends FragmentPagerAdapter {
position = getCorrectPosition(position);
 
switch (position) {
case OVERVIEW_POS:
return OverviewFragment.newInstance();
case PROJECT_POS:
return ProjectFragment.newInstance();
case ACTIVITY_POS:
return FeedFragment.newInstance(mProject.getFeedUrl());
case FILES_POS:
return FilesFragment.newInstance();
case COMMITS_POS:
return CommitsFragment.newInstance();
case BUILDS_POS:
return BuildsFragment.newInstance();
case MILESTONES_POS:
return MilestonesFragment.newInstance();
case ISSUES_POS:
Loading
Loading
Loading
Loading
@@ -2,7 +2,9 @@ package com.commit451.gitlab.api;
 
import android.support.annotation.Nullable;
 
import com.commit451.gitlab.model.api.Artifact;
import com.commit451.gitlab.model.api.Branch;
import com.commit451.gitlab.model.api.Build;
import com.commit451.gitlab.model.api.Contributor;
import com.commit451.gitlab.model.api.Diff;
import com.commit451.gitlab.model.api.Group;
Loading
Loading
@@ -225,7 +227,7 @@ public interface GitLab {
 
@PUT(API_VERSION + "/projects/{id}/merge_requests/{merge_request_id}")
Call<MergeRequest> acceptMergeRequest(@Path("id") long projectId,
@Path("merge_request_id") long mergeRequestId);
@Path("merge_request_id") long mergeRequestId);
 
/* --- ISSUES --- */
 
Loading
Loading
@@ -338,4 +340,29 @@ public interface GitLab {
Call<Label> deleteLabel(@Path("id") long projectId,
@Query("name") String name);
 
/* --- BUILDS --- */
@GET(API_VERSION + "/projects/{id}/builds")
Call<List<Build>> getBuilds(@Path("id") long projectId,
@Query("scope") String scope);
@GET
Call<List<Build>> getBuilds(@Url String url,
@Query("scope") String state);
@POST(API_VERSION + "/projects/{id}/builds/{build_id}/retry")
Call<Build> retryBuild(@Path("id") long projectId,
@Path("build_id") long buildId);
@POST(API_VERSION + "/projects/{id}/builds/{build_id}/erase")
Call<Build> eraseBuild(@Path("id") long projectId,
@Path("build_id") long buildId);
@POST(API_VERSION + "/projects/{id}/builds/{build_id}/cancel")
Call<Build> cancelBuild(@Path("id") long projectId,
@Path("build_id") long buildId);
@GET(API_VERSION + "/projects/{id}/builds/{build_id}/artifacts")
Call<List<Artifact>> getBuildArtifacts(@Path("id") long projectId,
@Path("build_id") long buildId);
}
\ No newline at end of file
package com.commit451.gitlab.event;
import com.commit451.gitlab.model.api.Build;
/**
* A build changed
*/
public class BuildChangedEvent {
public final Build build;
public BuildChangedEvent(Build build) {
this.build = build;
}
}
package com.commit451.gitlab.fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.commit451.gitlab.LabCoatApp;
import com.commit451.gitlab.R;
import com.commit451.gitlab.adapter.BuildArtifactsAdapter;
import com.commit451.gitlab.adapter.DividerItemDecoration;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.event.BuildChangedEvent;
import com.commit451.gitlab.model.api.Artifact;
import com.commit451.gitlab.model.api.Build;
import com.commit451.gitlab.model.api.Project;
import com.squareup.otto.Subscribe;
import org.parceler.Parcels;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import timber.log.Timber;
/**
* Shows the build artifacts
*/
public class BuildArtifactsFragment extends BaseFragment {
private static final String KEY_PROJECT = "project";
private static final String KEY_BUILD = "build";
public static BuildArtifactsFragment newInstance(Project project, Build build) {
BuildArtifactsFragment fragment = new BuildArtifactsFragment();
Bundle args = new Bundle();
args.putParcelable(KEY_PROJECT, Parcels.wrap(project));
args.putParcelable(KEY_BUILD, Parcels.wrap(build));
fragment.setArguments(args);
return fragment;
}
@Bind(R.id.swipe_layout) SwipeRefreshLayout mSwipeRefreshLayout;
@Bind(R.id.list) RecyclerView mCommitsListView;
@Bind(R.id.message_text) TextView mMessageView;
private Project mProject;
private Build mBuild;
private BuildArtifactsAdapter mArtifactsAdapter;
EventReceiver mEventReceiver;
private final EasyCallback<List<Artifact>> mCommitsCallback = new EasyCallback<List<Artifact>>() {
@Override
public void onResponse(@NonNull List<Artifact> response) {
if (getView() == null) {
return;
}
mSwipeRefreshLayout.setRefreshing(false);
if (!response.isEmpty()) {
mMessageView.setVisibility(View.GONE);
} else {
mMessageView.setVisibility(View.VISIBLE);
mMessageView.setText(R.string.no_commits_found);
}
mArtifactsAdapter.setData(response);
}
@Override
public void onAllFailure(Throwable t) {
Timber.e(t, null);
if (getView() == null) {
return;
}
mSwipeRefreshLayout.setRefreshing(false);
mMessageView.setVisibility(View.VISIBLE);
mMessageView.setText(R.string.no_build_artifacts_found);
mArtifactsAdapter.setData(null);
}
};
private final BuildArtifactsAdapter.Listener mAdapterListener = new BuildArtifactsAdapter.Listener() {
@Override
public void onFolderClicked(Artifact treeItem) {
}
@Override
public void onFileClicked(Artifact treeItem) {
}
@Override
public void onCopyClicked(Artifact treeItem) {
}
@Override
public void onShareClicked(Artifact treeItem) {
}
@Override
public void onOpenInBrowserClicked(Artifact treeItem) {
}
};
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mProject = Parcels.unwrap(getArguments().getParcelable(KEY_PROJECT));
mBuild = Parcels.unwrap(getArguments().getParcelable(KEY_BUILD));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_build_artifacts, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
mArtifactsAdapter = new BuildArtifactsAdapter(mAdapterListener);
mCommitsListView.setLayoutManager(new LinearLayoutManager(getActivity()));
mCommitsListView.addItemDecoration(new DividerItemDecoration(getActivity()));
mCommitsListView.setAdapter(mArtifactsAdapter);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
loadData();
}
});
loadData();
mEventReceiver = new EventReceiver();
LabCoatApp.bus().register(mEventReceiver);
}
@Override
public void onDestroyView() {
super.onDestroyView();
LabCoatApp.bus().unregister(mEventReceiver);
ButterKnife.unbind(this);
}
@Override
protected void loadData() {
if (getView() == null) {
return;
}
mSwipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
if (mSwipeRefreshLayout != null) {
mSwipeRefreshLayout.setRefreshing(true);
}
}
});
GitLabClient.instance().getBuildArtifacts(mProject.getId(), mBuild.getId()).enqueue(mCommitsCallback);
}
private class EventReceiver {
@Subscribe
public void onBuildChanged(BuildChangedEvent event) {
if (mBuild.getId() == event.build.getId()) {
mBuild = event.build;
loadData();
}
}
}
}
\ No newline at end of file
package com.commit451.gitlab.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.commit451.gitlab.LabCoatApp;
import com.commit451.gitlab.R;
import com.commit451.gitlab.event.BuildChangedEvent;
import com.commit451.gitlab.model.api.Build;
import com.commit451.gitlab.model.api.Project;
import com.commit451.gitlab.model.api.RepositoryCommit;
import com.commit451.gitlab.model.api.Runner;
import com.commit451.gitlab.util.DateUtils;
import com.squareup.otto.Subscribe;
import org.parceler.Parcels;
import java.util.Date;
import butterknife.Bind;
import butterknife.ButterKnife;
/**
* Shows the details of a build
*/
public class BuildDescriptionFragment extends BaseFragment {
private static final String KEY_PROJECT = "project";
private static final String KEY_BUILD = "build";
public static BuildDescriptionFragment newInstance(Project project, Build build) {
BuildDescriptionFragment fragment = new BuildDescriptionFragment();
Bundle args = new Bundle();
args.putParcelable(KEY_PROJECT, Parcels.wrap(project));
args.putParcelable(KEY_BUILD, Parcels.wrap(build));
fragment.setArguments(args);
return fragment;
}
@Bind(R.id.root)
ViewGroup mRoot;
@Bind(R.id.text_duration)
TextView mTextDuration;
@Bind(R.id.text_created)
TextView mTextCreated;
@Bind(R.id.text_finished)
TextView mTextFinished;
@Bind(R.id.text_runner)
TextView mTextRunner;
@Bind(R.id.text_author)
TextView mTextAuthor;
@Bind(R.id.text_message)
TextView mTextMessage;
Project mProject;
Build mBuild;
EventReceiver mEventReceiver;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mProject = Parcels.unwrap(getArguments().getParcelable(KEY_PROJECT));
mBuild = Parcels.unwrap(getArguments().getParcelable(KEY_BUILD));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_build_description, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
bindBuild(mBuild);
mEventReceiver = new EventReceiver();
LabCoatApp.bus().register(mEventReceiver);
}
private void bindBuild(Build build) {
Date finishedTime = build.getFinishedAt();
if (finishedTime == null) {
finishedTime = new Date();
}
String timeTaken = DateUtils.getTimeTaken(build.getStartedAt(), finishedTime);
String duration = String.format(getString(R.string.build_duration), timeTaken);
mTextDuration.setText(duration);
String created = String.format(getString(R.string.build_created), DateUtils.getRelativeTimeSpanString(getActivity(), build.getCreatedAt()));
mTextCreated.setText(created);
String finished = String.format(getString(R.string.build_finished), DateUtils.getRelativeTimeSpanString(getActivity(), build.getFinishedAt()));
mTextFinished.setText(finished);
bindRunner(build.getRunner());
bindCommit(build.getCommit());
}
private void bindRunner(Runner runner) {
String runnerNum = String.format(getString(R.string.runner_number), String.valueOf(runner.getId()));
mTextRunner.setText(runnerNum);
}
private void bindCommit(RepositoryCommit commit) {
String authorText = String.format(getString(R.string.build_commit_author), commit.getAuthorName());
mTextAuthor.setText(authorText);
String messageText = String.format(getString(R.string.build_commit_message), commit.getMessage());
mTextMessage.setText(messageText);
}
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
LabCoatApp.bus().unregister(mEventReceiver);
}
private class EventReceiver {
@Subscribe
public void onBuildChangedEvent(BuildChangedEvent event) {
if (mBuild.getId() == event.build.getId()) {
mBuild = event.build;
bindBuild(mBuild);
}
}
}
}
package com.commit451.gitlab.fragment;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import com.commit451.gitlab.LabCoatApp;
import com.commit451.gitlab.R;
import com.commit451.gitlab.activity.ProjectActivity;
import com.commit451.gitlab.adapter.BuildsAdapter;
import com.commit451.gitlab.adapter.DividerItemDecoration;
import com.commit451.gitlab.api.EasyCallback;
import com.commit451.gitlab.api.GitLabClient;
import com.commit451.gitlab.event.BuildChangedEvent;
import com.commit451.gitlab.event.ProjectReloadEvent;
import com.commit451.gitlab.model.api.Build;
import com.commit451.gitlab.model.api.Project;
import com.commit451.gitlab.util.NavigationManager;
import com.commit451.gitlab.util.PaginationUtil;
import com.squareup.otto.Subscribe;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import timber.log.Timber;
/**
* Shows the builds of a project
*/
public class BuildsFragment extends BaseFragment {
public static BuildsFragment newInstance() {
return new BuildsFragment();
}
@Bind(R.id.root)
ViewGroup mRoot;
@Bind(R.id.swipe_layout)
SwipeRefreshLayout mSwipeRefreshLayout;
@Bind(R.id.list)
RecyclerView mListBuilds;
@Bind(R.id.message_text)
TextView mMessageView;
@Bind(R.id.issue_spinner)
Spinner mSpinner;
private Project mProject;
private BuildsAdapter mBuildsAdapter;
private LinearLayoutManager mLayoutManagerBuilds;
private EventReceiver mEventReceiver;
String mScope;
private String[] mScopes;
private Uri mNextPageUrl;
private boolean mLoading = false;
private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = mLayoutManagerBuilds.getChildCount();
int totalItemCount = mLayoutManagerBuilds.getItemCount();
int firstVisibleItem = mLayoutManagerBuilds.findFirstVisibleItemPosition();
if (firstVisibleItem + visibleItemCount >= totalItemCount && !mLoading && mNextPageUrl != null) {
loadMore();
}
}
};
private final BuildsAdapter.Listener mAdapterListener = new BuildsAdapter.Listener() {
@Override
public void onBuildClicked(Build build) {
if (mProject != null) {
NavigationManager.navigateToBuild(getActivity(), mProject, build);
} else {
Snackbar.make(mRoot, getString(R.string.wait_for_project_to_load), Snackbar.LENGTH_SHORT)
.show();
}
}
};
private final AdapterView.OnItemSelectedListener mSpinnerItemSelectedListener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mScope = mScopes[position];
loadData();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
};
private final EasyCallback<List<Build>> mLoadCallback = new EasyCallback<List<Build>>() {
@Override
public void onResponse(@NonNull List<Build> response) {
mLoading = false;
if (getView() == null) {
return;
}
mSwipeRefreshLayout.setRefreshing(false);
if (response.isEmpty()) {
mMessageView.setVisibility(View.VISIBLE);
mMessageView.setText(R.string.no_builds);
}
mBuildsAdapter.setValues(response);
mNextPageUrl = PaginationUtil.parse(getResponse()).getNext();
Timber.d("Next page url %s", mNextPageUrl);
}
@Override
public void onAllFailure(Throwable t) {
mLoading = false;
Timber.e(t, null);
if (getView() == null) {
return;
}
mSwipeRefreshLayout.setRefreshing(false);
mMessageView.setVisibility(View.VISIBLE);
mMessageView.setText(R.string.connection_error_issues);
mBuildsAdapter.setValues(null);
mNextPageUrl = null;
}
};
private final EasyCallback<List<Build>> mMoreCallback = new EasyCallback<List<Build>>() {
@Override
public void onResponse(@NonNull List<Build> response) {
mLoading = false;
mBuildsAdapter.setLoading(false);
mNextPageUrl = PaginationUtil.parse(getResponse()).getNext();
mBuildsAdapter.addValues(response);
}
@Override
public void onAllFailure(Throwable t) {
Timber.e(t, null);
mLoading = false;
mBuildsAdapter.setLoading(false);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mScopes = getResources().getStringArray(R.array.build_scope_values);
mScope = mScopes[0];
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_builds, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
mEventReceiver = new EventReceiver();
LabCoatApp.bus().register(mEventReceiver);
mBuildsAdapter = new BuildsAdapter(mAdapterListener);
mLayoutManagerBuilds = new LinearLayoutManager(getActivity());
mListBuilds.setLayoutManager(mLayoutManagerBuilds);
mListBuilds.addItemDecoration(new DividerItemDecoration(getActivity()));
mListBuilds.setAdapter(mBuildsAdapter);
mListBuilds.addOnScrollListener(mOnScrollListener);
mSpinner.setAdapter(new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1,
android.R.id.text1, getResources().getStringArray(R.array.build_scope_names)));
mSpinner.setOnItemSelectedListener(mSpinnerItemSelectedListener);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
loadData();
}
});
if (getActivity() instanceof ProjectActivity) {
mProject = ((ProjectActivity) getActivity()).getProject();
loadData();
} else {
throw new IllegalStateException("Incorrect parent activity");
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
LabCoatApp.bus().unregister(mEventReceiver);
}
@Override
protected void loadData() {
if (getView() == null) {
return;
}
if (mProject == null) {
mSwipeRefreshLayout.setRefreshing(false);
return;
}
mMessageView.setVisibility(View.GONE);
mSwipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
if (mSwipeRefreshLayout != null) {
mSwipeRefreshLayout.setRefreshing(true);
}
}
});
mNextPageUrl = null;
mLoading = true;
GitLabClient.instance().getBuilds(mProject.getId(), mScope).enqueue(mLoadCallback);
}
private void loadMore() {
if (getView() == null) {
return;
}
if (mNextPageUrl == null) {
return;
}
mBuildsAdapter.setLoading(true);
mLoading = true;
Timber.d("loadMore called for %s", mNextPageUrl);
GitLabClient.instance().getBuilds(mNextPageUrl.toString(), mScope).enqueue(mMoreCallback);
}
private class EventReceiver {
@Subscribe
public void onProjectReload(ProjectReloadEvent event) {
mProject = event.mProject;
loadData();
}
@Subscribe
public void onBuildChangedEvent(BuildChangedEvent event) {
mBuildsAdapter.updateBuild(event.build);
}
}
}
\ No newline at end of file
Loading
Loading
@@ -34,10 +34,10 @@ import butterknife.OnClick;
import in.uncod.android.bypass.Bypass;
import timber.log.Timber;
 
public class OverviewFragment extends BaseFragment {
public class ProjectFragment extends BaseFragment {
 
public static OverviewFragment newInstance() {
return new OverviewFragment();
public static ProjectFragment newInstance() {
return new ProjectFragment();
}
 
@Bind(R.id.swipe_layout) SwipeRefreshLayout mSwipeRefreshLayout;
Loading
Loading
@@ -121,7 +121,7 @@ public class OverviewFragment extends BaseFragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_overview, container, false);
return inflater.inflate(R.layout.fragment_project, container, false);
}
 
@Override
Loading
Loading
package com.commit451.gitlab.model.api;
import com.google.gson.annotations.SerializedName;
import org.parceler.Parcel;
/**
* Artifact from a build
*/
@Parcel
public class Artifact {
@SerializedName("name")
String mName;
public String getName() {
return mName;
}
}
package com.commit451.gitlab.model.api;
import com.google.gson.annotations.SerializedName;
import org.parceler.Parcel;
import java.util.Date;
/**
* Represents a build
*/
@Parcel
public class Build {
@SerializedName("commit")
RepositoryCommit mCommit;
@SerializedName("coverage")
String mCoverage;
@SerializedName("created_at")
Date mCreatedAt;
@SerializedName("artifacts_file")
String mArtifactsFile;
@SerializedName("finished_at")
Date mFinishedAt;
@SerializedName("id")
long mId;
@SerializedName("name")
String mName;
@SerializedName("ref")
String mRef;
@SerializedName("runner")
Runner mRunner;
@SerializedName("stage")
String mStage;
@SerializedName("started_at")
Date mStartedAt;
@SerializedName("status")
String mStatus;
@SerializedName("tag")
boolean mTag;
@SerializedName("user")
User mUser;
public RepositoryCommit getCommit() {
return mCommit;
}
public String getCoverage() {
return mCoverage;
}
public Date getCreatedAt() {
return mCreatedAt;
}
public String getArtifactsFile() {
return mArtifactsFile;
}
public Date getFinishedAt() {
return mFinishedAt;
}
public long getId() {
return mId;
}
public String getName() {
return mName;
}
public String getRef() {
return mRef;
}
public Runner getRunner() {
return mRunner;
}
public String getStage() {
return mStage;
}
public Date getStartedAt() {
return mStartedAt;
}
public String getStatus() {
return mStatus;
}
public boolean isTag() {
return mTag;
}
public User getUser() {
return mUser;
}
}
Loading
Loading
@@ -48,7 +48,7 @@ public class Project {
boolean mMergeRequestsEnabled;
@SerializedName("wiki_enabled")
boolean mWikiEnabled;
@SerializedName("build_enabled")
@SerializedName("builds_enabled")
boolean mBuildEnabled;
@SerializedName("snippets_enabled")
boolean mSnippetsEnabled;
Loading
Loading
package com.commit451.gitlab.model.api;
import com.google.gson.annotations.SerializedName;
import org.parceler.Parcel;
/**
* A runner. It runs builds. yeah
*/
@Parcel
public class Runner {
@SerializedName("id")
long mId;
@SerializedName("description")
String mDescription;
@SerializedName("active")
boolean mActive;
@SerializedName("is_shared")
boolean mIsShared;
@SerializedName("name")
String mName;
public long getId() {
return mId;
}
public String getDescription() {
return mDescription;
}
public boolean isActive() {
return mActive;
}
public boolean isShared() {
return mIsShared;
}
public String getName() {
return mName;
}
}
Loading
Loading
@@ -4,6 +4,8 @@ import android.content.Context;
 
import com.commit451.gitlab.R;
 
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
 
/**
Loading
Loading
@@ -12,6 +14,8 @@ import java.util.Date;
*/
public class DateUtils {
 
private static DateFormat FORMATTER = new SimpleDateFormat("HH:mm:ss");
public static CharSequence getRelativeTimeSpanString(Context context, Date startTime) {
Date now = new Date();
if (Math.abs(now.getTime() - startTime.getTime()) < android.text.format.DateUtils.SECOND_IN_MILLIS) {
Loading
Loading
@@ -23,4 +27,9 @@ public class DateUtils {
android.text.format.DateUtils.SECOND_IN_MILLIS)
.toString();
}
public static String getTimeTaken(Date startTime, Date endTime) {
Date timeTaken = new Date(endTime.getTime() - startTime.getTime());
return FORMATTER.format(timeTaken);
}
}
Loading
Loading
@@ -14,6 +14,7 @@ import com.commit451.gitlab.activity.AboutActivity;
import com.commit451.gitlab.activity.AddIssueActivity;
import com.commit451.gitlab.activity.AddMilestoneActivity;
import com.commit451.gitlab.activity.AddUserActivity;
import com.commit451.gitlab.activity.BuildActivity;
import com.commit451.gitlab.activity.DiffActivity;
import com.commit451.gitlab.activity.FileActivity;
import com.commit451.gitlab.activity.GroupActivity;
Loading
Loading
@@ -172,6 +173,11 @@ public class NavigationManager {
startMorphActivity(activity, fab, intent);
}
 
public static void navigateToBuild(Activity activity, Project project, com.commit451.gitlab.model.api.Build build) {
Intent intent = BuildActivity.newInstance(activity, project, build);
activity.startActivity(intent);
}
private static void startMorphActivity(Activity activity, View fab, Intent intent) {
if (Build.VERSION.SDK_INT >= 21 && fab != null) {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation
Loading
Loading
package com.commit451.gitlab.viewHolder;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import com.commit451.gitlab.R;
import com.commit451.gitlab.model.api.Artifact;
import butterknife.Bind;
import butterknife.ButterKnife;
/**
* Files, yay!
*/
public class BuildArtifactViewHolder extends RecyclerView.ViewHolder {
public static BuildArtifactViewHolder inflate(ViewGroup parent) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_build_artifact, parent, false);
return new BuildArtifactViewHolder(view);
}
@Bind(R.id.file_title) TextView mTitleView;
@Bind(R.id.file_image) ImageView mImageView;
@Bind(R.id.file_more) ImageView mMoreView;
public final PopupMenu popupMenu;
public BuildArtifactViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
popupMenu = new PopupMenu(itemView.getContext(), mMoreView);
popupMenu.getMenuInflater().inflate(R.menu.item_menu_file, popupMenu.getMenu());
mMoreView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
popupMenu.show();
}
});
}
public void bind(Artifact artifact) {
mTitleView.setText(artifact.getName());
}
}
package com.commit451.gitlab.viewHolder;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.commit451.gitlab.R;
import com.commit451.gitlab.model.api.Build;
import com.commit451.gitlab.util.DateUtils;
import java.util.Date;
import butterknife.Bind;
import butterknife.ButterKnife;
/**
* Builds, woot
*/
public class BuildViewHolder extends RecyclerView.ViewHolder {
public static BuildViewHolder inflate(ViewGroup parent) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_build, parent, false);
return new BuildViewHolder(view);
}
@Bind(R.id.number) TextView buildNumber;
@Bind(R.id.status) TextView status;
@Bind(R.id.duration) TextView duration;
public BuildViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
public void bind(Build build) {
buildNumber.setText(itemView.getResources().getString(R.string.build_number) + build.getId());
String statusText = String.format(itemView.getResources().getString(R.string.build_status), build.getStatus());
status.setText(statusText);
Date finishedTime = build.getFinishedAt();
if (finishedTime == null) {
finishedTime = new Date();
}
String timeTaken = DateUtils.getTimeTaken(build.getStartedAt(), finishedTime);
String durationStr = String.format(itemView.getResources().getString(R.string.build_duration), timeTaken);
duration.setText(durationStr);
}
}
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