From 4bc9bda3c5ce7d9745ac22b480f34b301e09fe11 Mon Sep 17 00:00:00 2001 From: k0shk0sh Date: Sat, 16 Sep 2017 19:59:42 +0200 Subject: [PATCH] this commit fixes #384 and fixes #981 --- .../main/graphql/github/RepoProject.graphql | 2 + .../data/dao/FragmentPagerAdapterModel.java | 21 ++- .../fastaccess/data/dao/ProjectCardModel.java | 12 +- .../data/dao/ProjectColumnModel.java | 23 +++- .../data/dao/PullsIssuesParser.java | 77 ++++++++--- .../data/service/ProjectsService.kt | 30 ++++- .../ui/adapter/FragmentsPagerAdapter.java | 13 ++ .../viewholder/ColumnCardViewHolder.kt | 21 ++- .../PullRequestFilesViewHolder.java | 10 +- .../com/fastaccess/ui/base/BaseActivity.java | 4 +- .../create/dialog/AddGistBottomSheetDialog.kt | 8 +- .../projects/columns/ProjectColumnFragment.kt | 112 +++++++++++++++- .../projects/columns/ProjectColumnMvp.kt | 17 ++- .../columns/ProjectColumnPresenter.kt | 125 +++++++++++++++++- .../crud/ProjectCurdDialogFragment.kt | 120 +++++++++++++++++ .../projects/details/ProjectPagerActivity.kt | 19 ++- .../repos/projects/details/ProjectPagerMvp.kt | 6 +- .../projects/details/ProjectPagerPresenter.kt | 4 +- .../projects/list/RepoProjectPresenter.kt | 6 +- .../ui/widgets/dialog/MessageDialogView.java | 7 + .../recyclerview/BaseRecyclerAdapter.java | 6 +- .../edit_project_column_note_layout.xml | 45 +++++++ .../layout/column_card_row_layout.xml | 4 +- app/src/main/res/menu/project_card_menu.xml | 31 +++++ app/src/main/res/values/strings.xml | 3 +- 25 files changed, 662 insertions(+), 64 deletions(-) create mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/projects/crud/ProjectCurdDialogFragment.kt create mode 100644 app/src/main/res/layouts/main_layouts/layout/edit_project_column_note_layout.xml create mode 100644 app/src/main/res/menu/project_card_menu.xml diff --git a/app/src/main/graphql/github/RepoProject.graphql b/app/src/main/graphql/github/RepoProject.graphql index 15b895db..87e951d1 100644 --- a/app/src/main/graphql/github/RepoProject.graphql +++ b/app/src/main/graphql/github/RepoProject.graphql @@ -15,6 +15,7 @@ repository(owner: $owner, name: $name) { columns(first: 1) { totalCount } + databaseId } } } @@ -36,6 +37,7 @@ repository(owner: $owner, name: $name) { columns(first: 1) { totalCount } + databaseId } } } diff --git a/app/src/main/java/com/fastaccess/data/dao/FragmentPagerAdapterModel.java b/app/src/main/java/com/fastaccess/data/dao/FragmentPagerAdapterModel.java index 0e3d4c02..98099390 100644 --- a/app/src/main/java/com/fastaccess/data/dao/FragmentPagerAdapterModel.java +++ b/app/src/main/java/com/fastaccess/data/dao/FragmentPagerAdapterModel.java @@ -69,10 +69,16 @@ import lombok.Setter; String title; Fragment fragment; + String key; private FragmentPagerAdapterModel(String title, Fragment fragment) { + this(title, fragment, null); + } + + public FragmentPagerAdapterModel(String title, Fragment fragment, String key) { this.title = title; this.fragment = fragment; + this.key = key; } @NonNull public static List buildForProfile(@NonNull Context context, @NonNull String login) { @@ -245,7 +251,20 @@ import lombok.Setter; @NonNull public static List buildForProjectColumns(@NonNull List models, boolean isCollaborator) { return Stream.of(models) .map(projectColumnModel -> new FragmentPagerAdapterModel("", ProjectColumnFragment.Companion - .newInstance(projectColumnModel, isCollaborator))) + .newInstance(projectColumnModel, isCollaborator), String.valueOf(projectColumnModel.getId()))) .toList(); } + + @Override public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FragmentPagerAdapterModel that = (FragmentPagerAdapterModel) o; + + return key != null ? key.equals(that.key) : that.key == null; + } + + @Override public int hashCode() { + return key != null ? key.hashCode() : 0; + } } diff --git a/app/src/main/java/com/fastaccess/data/dao/ProjectCardModel.java b/app/src/main/java/com/fastaccess/data/dao/ProjectCardModel.java index 4f0fba75..0a5ec2fd 100644 --- a/app/src/main/java/com/fastaccess/data/dao/ProjectCardModel.java +++ b/app/src/main/java/com/fastaccess/data/dao/ProjectCardModel.java @@ -15,7 +15,7 @@ public class ProjectCardModel implements Parcelable { private String url; private String columnUrl; private String contentUrl; - private int id; + private Integer id; private String note; private User creator; private Date createdAt; @@ -85,26 +85,26 @@ public class ProjectCardModel implements Parcelable { this.updatedAt = updatedAt; } + public ProjectCardModel() {} + @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.url); dest.writeString(this.columnUrl); dest.writeString(this.contentUrl); - dest.writeInt(this.id); + dest.writeValue(this.id); dest.writeString(this.note); dest.writeParcelable(this.creator, flags); dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); } - public ProjectCardModel() {} - protected ProjectCardModel(Parcel in) { this.url = in.readString(); this.columnUrl = in.readString(); this.contentUrl = in.readString(); - this.id = in.readInt(); + this.id = (Integer) in.readValue(Integer.class.getClassLoader()); this.note = in.readString(); this.creator = in.readParcelable(User.class.getClassLoader()); long tmpCreatedAt = in.readLong(); @@ -113,7 +113,7 @@ public class ProjectCardModel implements Parcelable { this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); } - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public static final Creator CREATOR = new Creator() { @Override public ProjectCardModel createFromParcel(Parcel source) {return new ProjectCardModel(source);} @Override public ProjectCardModel[] newArray(int size) {return new ProjectCardModel[size];} diff --git a/app/src/main/java/com/fastaccess/data/dao/ProjectColumnModel.java b/app/src/main/java/com/fastaccess/data/dao/ProjectColumnModel.java index e2492024..c7f3515b 100644 --- a/app/src/main/java/com/fastaccess/data/dao/ProjectColumnModel.java +++ b/app/src/main/java/com/fastaccess/data/dao/ProjectColumnModel.java @@ -11,7 +11,7 @@ import java.util.Date; public class ProjectColumnModel implements Parcelable { - private long id; + private Long id; private String name; private String url; private String projectUrl; @@ -75,10 +75,12 @@ public class ProjectColumnModel implements Parcelable { this.updatedAt = updatedAt; } + public ProjectColumnModel() {} + @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); + dest.writeValue(this.id); dest.writeString(this.name); dest.writeString(this.url); dest.writeString(this.projectUrl); @@ -87,10 +89,8 @@ public class ProjectColumnModel implements Parcelable { dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); } - public ProjectColumnModel() {} - protected ProjectColumnModel(Parcel in) { - this.id = in.readLong(); + this.id = (Long) in.readValue(Long.class.getClassLoader()); this.name = in.readString(); this.url = in.readString(); this.projectUrl = in.readString(); @@ -106,4 +106,17 @@ public class ProjectColumnModel implements Parcelable { @Override public ProjectColumnModel[] newArray(int size) {return new ProjectColumnModel[size];} }; + + @Override public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ProjectColumnModel that = (ProjectColumnModel) o; + + return id != null ? id.equals(that.id) : that.id == null; + } + + @Override public int hashCode() { + return id != null ? id.hashCode() : 0; + } } diff --git a/app/src/main/java/com/fastaccess/data/dao/PullsIssuesParser.java b/app/src/main/java/com/fastaccess/data/dao/PullsIssuesParser.java index 6fae554b..59333a99 100644 --- a/app/src/main/java/com/fastaccess/data/dao/PullsIssuesParser.java +++ b/app/src/main/java/com/fastaccess/data/dao/PullsIssuesParser.java @@ -9,14 +9,10 @@ import com.fastaccess.helper.InputHelper; import java.util.List; -import lombok.Getter; -import lombok.Setter; - /** * Created by Kosh on 17 Dec 2016, 12:17 AM */ -@Getter @Setter public class PullsIssuesParser implements Parcelable { private String login; @@ -26,11 +22,23 @@ public class PullsIssuesParser implements Parcelable { public static PullsIssuesParser getForPullRequest(@NonNull String url) { Uri uri = Uri.parse(url); List segments = uri.getPathSegments(); - if (segments == null || segments.size() < 4) return null; - if (!"pull".equals(segments.get(2))) return null; - String owner = segments.get(0); - String repo = segments.get(1); - String number = segments.get(3); + if (segments == null || segments.size() < 3) return null; + String owner = null; + String repo = null; + String number = null; + if (segments.size() > 3) { + if (("pull".equals(segments.get(2)) || "pulls".equals(segments.get(2)))) { + owner = segments.get(0); + repo = segments.get(1); + number = segments.get(3); + } else if (("pull".equals(segments.get(3)) || "pulls".equals(segments.get(3))) && segments.size() > 4) { + owner = segments.get(1); + repo = segments.get(2); + number = segments.get(4); + } else { + return null; + } + } if (InputHelper.isEmpty(number)) return null; int issueNumber; try { @@ -38,6 +46,7 @@ public class PullsIssuesParser implements Parcelable { } catch (NumberFormatException nfe) { return null; } + if (issueNumber < 1) return null; PullsIssuesParser model = new PullsIssuesParser(); model.setLogin(owner); model.setRepoId(repo); @@ -48,18 +57,32 @@ public class PullsIssuesParser implements Parcelable { public static PullsIssuesParser getForIssue(@NonNull String url) { Uri uri = Uri.parse(url); List segments = uri.getPathSegments(); - if (segments == null || segments.size() < 4) return null; - if (!"issues".equals(segments.get(2))) return null; - String owner = segments.get(0); - String repo = segments.get(1); - String number = segments.get(3); - if (InputHelper.isEmpty(number)) return null; + if (segments == null || segments.size() < 3) return null; + String owner = null; + String repo = null; + String number = null; + if (segments.size() > 3) { + if (segments.get(2).equalsIgnoreCase("issues")) { + owner = segments.get(0); + repo = segments.get(1); + number = segments.get(3); + } else if (segments.get(3).equalsIgnoreCase("issues") && segments.size() > 4) { + owner = segments.get(1); + repo = segments.get(2); + number = segments.get(4); + } else { + return null; + } + } + if (InputHelper.isEmpty(number)) + return null; int issueNumber; try { issueNumber = Integer.parseInt(number); } catch (NumberFormatException nfe) { return null; } + if (issueNumber < 1) return null; PullsIssuesParser model = new PullsIssuesParser(); model.setLogin(owner); model.setRepoId(repo); @@ -83,6 +106,30 @@ public class PullsIssuesParser implements Parcelable { dest.writeInt(this.number); } + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getRepoId() { + return repoId; + } + + public void setRepoId(String repoId) { + this.repoId = repoId; + } + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + public PullsIssuesParser() {} protected PullsIssuesParser(Parcel in) { diff --git a/app/src/main/java/com/fastaccess/data/service/ProjectsService.kt b/app/src/main/java/com/fastaccess/data/service/ProjectsService.kt index 53231ea5..61eb1168 100644 --- a/app/src/main/java/com/fastaccess/data/service/ProjectsService.kt +++ b/app/src/main/java/com/fastaccess/data/service/ProjectsService.kt @@ -5,10 +5,8 @@ import com.fastaccess.data.dao.ProjectCardModel import com.fastaccess.data.dao.ProjectColumnModel import com.fastaccess.data.dao.ProjectsModel import io.reactivex.Observable -import retrofit2.http.GET -import retrofit2.http.Headers -import retrofit2.http.Path -import retrofit2.http.Query +import retrofit2.Response +import retrofit2.http.* /** * Created by kosh on 09/09/2017. @@ -33,4 +31,28 @@ interface ProjectsService { @GET("projects/columns/{columnId}/cards") @Headers("Accept: application/vnd.github.inertia-preview+json") fun getProjectCards(@Path("columnId") columnId: Long, @Query("page") page: Int): Observable> + + @POST("projects/columns/{projectId}") + @Headers("Accept: application/vnd.github.inertia-preview+json") + fun createColumn(@Path("projectId") projectId: Long, @Body card: ProjectColumnModel): Observable + + @PATCH("projects/columns/{projectId}") + @Headers("Accept: application/vnd.github.inertia-preview+json") + fun updateColumn(@Path("projectId") projectId: Long, @Body card: ProjectColumnModel): Observable + + @DELETE("projects/columns/{projectId}") + @Headers("Accept: application/vnd.github.inertia-preview+json") + fun deleteColumn(@Path("projectId") projectId: Long): Observable> + + @POST("/projects/columns/{columnId}/cards") + @Headers("Accept: application/vnd.github.inertia-preview+json") + fun createCard(@Path("columnId") columnId: Long, @Body card: ProjectCardModel): Observable + + @PATCH("projects/columns/cards/{cardId}") + @Headers("Accept: application/vnd.github.inertia-preview+json") + fun updateCard(@Path("cardId") cardId: Long, @Body card: ProjectCardModel): Observable + + @DELETE("projects/columns/cards/{cardId}") + @Headers("Accept: application/vnd.github.inertia-preview+json") + fun deleteCard(@Path("cardId") cardId: Long): Observable> } \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/FragmentsPagerAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/FragmentsPagerAdapter.java index 519936c3..18595d22 100644 --- a/app/src/main/java/com/fastaccess/ui/adapter/FragmentsPagerAdapter.java +++ b/app/src/main/java/com/fastaccess/ui/adapter/FragmentsPagerAdapter.java @@ -37,4 +37,17 @@ public class FragmentsPagerAdapter extends FragmentStatePagerAdapter { return super.getPageWidth(position); } + public void remove(FragmentPagerAdapterModel model) { + if (fragments != null) { + fragments.remove(model); + notifyDataSetChanged(); + } + } + + public void remove(int position) { + if (fragments != null) { + fragments.remove(position); + notifyDataSetChanged(); + } + } } diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ColumnCardViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ColumnCardViewHolder.kt index d568f237..6ea18f17 100644 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ColumnCardViewHolder.kt +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ColumnCardViewHolder.kt @@ -6,6 +6,8 @@ import android.widget.TextView import butterknife.BindView import com.fastaccess.R import com.fastaccess.data.dao.ProjectCardModel +import com.fastaccess.data.dao.PullsIssuesParser +import com.fastaccess.helper.ParseDateFormat import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder @@ -24,9 +26,22 @@ class ColumnCardViewHolder private constructor(item: View, adapter: BaseRecycler } override fun bind(t: ProjectCardModel) { - title.text = t.note - addedBy.text = itemView.context.getString(R.string.card_added_by, t.creator?.login) - editCard.visibility = if (isOwner) View.VISIBLE else View.GONE + title.text = if (t.note.isNullOrBlank()) { + val issue = PullsIssuesParser.getForIssue(t.contentUrl) + if (issue != null) { + "${issue.login}/${issue.repoId}/${issue.number}" + } else { + val pr = PullsIssuesParser.getForPullRequest(t.contentUrl) + if (pr != null) { + "${pr.login}/${pr.repoId}/${pr.number}" + } else { + "(FastHub) - to be fixed by GitHub! Sorry!" + } + } + } else { + t.note + } + addedBy.text = itemView.context.getString(R.string.card_added_by, t.creator?.login, ParseDateFormat.getTimeAgo(t.createdAt)) } companion object { diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestFilesViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestFilesViewHolder.java index ecd59869..2b0077f8 100644 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestFilesViewHolder.java +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestFilesViewHolder.java @@ -20,6 +20,7 @@ import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; import butterknife.BindString; import butterknife.BindView; +import es.dmoral.toasty.Toasty; /** * Created by Kosh on 15 Feb 2017, 10:29 PM @@ -104,8 +105,13 @@ public class PullRequestFilesViewHolder extends BaseViewHolder addFileListener = parentFragment as AddGistFileListener - context is AddGistFileListener -> addFileListener = context + addFileListener = when { + parentFragment is AddGistFileListener -> parentFragment as AddGistFileListener + context is AddGistFileListener -> context else -> throw NullPointerException("${context::class.java.simpleName} most implement AddGistFileListener") } } @@ -53,7 +53,7 @@ class AddGistBottomSheetDialog : BaseDialogFragment? = null private val adapter by lazy { ColumnCardAdapter(presenter.getCards(), isOwner()) } + private var pageCallback: ProjectPagerMvp.DeletePageListener? = null - @OnClick(R.id.editColumn) fun onEditColumn() {} - @OnClick(R.id.deleteColumn) fun onDeleteColumn() {} - @OnClick(R.id.addCard) fun onAddCard() {} + override fun onAttach(context: Context?) { + super.onAttach(context) + pageCallback = when { + parentFragment is ProjectPagerMvp.DeletePageListener -> parentFragment as ProjectPagerMvp.DeletePageListener + context is ProjectPagerMvp.DeletePageListener -> context + else -> null + } + } + + override fun onDetach() { + pageCallback = null + super.onDetach() + } + + @OnClick(R.id.editColumn) fun onEditColumn() { + ProjectCurdDialogFragment.newInstance(getColumn().name) + .show(childFragmentManager, ProjectCurdDialogFragment.TAG) + } + + @OnClick(R.id.deleteColumn) fun onDeleteColumn() { + MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), + false, MessageDialogView.getYesNoBundle(context)) + .show(childFragmentManager, MessageDialogView.TAG) + } + + @OnClick(R.id.addCard) fun onAddCard() { + ProjectCurdDialogFragment.newInstance(isCard = true) + .show(childFragmentManager, ProjectCurdDialogFragment.TAG) + } override fun onNotifyAdapter(items: List?, page: Int) { hideProgress() @@ -111,6 +143,78 @@ class ProjectColumnFragment : BaseFragment?, page: Int) fun getLoadMore(): OnLoadMore + fun deleteColumn() + fun showBlockingProgress() + fun hideBlockingProgress() + fun isOwner(): Boolean + fun onDeleteCard(position: Int) + fun onEditCard(note: String?, position: Int) + fun addCard(it: ProjectCardModel) + fun updateCard(response: ProjectCardModel, position: Int) + fun onRemoveCard(position: Int) } interface Presenter : BaseViewHolder.OnItemClickListener, BaseMvp.PaginationListener { fun getCards(): ArrayList + fun onEditOrDeleteColumn(text: String? = null, column: ProjectColumnModel) + fun onDeleteCard(position: Int, card: ProjectCardModel) + fun createCard(text: String, columnId: Long) + fun editCard(text: String, card: ProjectCardModel, position: Int) } } \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnPresenter.kt index 9fca8046..ef67ccb8 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnPresenter.kt +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnPresenter.kt @@ -1,9 +1,16 @@ package com.fastaccess.ui.modules.repos.projects.columns import android.view.View +import android.widget.PopupMenu +import com.fastaccess.R import com.fastaccess.data.dao.ProjectCardModel +import com.fastaccess.data.dao.ProjectColumnModel +import com.fastaccess.helper.ActivityHelper +import com.fastaccess.helper.AppHelper import com.fastaccess.helper.Logger +import com.fastaccess.helper.RxHelper import com.fastaccess.provider.rest.RestProvider +import com.fastaccess.provider.scheme.SchemeParser import com.fastaccess.ui.base.mvp.presenter.BasePresenter import java.util.* @@ -13,13 +20,41 @@ import java.util.* class ProjectColumnPresenter : BasePresenter(), ProjectColumnMvp.Presenter { - private val projects = ArrayList() private var page: Int = 0 private var previousTotal: Int = 0 private var lastPage = Integer.MAX_VALUE - override fun onItemClick(position: Int, v: View?, item: ProjectCardModel?) {} + override fun onItemClick(position: Int, v: View, item: ProjectCardModel) { + if (v.id == R.id.editCard) { + view?.let { + val popupMenu = PopupMenu(v.context, v) + popupMenu.inflate(R.menu.project_card_menu) + popupMenu.menu.findItem(R.id.share).isVisible = !item.contentUrl.isNullOrBlank() + popupMenu.menu.findItem(R.id.copy).isVisible = !item.contentUrl.isNullOrBlank() + popupMenu.menu.findItem(R.id.edit).isVisible = it.isOwner() && item.note.isNullOrBlank() + popupMenu.menu.findItem(R.id.delete).isVisible = it.isOwner() && item.note.isNullOrBlank() + popupMenu.setOnMenuItemClickListener { + when (it.itemId) { + R.id.edit -> sendToView { it.onEditCard(item.note, position) } + R.id.delete -> sendToView { it.onDeleteCard(position) } + R.id.share -> if (!item.contentUrl.isNullOrBlank()) { + ActivityHelper.shareUrl(v.context, item.contentUrl) + } + R.id.copy -> if (!item.contentUrl.isNullOrBlank()) { + AppHelper.copyToClipboard(v.context, item.contentUrl) + } + } + return@setOnMenuItemClickListener true + } + popupMenu.show() + } + } else { + if (!item.contentUrl.isNullOrBlank()) { + SchemeParser.launchUri(v.context, item.contentUrl) + } + } + } override fun onItemLongClick(position: Int, v: View?, item: ProjectCardModel?) {} @@ -56,4 +91,90 @@ class ProjectColumnPresenter : BasePresenter(), ProjectCo return true } + override fun onEditOrDeleteColumn(text: String?, column: ProjectColumnModel) { + if (text.isNullOrBlank()) { + manageDisposable(RxHelper.getObservable(RestProvider.getProjectsService(isEnterprise).deleteColumn(column.id)) + .doOnSubscribe { + showBlockingProgress() + } + .subscribe({ + if (it.code() == 204) { + sendToView { it.deleteColumn() } + } else { + sendToView { it.showMessage(R.string.error, R.string.network_error) } + } + }, { + hideBlockingProgress() + onError(it) + })) + } else { + val body = ProjectColumnModel() + body.name = text + manageDisposable(RxHelper.getObservable(RestProvider.getProjectsService(isEnterprise).updateColumn(column.id, body)) + .doOnSubscribe { + showBlockingProgress() + } + .subscribe({ + hideBlockingProgress() + }, { + hideBlockingProgress() + onError(it) + })) + } + } + + override fun onDeleteCard(position: Int, card: ProjectCardModel) { + manageDisposable(RxHelper.getObservable(RestProvider.getProjectsService(isEnterprise).deleteCard(card.id.toLong())) + .doOnSubscribe { + showBlockingProgress() + } + .subscribe({ + if (it.code() == 204) { + sendToView { it.onRemoveCard(position) } + } else { + sendToView { it.showMessage(R.string.error, R.string.network_error) } + } + }, { + hideBlockingProgress() + onError(it) + })) + } + + override fun createCard(text: String, columnId: Long) { + val body = ProjectCardModel() + body.note = text + manageDisposable(RxHelper.getObservable(RestProvider.getProjectsService(isEnterprise).createCard(columnId, body)) + .doOnSubscribe { + showBlockingProgress() + } + .subscribe({ response -> + sendToView { it.addCard(response) } + }, { + hideBlockingProgress() + onError(it) + })) + } + + override fun editCard(text: String, card: ProjectCardModel, position: Int) { + val body = ProjectCardModel() + body.note = text + manageDisposable(RxHelper.getObservable(RestProvider.getProjectsService(isEnterprise).updateCard(card.id.toLong(), body)) + .doOnSubscribe { + showBlockingProgress() + } + .subscribe({ response -> + sendToView { it.updateCard(response, position) } + }, { + hideBlockingProgress() + onError(it) + })) + } + + private fun showBlockingProgress() { + sendToView({ v -> v.showBlockingProgress() }) + } + + private fun hideBlockingProgress() { + sendToView({ v -> v.hideBlockingProgress() }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/crud/ProjectCurdDialogFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/crud/ProjectCurdDialogFragment.kt new file mode 100644 index 00000000..dffd7cf5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/crud/ProjectCurdDialogFragment.kt @@ -0,0 +1,120 @@ +package com.fastaccess.ui.modules.repos.projects.crud + +import android.annotation.SuppressLint +import android.content.Context +import android.os.Bundle +import android.support.v4.app.FragmentManager +import android.support.v7.widget.Toolbar +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.EditText +import butterknife.BindView +import com.fastaccess.R +import com.fastaccess.helper.BundleConstant +import com.fastaccess.helper.Bundler +import com.fastaccess.helper.InputHelper +import com.fastaccess.provider.emoji.Emoji +import com.fastaccess.ui.base.BaseDialogFragment +import com.fastaccess.ui.base.mvp.BaseMvp +import com.fastaccess.ui.base.mvp.presenter.BasePresenter +import com.fastaccess.ui.modules.editor.emoji.EmojiMvp +import com.fastaccess.ui.modules.editor.popup.EditorLinkImageMvp +import com.fastaccess.ui.widgets.markdown.MarkDownLayout +import com.fastaccess.ui.widgets.markdown.MarkdownEditText + +/** + * Created by Hashemsergani on 15.09.17. + */ + +class ProjectCurdDialogFragment : BaseDialogFragment>(), + EditorLinkImageMvp.EditorLinkCallback, MarkDownLayout.MarkdownListener, EmojiMvp.EmojiCallback { + + @BindView(R.id.editText) lateinit var editText: MarkdownEditText + @BindView(R.id.toolbar) lateinit var toolbar: Toolbar + @BindView(R.id.markDownLayout) lateinit var markDownLayout: MarkDownLayout + + private var onProjectEditedCallback: OnProjectEditedCallback? = null + + override fun onAttach(context: Context) { + super.onAttach(context) + onProjectEditedCallback = when { + parentFragment is OnProjectEditedCallback -> parentFragment as OnProjectEditedCallback + context is OnProjectEditedCallback -> context + else -> throw NullPointerException("${context::class.java.simpleName} most implement OnProjectEditedCallback") + } + } + + override fun onDetach() { + onProjectEditedCallback = null + super.onDetach() + } + + override fun fragmentLayout(): Int = R.layout.edit_project_column_note_layout + + override fun providePresenter(): BasePresenter = BasePresenter() + + override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { + dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN) + return super.onCreateView(inflater, container, savedInstanceState) + } + + override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { + markDownLayout.markdownListener = this + toolbar.inflateMenu(R.menu.done_menu) + toolbar.menu.findItem(R.id.submit)?.setIcon(R.drawable.ic_done) + toolbar.setNavigationIcon(R.drawable.ic_clear) + toolbar.setNavigationOnClickListener { dismiss() } + val position: Int = arguments.getInt(BundleConstant.ID, -1) + val isCard: Boolean = arguments.getBoolean(BundleConstant.EXTRA) + if (savedInstanceState == null) { + editText.setText(arguments.getString(BundleConstant.ITEM)) + } + toolbar.setOnMenuItemClickListener { + if (it.itemId == R.id.submit) { + val isEmpty = editText.text.isNullOrBlank() + editText.error = if (isEmpty) getString(R.string.required_field) else null + if (!isEmpty) { + onProjectEditedCallback?.onCreatedOrEdited(InputHelper.toString(editText), isCard, position) + dismiss() + } + } + return@setOnMenuItemClickListener true + } + } + + override fun getEditText(): EditText = editText + + override fun fragmentManager(): FragmentManager = childFragmentManager + + override fun getSavedText(): CharSequence? = editText.savedText + + override fun onAppendLink(title: String?, link: String?, isLink: Boolean) { + markDownLayout.onAppendLink(title, link, isLink) + } + + @SuppressLint("SetTextI18n") + override fun onEmojiAdded(emoji: Emoji?) { + markDownLayout.onEmojiAdded(emoji) + } + + companion object { + val TAG = ProjectCurdDialogFragment::class.java.simpleName!! + + fun newInstance(text: String? = null, isCard: Boolean = false, position: Int = -1): ProjectCurdDialogFragment { + val fragment = ProjectCurdDialogFragment() + fragment.arguments = Bundler.start() + .put(BundleConstant.ITEM, text) + .put(BundleConstant.EXTRA, isCard) + .put(BundleConstant.ID, position) + .end() + return fragment + } + } + + interface OnProjectEditedCallback { + fun onCreatedOrEdited(text: String, isCard: Boolean, position: Int) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerActivity.kt index a756458d..d4859dd4 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerActivity.kt +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerActivity.kt @@ -8,6 +8,7 @@ import android.view.MenuItem import android.view.View import butterknife.BindView import com.airbnb.lottie.LottieAnimationView +import com.evernote.android.state.State import com.fastaccess.R import com.fastaccess.data.dao.FragmentPagerAdapterModel import com.fastaccess.data.dao.NameParser @@ -25,9 +26,9 @@ import com.fastaccess.ui.widgets.CardsPagerTransformerBasic class ProjectPagerActivity : BaseActivity(), ProjectPagerMvp.View { - @BindView(R.id.pager) lateinit var pager: ViewPager @BindView(R.id.loading) lateinit var loading: LottieAnimationView + @State var isProgressShowing = false override fun canBack(): Boolean = true @@ -38,7 +39,7 @@ class ProjectPagerActivity : BaseActivity) { hideProgress() pager.adapter = FragmentsPagerAdapter(supportFragmentManager, FragmentPagerAdapterModel - .buildForProjectColumns(list, presenter.isCollaborator)) + .buildForProjectColumns(list, presenter.viewerCanUpdate)) } override fun showMessage(titleRes: Int, msgRes: Int) { @@ -57,11 +58,13 @@ class ProjectPagerActivity : BaseActivity) } @@ -20,4 +20,8 @@ interface ProjectPagerMvp { fun getColumns(): ArrayList } + + interface DeletePageListener { + fun onDeletePage(model: ProjectColumnModel) + } } \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerPresenter.kt index 2900feb9..169a9168 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerPresenter.kt +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerPresenter.kt @@ -21,7 +21,7 @@ class ProjectPagerPresenter : BasePresenter(), ProjectPage @com.evernote.android.state.State var projectId: Long = -1 @com.evernote.android.state.State var repoId: String = "" @com.evernote.android.state.State var login: String = "" - @com.evernote.android.state.State var isCollaborator: Boolean = false + @com.evernote.android.state.State var viewerCanUpdate: Boolean = false override fun getColumns(): ArrayList = columns @@ -30,7 +30,7 @@ class ProjectPagerPresenter : BasePresenter(), ProjectPage makeRestCall(Observable.zip(RestProvider.getProjectsService(isEnterprise).getProjectColumns(projectId), RestProvider.getRepoService(isEnterprise).isCollaborator(login, repoId, Login.getUser().login), BiFunction { items: Pageable, response: Response -> - isCollaborator = response.code() == 204 + viewerCanUpdate = response.code() == 204 return@BiFunction items }) .flatMap { diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectPresenter.kt index 782596aa..c387f88a 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectPresenter.kt +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectPresenter.kt @@ -27,7 +27,9 @@ class RepoProjectPresenter : BasePresenter(), RepoProjectMv val pages = arrayListOf() override fun onItemClick(position: Int, v: View, item: RepoProjectsOpenQuery.Node) { - ProjectPagerActivity.startActivity(v.context, login, repoId, item.number().toLong()) + item.databaseId()?.let { + ProjectPagerActivity.startActivity(v.context, login, repoId, it.toLong()) + } } override fun onItemLongClick(position: Int, v: View?, item: RepoProjectsOpenQuery.Node?) {} @@ -114,7 +116,7 @@ class RepoProjectPresenter : BasePresenter(), RepoProjectMv it.onEach { val columns = RepoProjectsOpenQuery.Columns(it.columns().__typename(), it.columns().totalCount()) val node = RepoProjectsOpenQuery.Node(it.__typename(), it.name(), it.number(), it.body(), - it.createdAt(), it.id(), it.viewerCanUpdate(), columns) + it.createdAt(), it.id(), it.viewerCanUpdate(), columns, it.databaseId()) toConvert.add(node) } list.addAll(toConvert) diff --git a/app/src/main/java/com/fastaccess/ui/widgets/dialog/MessageDialogView.java b/app/src/main/java/com/fastaccess/ui/widgets/dialog/MessageDialogView.java index e621c942..784512de 100644 --- a/app/src/main/java/com/fastaccess/ui/widgets/dialog/MessageDialogView.java +++ b/app/src/main/java/com/fastaccess/ui/widgets/dialog/MessageDialogView.java @@ -164,4 +164,11 @@ public class MessageDialogView extends BaseBottomSheetDialog { .put("hideCancel", hideCancel) .end(); } + + @NonNull public static Bundle getYesNoBundle(@NonNull Context context) { + return Bundler.start() + .put("primary_extra", context.getString(R.string.yes)) + .put("secondary_extra", context.getString(R.string.no)) + .end(); + } } diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java index e5c5c1b2..e5b90bdd 100644 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java @@ -131,7 +131,11 @@ public abstract class BaseRecyclerAdapter items) { diff --git a/app/src/main/res/layouts/main_layouts/layout/edit_project_column_note_layout.xml b/app/src/main/res/layouts/main_layouts/layout/edit_project_column_note_layout.xml new file mode 100644 index 00000000..ae97220d --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/edit_project_column_note_layout.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/column_card_row_layout.xml b/app/src/main/res/layouts/row_layouts/layout/column_card_row_layout.xml index 41b07da4..49d5b3de 100644 --- a/app/src/main/res/layouts/row_layouts/layout/column_card_row_layout.xml +++ b/app/src/main/res/layouts/row_layouts/layout/column_card_row_layout.xml @@ -39,9 +39,7 @@ android:layout_gravity="top" android:background="?selectableItemBackgroundBorderless" android:padding="@dimen/spacing_micro" - android:src="@drawable/ic_overflow" - android:tint="@color/white" - android:visibility="gone"/> + android:src="@drawable/ic_overflow"/> diff --git a/app/src/main/res/menu/project_card_menu.xml b/app/src/main/res/menu/project_card_menu.xml new file mode 100644 index 00000000..983104aa --- /dev/null +++ b/app/src/main/res/menu/project_card_menu.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + \ 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 66812982..57b02e8a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -564,5 +564,6 @@ Projects No Projects No Cards - Added by %s + Added by %s %s + Changes are large, please open in browser