diff --git a/app/build.gradle b/app/build.gradle index fc6e2cd1..e3f67773 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a8ede513..184c4d3b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -141,6 +141,10 @@ android:value=".ui.modules.main.MainView"/> + + editPullRequest(@Path("owner") String owner, @Path("repo") String repo, @Path("number") int number, @Body IssueRequestModel issue); + @PATCH("repos/{owner}/{repo}/issues/{number}") + Observable editIssue(@Path("owner") String owner, @Path("repo") String repo, + @Path("number") int number, + @Body IssueRequestModel issue); } diff --git a/app/src/main/java/com/fastaccess/data/service/RepoService.java b/app/src/main/java/com/fastaccess/data/service/RepoService.java index b194c676..21cd0f80 100644 --- a/app/src/main/java/com/fastaccess/data/service/RepoService.java +++ b/app/src/main/java/com/fastaccess/data/service/RepoService.java @@ -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> getBranches(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo); + @GET("repos/{owner}/{repo}/milestones") + Observable> getMilestones(@Path("owner") String owner, @Path("repo") String repo); + + @POST("repos/{owner}/{repo}/milestones") + Observable createMilestone(@Path("owner") String owner, @Path("repo") String repo, + @Body CreateMilestoneModel create); + + @GET("repos/{owner}/{repo}/assignees") + Observable> getAssignees(@Path("owner") String owner, @Path("repo") String repo); } diff --git a/app/src/main/java/com/fastaccess/helper/ParseDateFormat.java b/app/src/main/java/com/fastaccess/helper/ParseDateFormat.java index f27529b9..206a5ed7 100644 --- a/app/src/main/java/com/fastaccess/helper/ParseDateFormat.java +++ b/app/src/main/java/com/fastaccess/helper/ParseDateFormat.java @@ -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; + } } \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/helper/PrefGetter.java b/app/src/main/java/com/fastaccess/helper/PrefGetter.java index 647f962a..ddb0924a 100644 --- a/app/src/main/java/com/fastaccess/helper/PrefGetter.java +++ b/app/src/main/java/com/fastaccess/helper/PrefGetter.java @@ -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; diff --git a/app/src/main/java/com/fastaccess/provider/tasks/NotificationJobTask.java b/app/src/main/java/com/fastaccess/provider/tasks/NotificationJobTask.java index a6fa6d9f..d55cc305 100644 --- a/app/src/main/java/com/fastaccess/provider/tasks/NotificationJobTask.java +++ b/app/src/main/java/com/fastaccess/provider/tasks/NotificationJobTask.java @@ -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) diff --git a/app/src/main/java/com/fastaccess/ui/adapter/MilestonesAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/MilestonesAdapter.java new file mode 100644 index 00000000..142be747 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/MilestonesAdapter.java @@ -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> { + + public MilestonesAdapter(@NonNull ArrayList 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)); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/MilestonesViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/MilestonesViewHolder.java new file mode 100644 index 00000000..b49bdf84 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/MilestonesViewHolder.java @@ -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 { + + @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())); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/base/BaseDialogFragment.java b/app/src/main/java/com/fastaccess/ui/base/BaseDialogFragment.java index a1caf47e..1d4761ee 100644 --- a/app/src/main/java/com/fastaccess/ui/base/BaseDialogFragment.java +++ b/app/src/main/java/com/fastaccess/ui/base/BaseDialogFragment.java @@ -52,7 +52,6 @@ public abstract class BaseDialogFragment { + void onLoadMilestones(@NonNull String login, @NonNull String repo); + + @NonNull ArrayList getMilestones(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestonePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestonePresenter.java new file mode 100644 index 00000000..9eb08da7 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestonePresenter.java @@ -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 implements MilestoneMvp.Presenter { + private ArrayList 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 getMilestones() { + return milestoneModels; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestoneView.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestoneView.java new file mode 100644 index 00000000..71669221 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestoneView.java @@ -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 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; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneMvp.java new file mode 100644 index 00000000..5f8cbdce --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneMvp.java @@ -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); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestonePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestonePresenter.java new file mode 100644 index 00000000..50777403 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestonePresenter.java @@ -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 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)); + } + }); + } + } + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneView.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneView.java new file mode 100644 index 00000000..21a1be94 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneView.java @@ -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 + 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(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/MilestoneActivityView.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/MilestoneActivityView.java new file mode 100644 index 00000000..70e9c153 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/MilestoneActivityView.java @@ -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(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerMvp.java index 475a9e95..3a3476ff 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerMvp.java +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerMvp.java @@ -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 items); - void onLabelsAdded(); + void onUpdateTimeline(); void onUpdateMenu(); } @@ -57,6 +58,8 @@ interface IssuePagerMvp { void onLoadLabels(); + void onPutMilestones(@NonNull MilestoneModel milestone); + void onPutLabels(@NonNull ArrayList labels); String getLogin(); diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerPresenter.java index 65129540..2cf15a3c 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerPresenter.java +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerPresenter.java @@ -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 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 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); diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerView.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerView.java index 51d5a34f..a087c2b8 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerView.java +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerView.java @@ -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 labels); + void onPutMilestones(@NonNull MilestoneModel milestone); + String getLogin(); String getRepoId(); diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerPresenter.java index 434f4e80..ff085bb0 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerPresenter.java +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerPresenter.java @@ -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 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 }); } + @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())); diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerView.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerView.java index 59b81501..4c8b8605 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerView.java +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerView.java @@ -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 extends BaseDialogFragment implements BaseViewHolder.OnItemClickListener { + 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 extends BaseDialogFragment imp .putParcelableArrayList(BundleConstant.ITEM, objects) .end()); } + + public void initArguments(@NonNull String title, @NonNull List objects) { + setArguments(Bundler.start() + .put(BundleConstant.EXTRA, title) + .putParcelableArrayList(BundleConstant.ITEM, (ArrayList) objects) + .end()); + } } diff --git a/app/src/main/res/layouts/main_layouts/layout-land/repo_file_header_layout.xml b/app/src/main/res/layouts/main_layouts/layout-land/repo_file_header_layout.xml index 2fd7c299..b666eaa7 100644 --- a/app/src/main/res/layouts/main_layouts/layout-land/repo_file_header_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout-land/repo_file_header_layout.xml @@ -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"/> diff --git a/app/src/main/res/layouts/main_layouts/layout-large/repo_file_header_layout.xml b/app/src/main/res/layouts/main_layouts/layout-large/repo_file_header_layout.xml index 2fd7c299..b666eaa7 100644 --- a/app/src/main/res/layouts/main_layouts/layout-large/repo_file_header_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout-large/repo_file_header_layout.xml @@ -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"/> diff --git a/app/src/main/res/layouts/main_layouts/layout/create_milestone_layout.xml b/app/src/main/res/layouts/main_layouts/layout/create_milestone_layout.xml new file mode 100644 index 00000000..00e89992 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/create_milestone_layout.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/milestone_dialog_layout.xml b/app/src/main/res/layouts/main_layouts/layout/milestone_dialog_layout.xml new file mode 100644 index 00000000..0a2d8abf --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/milestone_dialog_layout.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/repo_file_header_layout.xml b/app/src/main/res/layouts/main_layouts/layout/repo_file_header_layout.xml index ad5e1dea..37f525e6 100644 --- a/app/src/main/res/layouts/main_layouts/layout/repo_file_header_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout/repo_file_header_layout.xml @@ -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"/> diff --git a/app/src/main/res/layouts/other_layouts/layout/simple_footer_list_dialog.xml b/app/src/main/res/layouts/other_layouts/layout/simple_footer_list_dialog.xml index 1c86c82a..a20c724e 100644 --- a/app/src/main/res/layouts/other_layouts/layout/simple_footer_list_dialog.xml +++ b/app/src/main/res/layouts/other_layouts/layout/simple_footer_list_dialog.xml @@ -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" diff --git a/app/src/main/res/layouts/other_layouts/layout/single_container_layout.xml b/app/src/main/res/layouts/other_layouts/layout/single_container_layout.xml new file mode 100644 index 00000000..a115ab83 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/single_container_layout.xml @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/app/src/main/res/menu/add_menu.xml b/app/src/main/res/menu/add_menu.xml new file mode 100644 index 00000000..8c0e9adf --- /dev/null +++ b/app/src/main/res/menu/add_menu.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index a0482748..5c9e5510 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -6,10 +6,12 @@ + @string/turn_off @string/one_minute @string/five_minutes @string/ten_minutes @string/twenty_minutes @string/thirty_minutes + Turn Off \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 34182ca1..5a724480 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -219,4 +219,11 @@ Edit Update Issue Update Pull Request + No Milestones + Add + Done + Home + Create Milestone + Error creating milestone + Due On diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index e63522e3..849a25e8 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -22,6 +22,7 @@ true @color/transparent true + @style/DialogTheme + +