adding milestone to issues & pull request as well as creating milestone from FastHub #13

This commit is contained in:
Kosh 2017-03-05 03:23:04 +08:00
parent a4699cbef3
commit 818b6d7fd6
36 changed files with 830 additions and 30 deletions

View File

@ -116,6 +116,7 @@ dependencies {
compile 'com.commonsware.cwac:anddown:0.3.0'
compile 'com.github.GrenderG:Toasty:1.1.3'
compile 'uk.co.samuelwall:material-tap-target-prompt:1.9.2'
compile 'com.github.k0shk0sh:RetainedDateTimePickers:1.0.2'
apt 'org.projectlombok:lombok:1.12.6'
apt 'frankiesardo:icepick-processor:3.1.0'
apt 'com.jakewharton:butterknife-compiler:8.4.0'

View File

@ -141,6 +141,10 @@
android:value=".ui.modules.main.MainView"/>
</activity>
<activity
android:name=".ui.modules.repos.extras.milestone.create.MilestoneActivityView"
android:theme="@style/WhenLargeTheme"/>
<activity
android:name=".ui.modules.parser.LinksParserActivity"
android:configChanges="keyboard|orientation|screenSize"

View File

@ -0,0 +1,18 @@
package com.fastaccess.data.dao;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* Created by Kosh on 05 Mar 2017, 2:30 AM
*/
@Getter @Setter @NoArgsConstructor
public class CreateMilestoneModel {
private String title;
private String description;
@SerializedName("due_one") private String dueOn;
}

View File

@ -53,4 +53,8 @@ public interface PullRequestService {
Observable<PullRequestModel> editPullRequest(@Path("owner") String owner, @Path("repo") String repo,
@Path("number") int number,
@Body IssueRequestModel issue);
@PATCH("repos/{owner}/{repo}/issues/{number}")
Observable<PullRequestModel> editIssue(@Path("owner") String owner, @Path("repo") String repo,
@Path("number") int number,
@Body IssueRequestModel issue);
}

View File

@ -6,8 +6,10 @@ import com.fastaccess.data.dao.BranchesModel;
import com.fastaccess.data.dao.CommentRequestModel;
import com.fastaccess.data.dao.CommentsModel;
import com.fastaccess.data.dao.CommitModel;
import com.fastaccess.data.dao.CreateMilestoneModel;
import com.fastaccess.data.dao.LabelModel;
import com.fastaccess.data.dao.MarkdownModel;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.data.dao.Pageable;
import com.fastaccess.data.dao.ReleasesModel;
import com.fastaccess.data.dao.RepoFilesModel;
@ -110,4 +112,13 @@ public interface RepoService {
@GET("repos/{owner}/{repo}/branches")
Observable<Pageable<BranchesModel>> getBranches(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo);
@GET("repos/{owner}/{repo}/milestones")
Observable<Pageable<MilestoneModel>> getMilestones(@Path("owner") String owner, @Path("repo") String repo);
@POST("repos/{owner}/{repo}/milestones")
Observable<MilestoneModel> createMilestone(@Path("owner") String owner, @Path("repo") String repo,
@Body CreateMilestoneModel create);
@GET("repos/{owner}/{repo}/assignees")
Observable<Pageable<UserModel>> getAssignees(@Path("owner") String owner, @Path("repo") String repo);
}

View File

@ -1,9 +1,11 @@
package com.fastaccess.helper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.format.DateUtils;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
@ -43,4 +45,22 @@ public class ParseDateFormat {
}
return "N/A";
}
public static String toGithubDate(@NonNull Date date) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
return simpleDateFormat.format(date);
}
public static String prettifyDate(long timestamp) {
return new SimpleDateFormat("dd-MM-yyyy", Locale.US).format(new Date(timestamp));
}
@Nullable public static Date getDateFromString(@NonNull String date) {
try {
return new SimpleDateFormat("dd-MM-yyyy", Locale.US).parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -92,6 +92,8 @@ public class PrefGetter {
return 5 * 60;
} else if (s.equals(context.getString(R.string.one_minute))) {
return 60;
} else if (s.equals(context.getString(R.string.turn_off))) {
return -1;
}
}
return 0;

View File

@ -55,13 +55,17 @@ public class NotificationJobTask extends JobService {
}
public static void scheduleJob(@NonNull Context context) {
scheduleJob(context, PrefGetter.getNotificationTaskDuration(context) == 0 ? (30 * 60) : PrefGetter.getNotificationTaskDuration(context),
false);
int duration = PrefGetter.getNotificationTaskDuration(context);
scheduleJob(context, duration == 0 ? (30 * 60) : duration, false);
}
public static void scheduleJob(@NonNull Context context, int duration, boolean cancel) {
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
if (cancel) dispatcher.cancel(EVERY_30_MINS);
if (duration == -1) {
dispatcher.cancel(EVERY_30_MINS);
return;
}
Job.Builder builder = dispatcher
.newJobBuilder()
.setTag(EVERY_30_MINS)

View File

@ -0,0 +1,31 @@
package com.fastaccess.ui.adapter;
import android.support.annotation.NonNull;
import android.view.ViewGroup;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.ui.adapter.viewholder.MilestonesViewHolder;
import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter;
import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder;
import java.util.ArrayList;
/**
* Created by Kosh on 11 Nov 2016, 2:07 PM
*/
public class MilestonesAdapter extends BaseRecyclerAdapter<MilestoneModel, MilestonesViewHolder,
BaseViewHolder.OnItemClickListener<MilestoneModel>> {
public MilestonesAdapter(@NonNull ArrayList<MilestoneModel> eventsModels) {
super(eventsModels);
}
@Override protected MilestonesViewHolder viewHolder(ViewGroup parent, int viewType) {
return MilestonesViewHolder.newInstance(parent, this);
}
@Override protected void onBindView(MilestonesViewHolder holder, int position) {
holder.bind(getItem(position));
}
}

View File

@ -0,0 +1,44 @@
package com.fastaccess.ui.adapter.viewholder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.ViewGroup;
import com.fastaccess.R;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.helper.ParseDateFormat;
import com.fastaccess.ui.widgets.FontTextView;
import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter;
import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder;
import butterknife.BindView;
/**
* Created by Kosh on 11 Nov 2016, 2:08 PM
*/
public class MilestonesViewHolder extends BaseViewHolder<MilestoneModel> {
@BindView(R.id.title) FontTextView title;
@BindView(R.id.date) FontTextView date;
@BindView(R.id.notificationTitle) FontTextView notificationTitle;
private MilestonesViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) {
super(itemView, adapter);
}
public static MilestonesViewHolder newInstance(@NonNull ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter) {
return new MilestonesViewHolder(getView(viewGroup, R.layout.notifications_row_item), adapter);
}
@Override public void bind(@NonNull MilestoneModel milestoneModel) {
title.setText(milestoneModel.getTitle());
notificationTitle.setText(milestoneModel.getDescription());
if (milestoneModel.getDueOn() != null) {
date.setText(ParseDateFormat.getTimeAgo(milestoneModel.getDueOn()));
} else {
date.setText(ParseDateFormat.getTimeAgo(milestoneModel.getCreatedAt()));
}
}
}

View File

@ -52,7 +52,6 @@ public abstract class BaseDialogFragment<V extends BaseMvp.FAView, P extends Bas
@Override public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_TITLE, 0);
if (savedInstanceState != null && !savedInstanceState.isEmpty()) {
Icepick.restoreInstanceState(this, savedInstanceState);
}

View File

@ -0,0 +1,34 @@
package com.fastaccess.ui.modules.repos.extras.milestone;
import android.support.annotation.NonNull;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.ui.base.mvp.BaseMvp;
import com.fastaccess.ui.modules.repos.extras.milestone.create.CreateMilestoneMvp;
import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder;
import java.util.ArrayList;
/**
* Created by Kosh on 04 Mar 2017, 9:38 PM
*/
public interface MilestoneMvp {
interface OnMilestoneSelected {
void onMilestoneSelected(@NonNull MilestoneModel milestoneModel);
}
interface View extends BaseMvp.FAView, CreateMilestoneMvp.OnMilestoneAdded {
void onNotifyAdapter();
void onMilestoneSelected(@NonNull MilestoneModel milestoneModel);
}
interface Presenter extends BaseViewHolder.OnItemClickListener<MilestoneModel> {
void onLoadMilestones(@NonNull String login, @NonNull String repo);
@NonNull ArrayList<MilestoneModel> getMilestones();
}
}

View File

@ -0,0 +1,46 @@
package com.fastaccess.ui.modules.repos.extras.milestone;
import android.support.annotation.NonNull;
import android.view.View;
import com.fastaccess.R;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.provider.rest.RestProvider;
import com.fastaccess.ui.base.mvp.presenter.BasePresenter;
import java.util.ArrayList;
/**
* Created by Kosh on 04 Mar 2017, 9:41 PM
*/
public class MilestonePresenter extends BasePresenter<MilestoneMvp.View> implements MilestoneMvp.Presenter {
private ArrayList<MilestoneModel> milestoneModels = new ArrayList<>();
@Override public void onItemClick(int position, View v, MilestoneModel item) {
if (getView() != null) getView().onMilestoneSelected(item);
}
@Override public void onItemLongClick(int position, View v, MilestoneModel item) {
onItemClick(position, v, item);
}
@Override public void onLoadMilestones(@NonNull String login, @NonNull String repo) {
makeRestCall(RestProvider.getRepoService().getMilestones(login, repo),
response -> {
if (response == null || response.getItems() == null || response.getItems().isEmpty()) {
sendToView(view -> view.showMessage(R.string.error, R.string.no_milestones));
return;
}
if (response.getItems() != null) {
milestoneModels.clear();
milestoneModels.addAll(response.getItems());
sendToView(MilestoneMvp.View::onNotifyAdapter);
}
});
}
@NonNull @Override public ArrayList<MilestoneModel> getMilestones() {
return milestoneModels;
}
}

View File

@ -0,0 +1,131 @@
package com.fastaccess.ui.modules.repos.extras.milestone;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.design.widget.AppBarLayout;
import android.support.v7.widget.Toolbar;
import android.view.View;
import com.fastaccess.R;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.helper.BundleConstant;
import com.fastaccess.helper.Bundler;
import com.fastaccess.ui.adapter.MilestonesAdapter;
import com.fastaccess.ui.base.BaseFragment;
import com.fastaccess.ui.modules.repos.extras.milestone.create.CreateMilestoneView;
import com.fastaccess.ui.widgets.AppbarRefreshLayout;
import com.fastaccess.ui.widgets.StateLayout;
import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView;
import butterknife.BindView;
/**
* Created by Kosh on 04 Mar 2017, 9:45 PM
*/
public class MilestoneView extends BaseFragment<MilestoneMvp.View, MilestonePresenter> implements MilestoneMvp.View {
public static final String TAG = MilestoneView.class.getSimpleName();
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.toolbarShadow) View toolbarShadow;
@BindView(R.id.appbar) AppBarLayout appbar;
@BindView(R.id.recycler) DynamicRecyclerView recycler;
@BindView(R.id.refresh) AppbarRefreshLayout refresh;
@BindView(R.id.stateLayout) StateLayout stateLayout;
private MilestonesAdapter adapter;
private MilestoneMvp.OnMilestoneSelected onMilestoneSelected;
public static MilestoneView newInstance(@NonNull String login, @NonNull String repo) {
MilestoneView fragment = new MilestoneView();
fragment.setArguments(Bundler.start()
.put(BundleConstant.EXTRA, login)
.put(BundleConstant.ID, repo)
.end());
return fragment;
}
@Override public void onAttach(Context context) {
super.onAttach(context);
if (getParentFragment() != null && getParentFragment() instanceof MilestoneMvp.OnMilestoneSelected) {
onMilestoneSelected = (MilestoneMvp.OnMilestoneSelected) getParentFragment();
} else if (context instanceof MilestoneMvp.OnMilestoneSelected) {
onMilestoneSelected = (MilestoneMvp.OnMilestoneSelected) context;
} else {
throw new IllegalArgumentException(context.getClass().getSimpleName() + " must implement onMilestoneSelected");
}
}
@Override public void onDetach() {
onMilestoneSelected = null;
super.onDetach();
}
@Override public void onNotifyAdapter() {
hideProgress();
adapter.notifyDataSetChanged();
}
@Override public void onMilestoneSelected(@NonNull MilestoneModel milestoneModel) {
onMilestoneSelected.onMilestoneSelected(milestoneModel);
}
@Override protected int fragmentLayout() {
return R.layout.milestone_dialog_layout;
}
@Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
if (getArguments() == null) {
return;
}
String login = getArguments().getString(BundleConstant.EXTRA);
String repo = getArguments().getString(BundleConstant.ID);
if (login == null || repo == null) {
return;
}
toolbar.setTitle(R.string.milestone);
toolbar.setOnMenuItemClickListener(item -> onAddMilestone());
toolbar.inflateMenu(R.menu.add_menu);
adapter = new MilestonesAdapter(getPresenter().getMilestones());
adapter.setListener(getPresenter());
recycler.setEmptyView(stateLayout, refresh);
recycler.setAdapter(adapter);
if (savedInstanceState == null || (getPresenter().getMilestones().isEmpty() && !getPresenter().isApiCalled())) {
getPresenter().onLoadMilestones(login, repo);
}
stateLayout.setOnReloadListener(v -> getPresenter().onLoadMilestones(login, repo));
refresh.setOnRefreshListener(() -> getPresenter().onLoadMilestones(login, repo));
}
@Override public void showProgress(@StringRes int resId) {
stateLayout.showProgress();
}
@Override public void hideProgress() {
refresh.setRefreshing(false);
stateLayout.hideProgress();
}
@Override public void showErrorMessage(@NonNull String msgRes) {
hideProgress();
stateLayout.showReload(adapter.getItemCount());
super.showErrorMessage(msgRes);
}
@NonNull @Override public MilestonePresenter providePresenter() {
return new MilestonePresenter();
}
@Override public void onMilestoneAdded(@NonNull MilestoneModel milestoneModel) {
adapter.addItem(milestoneModel, 0);
}
private boolean onAddMilestone() {
//noinspection ConstantConditions
CreateMilestoneView.newInstance(getArguments().getString(BundleConstant.EXTRA), getArguments().getString(BundleConstant.ID))
.show(getChildFragmentManager(), CreateMilestoneView.TAG);
return true;
}
}

View File

@ -0,0 +1,29 @@
package com.fastaccess.ui.modules.repos.extras.milestone.create;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.ui.base.mvp.BaseMvp;
/**
* Created by Kosh on 04 Mar 2017, 10:47 PM
*/
public interface CreateMilestoneMvp {
interface OnMilestoneAdded {
void onMilestoneAdded(@NonNull MilestoneModel milestoneModel);
}
interface View extends BaseMvp.FAView {
void onShowTitleError(boolean isError);
void onMilestoneAdded(@NonNull MilestoneModel milestoneModel);
}
interface Presenter {
void onSubmit(@Nullable String title, @Nullable String dueOn,
@NonNull String login, @NonNull String repo);
}
}

View File

@ -0,0 +1,43 @@
package com.fastaccess.ui.modules.repos.extras.milestone.create;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.fastaccess.R;
import com.fastaccess.data.dao.CreateMilestoneModel;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.ParseDateFormat;
import com.fastaccess.provider.rest.RestProvider;
import com.fastaccess.ui.base.mvp.presenter.BasePresenter;
import java.util.Date;
/**
* Created by Kosh on 04 Mar 2017, 10:49 PM
*/
public class CreateMilestonePresenter extends BasePresenter<CreateMilestoneMvp.View> implements CreateMilestoneMvp.Presenter {
@Override public void onSubmit(@Nullable String title, @Nullable String dueOn,
@NonNull String login, @NonNull String repo) {
if (getView() != null) {
boolean isEmptyTitle = InputHelper.isEmpty(title);
getView().onShowTitleError(isEmptyTitle);
if (!isEmptyTitle) {
CreateMilestoneModel createMilestoneModel = new CreateMilestoneModel();
createMilestoneModel.setTitle(title);
if (!InputHelper.isEmpty(dueOn)) {
Date date = ParseDateFormat.getDateFromString(dueOn);
if (date != null) createMilestoneModel.setDueOn(ParseDateFormat.toGithubDate(date));
}
makeRestCall(RestProvider.getRepoService().createMilestone(login, repo, createMilestoneModel),
milestoneModel -> {
if (milestoneModel != null) {
sendToView(view -> view.onMilestoneAdded(milestoneModel));
} else {
sendToView(view -> view.showMessage(R.string.error, R.string.error_creating_milestone));
}
});
}
}
}
}

View File

@ -0,0 +1,110 @@
package com.fastaccess.ui.modules.repos.extras.milestone.create;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
import android.support.v7.widget.Toolbar;
import android.view.MotionEvent;
import android.view.View;
import com.fastaccess.R;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.datetimepicker.DatePickerFragmentDialog;
import com.fastaccess.datetimepicker.callback.DatePickerCallback;
import com.fastaccess.helper.BundleConstant;
import com.fastaccess.helper.Bundler;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.ParseDateFormat;
import com.fastaccess.ui.base.BaseDialogFragment;
import butterknife.BindView;
import butterknife.OnTouch;
/**
* Created by Kosh on 04 Mar 2017, 10:40 PM
*/
public class CreateMilestoneView extends BaseDialogFragment<CreateMilestoneMvp.View, CreateMilestonePresenter>
implements CreateMilestoneMvp.View, DatePickerCallback {
public static final String TAG = CreateMilestoneView.class.getSimpleName();
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.title) TextInputLayout title;
@BindView(R.id.dueOnEditText) TextInputEditText dueOnEditText;
private CreateMilestoneMvp.OnMilestoneAdded onMilestoneAdded;
public static CreateMilestoneView newInstance(@NonNull String login, @NonNull String repo) {
CreateMilestoneView fragment = new CreateMilestoneView();
fragment.setArguments(Bundler.start()
.put(BundleConstant.EXTRA, login)
.put(BundleConstant.ID, repo)
.end());
return fragment;
}
@Override public void onAttach(Context context) {
super.onAttach(context);
if (getParentFragment() instanceof CreateMilestoneMvp.OnMilestoneAdded) {
onMilestoneAdded = (CreateMilestoneMvp.OnMilestoneAdded) getParentFragment();
} else {
onMilestoneAdded = (CreateMilestoneMvp.OnMilestoneAdded) context;
}
}
@Override public void onDetach() {
onMilestoneAdded = null;
super.onDetach();
}
@Override protected int fragmentLayout() {
return R.layout.create_milestone_layout;
}
@Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
String login = getArguments().getString(BundleConstant.EXTRA);
String repo = getArguments().getString(BundleConstant.ID);
if (login == null || repo == null) {
dismiss();
return;
}
toolbar.setTitle(R.string.create_milestone);
toolbar.setNavigationIcon(R.drawable.ic_back);
toolbar.inflateMenu(R.menu.add_menu);
toolbar.setOnMenuItemClickListener(item -> {
getPresenter().onSubmit(InputHelper.toString(title), InputHelper.toString(dueOnEditText), login, repo);
return true;
});
}
@NonNull @Override public CreateMilestonePresenter providePresenter() {
return new CreateMilestonePresenter();
}
@OnTouch(R.id.dueOnEditText) boolean onTouch(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
DatePickerFragmentDialog.newInstance().show(getChildFragmentManager(), "DatePickerFragmentDialog");
}
return false;
}
@Override public void onDateSet(long date) {
if (date > 0) {
dueOnEditText.setText(ParseDateFormat.prettifyDate(date));
}
}
@Override public void onShowTitleError(boolean isError) {
title.setError(isError ? getString(R.string.required_field) : null);
}
@Override public void onMilestoneAdded(@NonNull MilestoneModel milestoneModel) {
hideProgress();
onMilestoneAdded.onMilestoneAdded(milestoneModel);
dismiss();
}
}

View File

@ -0,0 +1,76 @@
package com.fastaccess.ui.modules.repos.extras.milestone.create;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.fastaccess.R;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.helper.BundleConstant;
import com.fastaccess.helper.Bundler;
import com.fastaccess.ui.base.BaseActivity;
import com.fastaccess.ui.base.mvp.presenter.BasePresenter;
import com.fastaccess.ui.modules.repos.extras.milestone.MilestoneMvp;
import com.fastaccess.ui.modules.repos.extras.milestone.MilestoneView;
import net.grandcentrix.thirtyinch.TiPresenter;
/**
* Created by Kosh on 04 Mar 2017, 10:58 PM
*/
public class MilestoneActivityView extends BaseActivity implements MilestoneMvp.OnMilestoneSelected {
public static final int CREATE_MILESTONE_RQ = 200;
public static void startActivity(@NonNull Activity activity, @NonNull String login, @NonNull String repo) {
Intent intent = new Intent(activity, MilestoneActivityView.class);
intent.putExtras(Bundler.start()
.put(BundleConstant.EXTRA, login)
.put(BundleConstant.ID, repo)
.end());
activity.startActivityForResult(intent, CREATE_MILESTONE_RQ);
}
@Override protected int layout() {
return R.layout.single_container_layout;
}
@Override protected boolean isTransparent() {
return false;
}
@Override protected boolean canBack() {
return true;
}
@Override protected boolean isSecured() {
return false;
}
@NonNull @Override public TiPresenter providePresenter() {
return new BasePresenter();
}
@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
Bundle bundle = getIntent().getExtras();
MilestoneView milestoneView = new MilestoneView();
milestoneView.setArguments(bundle);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.singleContainer, milestoneView, MilestoneView.TAG)
.commit();
}
}
@Override public void onMilestoneSelected(@NonNull MilestoneModel milestoneModel) {
Intent intent = new Intent();
intent.putExtras(Bundler.start().put(BundleConstant.ITEM, milestoneModel).end());
setResult(RESULT_OK, intent);
finish();
}
}

View File

@ -7,6 +7,7 @@ import android.support.annotation.Nullable;
import com.fastaccess.data.dao.IssueModel;
import com.fastaccess.data.dao.LabelModel;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.ui.base.mvp.BaseMvp;
import com.fastaccess.ui.modules.repos.labels.LabelsMvp;
@ -28,7 +29,7 @@ interface IssuePagerMvp {
void onLabelsRetrieved(@NonNull List<LabelModel> items);
void onLabelsAdded();
void onUpdateTimeline();
void onUpdateMenu();
}
@ -57,6 +58,8 @@ interface IssuePagerMvp {
void onLoadLabels();
void onPutMilestones(@NonNull MilestoneModel milestone);
void onPutLabels(@NonNull ArrayList<LabelModel> labels);
String getLogin();

View File

@ -14,6 +14,7 @@ import com.fastaccess.data.dao.IssueRequestModel;
import com.fastaccess.data.dao.LabelListModel;
import com.fastaccess.data.dao.LabelModel;
import com.fastaccess.data.dao.LoginModel;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.data.dao.PullsIssuesParser;
import com.fastaccess.data.dao.UserModel;
import com.fastaccess.data.dao.types.IssueState;
@ -191,12 +192,26 @@ class IssuePagerPresenter extends BasePresenter<IssuePagerMvp.View> implements I
);
}
@Override public void onPutMilestones(@NonNull MilestoneModel milestone) {
issueModel.setMilestone(milestone);
IssueRequestModel issueRequestModel = IssueRequestModel.clone(issueModel, false);
makeRestCall(RestProvider.getIssueService().editIssue(login, repoId, issueNumber, issueRequestModel),
issue -> {
this.issueModel = issue;
issueModel.setLogin(login);
issueModel.setRepoId(repoId);
manageSubscription(issue.save().subscribe());
sendToView(IssuePagerMvp.View::onUpdateTimeline);
});
}
@Override public void onPutLabels(@NonNull ArrayList<LabelModel> labels) {
makeRestCall(RestProvider.getIssueService().putLabels(login, repoId, issueNumber,
Stream.of(labels).filter(value -> value != null && value.getName() != null)
.map(LabelModel::getName).collect(Collectors.toList())),
labelModels -> {
sendToView(IssuePagerMvp.View::onLabelsAdded);
sendToView(IssuePagerMvp.View::onUpdateTimeline);
LabelListModel listModel = new LabelListModel();
listModel.addAll(labels);
issueModel.setLabels(listModel);

View File

@ -16,6 +16,7 @@ import com.fastaccess.R;
import com.fastaccess.data.dao.FragmentPagerAdapterModel;
import com.fastaccess.data.dao.IssueModel;
import com.fastaccess.data.dao.LabelModel;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.data.dao.UserModel;
import com.fastaccess.data.dao.types.IssueState;
import com.fastaccess.helper.ActivityHelper;
@ -26,6 +27,7 @@ import com.fastaccess.helper.Logger;
import com.fastaccess.helper.ParseDateFormat;
import com.fastaccess.ui.adapter.FragmentsPagerAdapter;
import com.fastaccess.ui.base.BaseActivity;
import com.fastaccess.ui.modules.repos.extras.milestone.create.MilestoneActivityView;
import com.fastaccess.ui.modules.repos.issues.create.CreateIssueView;
import com.fastaccess.ui.modules.repos.issues.issue.details.comments.IssueCommentsView;
import com.fastaccess.ui.modules.repos.issues.issue.details.events.IssueDetailsView;
@ -118,11 +120,17 @@ public class IssuePagerView extends BaseActivity<IssuePagerMvp.View, IssuePagerP
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == BundleConstant.REQUEST_CODE) {
if (data != null) {
if (resultCode == RESULT_OK && data != null) {
if (requestCode == BundleConstant.REQUEST_CODE) {
Bundle bundle = data.getExtras();
IssueModel issueModel = bundle.getParcelable(BundleConstant.ITEM);
if (issueModel != null) getPresenter().onUpdateIssue(issueModel);
} else if (requestCode == MilestoneActivityView.CREATE_MILESTONE_RQ) {
Bundle bundle = data.getExtras();
MilestoneModel milestoneModel = bundle.getParcelable(BundleConstant.ITEM);
if (milestoneModel != null) {
getPresenter().onPutMilestones(milestoneModel);
}
}
}
}
@ -160,6 +168,8 @@ public class IssuePagerView extends BaseActivity<IssuePagerMvp.View, IssuePagerP
} else if (item.getItemId() == R.id.edit) {
CreateIssueView.startForResult(this, getPresenter().getLogin(), getPresenter().getRepoId(), getPresenter().getIssue());
return true;
} else if (item.getItemId() == R.id.milestone) {
MilestoneActivityView.startActivity(this, getPresenter().getLogin(), getPresenter().getRepoId());
}
return super.onOptionsItemSelected(item);
}
@ -257,7 +267,7 @@ public class IssuePagerView extends BaseActivity<IssuePagerMvp.View, IssuePagerP
.show(getSupportFragmentManager(), "LabelsView");
}
@Override public void onLabelsAdded() {
@Override public void onUpdateTimeline() {
showMessage(R.string.success, R.string.labels_added_successfully);
IssueDetailsView issueDetailsView = (IssueDetailsView) pager.getAdapter().instantiateItem(pager, 0);
if (issueDetailsView != null) {

View File

@ -7,6 +7,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.fastaccess.data.dao.LabelModel;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.data.dao.PullRequestModel;
import com.fastaccess.ui.base.mvp.BaseMvp;
import com.fastaccess.ui.modules.repos.labels.LabelsMvp;
@ -21,7 +22,8 @@ import java.util.List;
interface PullRequestPagerMvp {
interface View extends BaseMvp.FAView, LabelsMvp.SelectedLabelsListener {
interface
View extends BaseMvp.FAView, LabelsMvp.SelectedLabelsListener {
void onSetupIssue();
@ -33,7 +35,7 @@ interface PullRequestPagerMvp {
void showErrorIssueActionMsg(boolean isClose);
void onLabelsAdded();
void onUpdateTimeline();
}
interface Presenter extends BaseMvp.FAPresenter {
@ -66,6 +68,8 @@ interface PullRequestPagerMvp {
void onPutLabels(@NonNull ArrayList<LabelModel> labels);
void onPutMilestones(@NonNull MilestoneModel milestone);
String getLogin();
String getRepoId();

View File

@ -15,6 +15,7 @@ import com.fastaccess.data.dao.LabelListModel;
import com.fastaccess.data.dao.LabelModel;
import com.fastaccess.data.dao.LoginModel;
import com.fastaccess.data.dao.MergeRequestModel;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.data.dao.PullRequestModel;
import com.fastaccess.data.dao.PullsIssuesParser;
import com.fastaccess.data.dao.UserModel;
@ -195,7 +196,7 @@ class PullRequestPagerPresenter extends BasePresenter<PullRequestPagerMvp.View>
Stream.of(labels).filter(value -> value != null && value.getName() != null)
.map(LabelModel::getName).collect(Collectors.toList())),
labelModels -> {
sendToView(PullRequestPagerMvp.View::onLabelsAdded);
sendToView(PullRequestPagerMvp.View::onUpdateTimeline);
LabelListModel listModel = new LabelListModel();
listModel.addAll(labels);
pullRequest.setLabels(listModel);
@ -203,8 +204,22 @@ class PullRequestPagerPresenter extends BasePresenter<PullRequestPagerMvp.View>
});
}
@Override public void onPutMilestones(@NonNull MilestoneModel milestone) {
pullRequest.setMilestone(milestone);
IssueRequestModel issueRequestModel = IssueRequestModel.clone(pullRequest, false);
makeRestCall(RestProvider.getPullRequestSerice().editIssue(login, repoId, issueNumber, issueRequestModel),
pr -> {
this.pullRequest = pr;
pullRequest.setLogin(login);
pullRequest.setRepoId(repoId);
manageSubscription(pr.save().subscribe());
sendToView(PullRequestPagerMvp.View::onUpdateTimeline);
});
}
@Override public void onMerge() {
if (isMergeable() && (isOwner() || isRepoOwner())) {//double the checking
if (isMergeable() && (isCollaborator() || isRepoOwner())) {//double the checking
MergeRequestModel mergeRequestModel = new MergeRequestModel();
// mergeRequestModel.setBase(String.valueOf(getPullRequest().getBase().getId()));
// mergeRequestModel.setHead(String.valueOf(getPullRequest().getHead().getId()));

View File

@ -14,8 +14,8 @@ import android.view.View;
import com.fastaccess.R;
import com.fastaccess.data.dao.FragmentPagerAdapterModel;
import com.fastaccess.data.dao.IssueModel;
import com.fastaccess.data.dao.LabelModel;
import com.fastaccess.data.dao.MilestoneModel;
import com.fastaccess.data.dao.PullRequestModel;
import com.fastaccess.data.dao.UserModel;
import com.fastaccess.data.dao.types.IssueState;
@ -26,6 +26,7 @@ import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.Logger;
import com.fastaccess.ui.adapter.FragmentsPagerAdapter;
import com.fastaccess.ui.base.BaseActivity;
import com.fastaccess.ui.modules.repos.extras.milestone.create.MilestoneActivityView;
import com.fastaccess.ui.modules.repos.issues.create.CreateIssueView;
import com.fastaccess.ui.modules.repos.issues.issue.details.comments.IssueCommentsView;
import com.fastaccess.ui.modules.repos.labels.LabelsView;
@ -116,11 +117,17 @@ public class PullRequestPagerView extends BaseActivity<PullRequestPagerMvp.View,
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == BundleConstant.REQUEST_CODE) {
if (data != null) {
if (resultCode == RESULT_OK && data != null) {
if (requestCode == BundleConstant.REQUEST_CODE) {
Bundle bundle = data.getExtras();
PullRequestModel pullRequestModel = bundle.getParcelable(BundleConstant.ITEM);
if (pullRequestModel != null) getPresenter().onUpdatePullRequest(pullRequestModel);
PullRequestModel pullRequest = bundle.getParcelable(BundleConstant.ITEM);
if (pullRequest != null) getPresenter().onUpdatePullRequest(pullRequest);
} else if (requestCode == MilestoneActivityView.CREATE_MILESTONE_RQ) {
Bundle bundle = data.getExtras();
MilestoneModel milestoneModel = bundle.getParcelable(BundleConstant.ITEM);
if (milestoneModel != null) {
getPresenter().onPutMilestones(milestoneModel);
}
}
}
}
@ -156,6 +163,8 @@ public class PullRequestPagerView extends BaseActivity<PullRequestPagerMvp.View,
} else if (item.getItemId() == R.id.edit) {
CreateIssueView.startForResult(this, getPresenter().getLogin(), getPresenter().getRepoId(), getPresenter().getPullRequest());
return true;
} else if (item.getItemId() == R.id.milestone) {
MilestoneActivityView.startActivity(this, getPresenter().getLogin(), getPresenter().getRepoId());
}
return super.onOptionsItemSelected(item);
}
@ -178,19 +187,15 @@ public class PullRequestPagerView extends BaseActivity<PullRequestPagerMvp.View,
assignees.setVisible(isCollaborator || isRepoOwner);
edit.setVisible(isCollaborator || isRepoOwner || isOwner);
if (getPresenter().getPullRequest() != null) {
closeIssue.setVisible((isOwner || isCollaborator) && getPresenter().getPullRequest().getState() == IssueState.open);
lockIssue.setVisible((isOwner || isCollaborator) && getPresenter().getPullRequest().getState() == IssueState.open);
closeIssue.setVisible(isRepoOwner || (isOwner || isCollaborator) && getPresenter().getPullRequest().getState() == IssueState.open);
lockIssue.setVisible(isRepoOwner || (isOwner || isCollaborator) && getPresenter().getPullRequest().getState() == IssueState.open);
closeIssue.setTitle(getPresenter().getPullRequest().getState() == IssueState.closed
? getString(R.string.re_open) : getString(R.string.close));
lockIssue.setTitle(isLocked ? getString(R.string.unlock_issue) : getString(R.string.lock_issue));
} else {
closeIssue.setVisible(false);
lockIssue.setVisible(false);
}
if (isOwner) {
//noinspection ConstantConditions ( getIssue at this stage is not null but AS doesn't know. )
closeIssue.setTitle(getPresenter().getPullRequest().getState() == IssueState.closed
? getString(R.string.re_open) : getString(R.string.close));
lockIssue.setTitle(isLocked ? getString(R.string.unlock_issue) : getString(R.string.lock_issue));
}
return super.onPrepareOptionsMenu(menu);
}
@ -267,7 +272,7 @@ public class PullRequestPagerView extends BaseActivity<PullRequestPagerMvp.View,
}
}
@Override public void onLabelsAdded() {
@Override public void onUpdateTimeline() {
showMessage(R.string.success, R.string.labels_added_successfully);
PullRequestDetailsView pullRequestDetailsView = (PullRequestDetailsView) pager.getAdapter().instantiateItem(pager, 0);
if (pullRequestDetailsView != null) {

View File

@ -20,6 +20,7 @@ import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView;
import net.grandcentrix.thirtyinch.TiPresenter;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
@ -29,6 +30,8 @@ import butterknife.BindView;
public class ListDialogView<O extends Parcelable> extends BaseDialogFragment implements BaseViewHolder.OnItemClickListener<O> {
public static final String TAG = ListDialogView.class.getSimpleName();
@BindView(R.id.title) FontTextView title;
@BindView(R.id.recycler) DynamicRecyclerView recycler;
@ -89,4 +92,11 @@ public class ListDialogView<O extends Parcelable> extends BaseDialogFragment imp
.putParcelableArrayList(BundleConstant.ITEM, objects)
.end());
}
public void initArguments(@NonNull String title, @NonNull List<O> objects) {
setArguments(Bundler.start()
.put(BundleConstant.EXTRA, title)
.putParcelableArrayList(BundleConstant.ITEM, (ArrayList<? extends Parcelable>) objects)
.end());
}
}

View File

@ -25,7 +25,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/switch_branch"
android:contentDescription="@string/home"
android:padding="@dimen/spacing_normal"
android:src="@drawable/ic_home"/>

View File

@ -25,7 +25,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/switch_branch"
android:contentDescription="@string/home"
android:padding="@dimen/spacing_normal"
android:src="@drawable/ic_home"/>

View File

@ -0,0 +1,76 @@
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="@dimen/spacing_xs_large">
<include layout="@layout/appbar_elevation_dark"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/spacing_xs_large">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/spacing_xs_large"
app:contentPadding="@dimen/spacing_xs_large">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintTextAppearance="@style/TextAppearance.AppCompat.Title">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/title"
android:maxLines="1"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/spacing_xs_large"
app:contentPadding="@dimen/spacing_xs_large">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:id="@+id/dueOn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintTextAppearance="@style/TextAppearance.AppCompat.Title">
<android.support.design.widget.TextInputEditText
android:id="@+id/dueOnEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:hint="@string/due_on"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/appbar_elevation_dark"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/scroll_behavior">
<include layout="@layout/vertical_refresh_list"/>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>

View File

@ -23,7 +23,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/switch_branch"
android:contentDescription="@string/home"
android:padding="@dimen/spacing_normal"
android:src="@drawable/ic_home"/>

View File

@ -25,6 +25,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/back"
android:foreground="?selectableItemBackgroundBorderless"
android:padding="@dimen/spacing_normal"
android:scaleType="centerCrop"
@ -46,6 +47,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/done"
android:foreground="?selectableItemBackgroundBorderless"
android:padding="@dimen/spacing_normal"
android:scaleType="centerCrop"

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/singleContainer"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/add"
android:icon="@drawable/ic_add"
android:title="@string/add"
app:showAsAction="ifRoom"/>
</menu>

View File

@ -6,10 +6,12 @@
</string-array>
<string-array name="notification_duration">
<item>@string/turn_off</item>
<item>@string/one_minute</item>
<item>@string/five_minutes</item>
<item>@string/ten_minutes</item>
<item>@string/twenty_minutes</item>
<item>@string/thirty_minutes</item>
</string-array>
<string name="turn_off">Turn Off</string>
</resources>

View File

@ -219,4 +219,11 @@
<string name="edit">Edit</string>
<string name="update_issue">Update Issue</string>
<string name="update_pull_request">Update Pull Request</string>
<string name="no_milestones">No Milestones</string>
<string name="add">Add</string>
<string name="done">Done</string>
<string name="home">Home</string>
<string name="create_milestone">Create Milestone</string>
<string name="error_creating_milestone">Error creating milestone</string>
<string name="due_on">Due On</string>
</resources>

View File

@ -22,6 +22,7 @@
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:windowContentTransitions">true</item>
<item name="android:dialogTheme">@style/DialogTheme</item>
</style>
<style name="WhenLargeTheme.Base" parent="Theme.AppCompat.Light.DialogWhenLarge">
@ -43,6 +44,14 @@
<item name="android:windowContentTransitions">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:dialogTheme">@style/DialogTheme</item>
</style>
<style name="DialogTheme" parent="Theme.AppCompat.Light.Dialog">
<item name="android:windowBackground">@color/windowBackground</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowCloseOnTouchOutside">false</item>
</style>
<style name="Transparent_Activity" parent="Theme.AppCompat.Light.Dialog">