Skip to content
Snippets Groups Projects
Commit 35eba923 authored by Jawnnypoo's avatar Jawnnypoo
Browse files

Merge remote-tracking branch 'origin/develop'

parents 8675a0f4 8b71a5d0
No related branches found
No related tags found
No related merge requests found
Pipeline #
Showing
with 436 additions and 88 deletions
package com.commit451.gitlab.adapter
import android.content.Context
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentPagerAdapter
import com.commit451.gitlab.R
import com.commit451.gitlab.fragment.PipelineDescriptionFragment
import com.commit451.gitlab.model.api.Pipeline
import com.commit451.gitlab.model.api.Project
/**
* Pipeline sections
*/
class PipelineSectionsPagerAdapter(context: Context, fm: FragmentManager, private val project: Project, private val pipeline: Pipeline) : FragmentPagerAdapter(fm) {
private val titles: Array<String> = context.resources.getStringArray(R.array.pipeline_tabs)
override fun getItem(position: Int): Fragment {
when (position) {
0 -> return PipelineDescriptionFragment.newInstance(project, pipeline)
//1 -> return PipelineDescriptionFragment.newInstance(project, pipeline)
}
throw IllegalStateException("Position exceeded on view pager")
}
override fun getCount(): Int {
return titles.size
}
override fun getPageTitle(position: Int): CharSequence {
return titles[position]
}
}
Loading
Loading
@@ -20,12 +20,13 @@ class ProjectSectionsPagerAdapter(context: ProjectActivity, fm: FragmentManager)
val ACTIVITY_POS = 1
val FILES_POS = 2
val COMMITS_POS = 3
val BUILDS_POS = 4
val MILESTONES_POS = 5
val ISSUES_POS = 6
val MERGE_REQUESTS_POS = 7
val PROJECT_MEMBERS_POS = 8
val SNIPPETS_POS = 9
val PIPELINES_POS = 4
val BUILDS_POS = 5
val MILESTONES_POS = 6
val ISSUES_POS = 7
val MERGE_REQUESTS_POS = 8
val PROJECT_MEMBERS_POS = 9
val SNIPPETS_POS = 10
}
 
private val project: Project = context.project!!
Loading
Loading
@@ -38,6 +39,7 @@ class ProjectSectionsPagerAdapter(context: ProjectActivity, fm: FragmentManager)
if (!project!!.isBuildEnabled) {
Timber.d("Builds are disabled")
disabledSections.add(BUILDS_POS)
disabledSections.add(PIPELINES_POS)
}
if (!project.isIssuesEnabled) {
Timber.d("Issues are disabled")
Loading
Loading
@@ -77,6 +79,7 @@ class ProjectSectionsPagerAdapter(context: ProjectActivity, fm: FragmentManager)
ACTIVITY_POS -> return FeedFragment.newInstance(project.feedUrl)
FILES_POS -> return FilesFragment.newInstance()
COMMITS_POS -> return CommitsFragment.newInstance()
PIPELINES_POS -> return PipelinesFragment.newInstance()
BUILDS_POS -> return BuildsFragment.newInstance()
MILESTONES_POS -> return MilestonesFragment.newInstance()
ISSUES_POS -> return IssuesFragment.newInstance()
Loading
Loading
Loading
Loading
@@ -5,15 +5,20 @@ import com.bluelinelabs.logansquare.LoganSquare
import com.commit451.gitlab.api.converter.UriTypeConverter
 
/**
* Provides access to all the GitLab things
* Provides access to all the GitLab things. Wraps RSS and the Retrofit service, in
* case we need to do overrides or global
*/
object GitLab {
class GitLab(gitLabService: GitLabService, gitLabRss: GitLabRss): GitLabService by gitLabService,
GitLabRss by gitLabRss {
 
fun init() {
/**
* Register our type converters on our singleton LoganSquare get. Needs to be set here
* since we are fetching accounts immediately with LoganSquare
*/
LoganSquare.registerTypeConverter(Uri::class.java, UriTypeConverter())
companion object {
fun init() {
/**
* Register our type converters on our singleton LoganSquare get. Needs to be set here
* since we are fetching accounts immediately with LoganSquare
*/
LoganSquare.registerTypeConverter(Uri::class.java, UriTypeConverter())
}
}
}
\ No newline at end of file
Loading
Loading
@@ -376,6 +376,35 @@ interface GitLabService {
fun cancelBuild(@Path("id") projectId: Long,
@Path("build_id") buildId: Long): Single<Build>
 
/* --- Pipelines --- */
@GET(API_VERSION + "/projects/{id}/pipelines")
fun getPipelines(@Path("id") projectId: Long,
@Query("scope") scope: String?): Single<Response<List<Pipeline>>>
@GET
fun getPipelines(@Url url: String,
@Query("scope") state: String?): Single<Response<List<Pipeline>>>
@GET(API_VERSION + "/projects/{id}/pipelines/{pipeline_id}/jobs")
fun getPipelineJobs(@Path("id") projectId: Long, @Path("pipeline_id") pipelineId: Long,
@Query("scope") scope: String?): Single<Response<List<Pipeline>>>
@GET
fun getPipelineJobs(@Url url: String,
@Query("scope") state: String?): Single<Response<List<Pipeline>>>
@GET(API_VERSION + "/projects/{id}/pipelines/{pipeline_id}")
fun getPipeline(@Path("id") projectId: Long,
@Path("pipeline_id") pipelineId: Long): Single<Pipeline>
@POST(API_VERSION + "/projects/{id}/pipelines/{pipeline_id}/retry")
fun retryPipeline(@Path("id") projectId: Long,
@Path("pipeline_id") pipelineId: Long): Single<Pipeline>
@POST(API_VERSION + "/projects/{id}/pipelines/{pipeline_id}/cancel")
fun cancelPipeline(@Path("id") projectId: Long,
@Path("pipeline_id") pipelineId: Long): Single<Pipeline>
/* --- SNIPPETS --- */
@GET(API_VERSION + "/projects/{id}/snippets")
fun getSnippets(@Path("id") projectId: Long): Single<Response<List<Snippet>>>
Loading
Loading
Loading
Loading
@@ -29,8 +29,10 @@ object OkHttpClientFactory {
 
val builder = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.addInterceptor(AuthenticationRequestInterceptor(account))
.sslSocketFactory(customTrustManager.getSSLSocketFactory(), X509TrustManagerProvider.get())
.sslSocketFactory(customTrustManager.getSSLSocketFactory(), X509TrustManagerProvider.x509TrustManager)
.hostnameVerifier(customTrustManager.getHostnameVerifier())
 
if (includeSignInAuthenticator) {
Loading
Loading
package com.commit451.gitlab.api
 
import java.security.KeyStore
import java.security.KeyStoreException
import java.security.NoSuchAlgorithmException
import java.util.*
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
Loading
Loading
@@ -12,34 +10,7 @@ import javax.net.ssl.X509TrustManager
*/
object X509TrustManagerProvider {
 
private var x509TrustManager: X509TrustManager? = null
/**
* Get the static [X509TrustManager] for the system
* @return the static get
*/
fun get(): X509TrustManager {
if (x509TrustManager == null) {
try {
init()
} catch (any: Exception) {
//If they don't have X509 trust manager, they have bigger problems
throw RuntimeException(any)
}
}
return x509TrustManager!!
}
/**
* Getting the [X509TrustManager] as shown in the [okhttp3.OkHttpClient.Builder.sslSocketFactory] docs
* @throws NoSuchAlgorithmException
* *
* @throws KeyStoreException
*/
@Throws(NoSuchAlgorithmException::class, KeyStoreException::class)
private fun init() {
val x509TrustManager: X509TrustManager by lazy {
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
val nullKeystore : KeyStore? = null
trustManagerFactory.init(nullKeystore)
Loading
Loading
@@ -47,6 +18,6 @@ object X509TrustManagerProvider {
if (trustManagers.size != 1 || trustManagers[0] !is X509TrustManager) {
throw IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers))
}
x509TrustManager = trustManagers[0] as X509TrustManager
trustManagers[0] as X509TrustManager
}
}
Loading
Loading
@@ -7,7 +7,7 @@ import java.text.DateFormat
/**
* Converts due dates
*/
class DueDateTypeConverter() : DateTypeConverter() {
class DueDateTypeConverter : DateTypeConverter() {
 
override fun getDateFormat(): DateFormat {
return Milestone.DUE_DATE_FORMAT
Loading
Loading
Loading
Loading
@@ -21,7 +21,7 @@ import java.util.*
*/
class AccessDialog private constructor(context: Context, internal var member: Member?, internal var group: Group?, projectId: Long) : MaterialDialog(MaterialDialog.Builder(context)
.items(if (group == null) R.array.project_role_names else R.array.group_role_names)
.itemsCallbackSingleChoice(-1) { materialDialog, view, i, charSequence -> true }
.itemsCallbackSingleChoice(-1) { _, _, _, _ -> true }
.theme(Theme.DARK)
.progress(true, 0) // So we can later show loading progress
.positiveText(R.string.action_apply)
Loading
Loading
@@ -40,9 +40,9 @@ class AccessDialog private constructor(context: Context, internal var member: Me
listener = accessAppliedListener
}
 
constructor(context: Context, member: Member, group: Group) : this(context, member, group, -1) {}
constructor(context: Context, member: Member, group: Group) : this(context, member, group, -1)
 
constructor(context: Context, member: Member, projectId: Long) : this(context, member, null, projectId) {}
constructor(context: Context, member: Member, projectId: Long) : this(context, member, null, projectId)
 
init {
getActionButton(DialogAction.POSITIVE).setOnClickListener { onApply() }
Loading
Loading
@@ -109,12 +109,7 @@ class AccessDialog private constructor(context: Context, internal var member: Me
return
}
val accessLevel = roleNames[selectedIndex]
if (accessLevel == null) {
Toast.makeText(context, R.string.please_select_access_level, Toast.LENGTH_LONG)
.show()
} else {
changeAccess(Member.getAccessLevel(accessLevel))
}
changeAccess(Member.getAccessLevel(accessLevel))
}
 
fun onCancel() {
Loading
Loading
package com.commit451.gitlab.event
import com.commit451.gitlab.model.api.Pipeline
/**
* A pipeline changed
*/
class PipelineChangedEvent(val pipeline: Pipeline)
package com.commit451.gitlab.extension
import android.os.Bundle
import org.parceler.Parcels
//Bundle extensions
fun Bundle.putParcelParcelableExtra(key: String, thing: Any?) {
this.putParcelable(key, org.parceler.Parcels.wrap(thing))
}
/**
* Get Parcelable that was put in the bundle using Parceler
*/
fun <T> Bundle.getParcelerParcelable(key: String): T? {
return Parcels.unwrap<T>(getParcelable(key))
}
\ No newline at end of file
package com.commit451.gitlab.rx
package com.commit451.gitlab.extension
 
import com.commit451.gitlab.util.FileUtil
import io.reactivex.Single
import okhttp3.MultipartBody
import java.io.File
 
/**
* Rx'ifies file util calls
*/
object FileObservableFactory {
//File extensions
 
fun toPart(file: File): Single<MultipartBody.Part> {
return Single.defer {
Single.just(FileUtil.toPart(file))
}
fun File.toPart(): Single<MultipartBody.Part> {
return Single.fromCallable {
FileUtil.toPart(this)
}
}
Loading
Loading
@@ -6,6 +6,10 @@ import org.parceler.Parcels
/**
* Get Parcelable that was put in the intent using Parceler
*/
fun <T> Intent.getParcelerParcelable(key: String): T {
fun <T> Intent.getParcelerParcelable(key: String): T? {
return Parcels.unwrap<T>(getParcelableExtra(key))
}
fun Intent.putParcelParcelableExtra(key: String, thing: Any?) {
this.putExtra(key, org.parceler.Parcels.wrap(thing))
}
package com.commit451.gitlab.extension
import android.os.Build
import android.text.Html
import android.text.Spanned
import android.util.Base64
import io.reactivex.Single
//String extension methods
fun String.base64Decode(): Single<ByteArray> {
return Single.fromCallable {
Base64.decode(this, Base64.DEFAULT)
}
}
/**
* Assures HTML is formatted the same way pre and post Android N
*/
@Suppress("DEPRECATION")
fun String.formatAsHtml(): Spanned {
if (Build.VERSION.SDK_INT >= 24) {
return Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
} else {
return Html.fromHtml(this)
}
}
\ No newline at end of file
package com.commit451.gitlab.fragment
 
import android.os.Bundle
import android.os.Parcelable
import android.support.design.widget.Snackbar
import android.support.v4.widget.SwipeRefreshLayout
import android.view.LayoutInflater
Loading
Loading
@@ -12,11 +11,10 @@ import butterknife.BindView
import com.commit451.gitlab.App
import com.commit451.gitlab.R
import com.commit451.gitlab.event.BuildChangedEvent
import com.commit451.gitlab.extension.getParcelerParcelable
import com.commit451.gitlab.extension.putParcelParcelableExtra
import com.commit451.gitlab.extension.setup
import com.commit451.gitlab.model.api.Build
import com.commit451.gitlab.model.api.Project
import com.commit451.gitlab.model.api.RepositoryCommit
import com.commit451.gitlab.model.api.Runner
import com.commit451.gitlab.model.api.*
import com.commit451.gitlab.rx.CustomSingleObserver
import com.commit451.gitlab.util.DateUtil
import com.trello.rxlifecycle2.android.FragmentEvent
Loading
Loading
@@ -38,8 +36,8 @@ class BuildDescriptionFragment : ButterKnifeFragment() {
fun newInstance(project: Project, build: Build): BuildDescriptionFragment {
val fragment = BuildDescriptionFragment()
val args = Bundle()
args.putParcelable(KEY_PROJECT, Parcels.wrap(project))
args.putParcelable(KEY_BUILD, Parcels.wrap(build))
args.putParcelParcelableExtra(KEY_PROJECT, project)
args.putParcelParcelableExtra(KEY_BUILD, build)
fragment.arguments = args
return fragment
}
Loading
Loading
@@ -47,6 +45,9 @@ class BuildDescriptionFragment : ButterKnifeFragment() {
 
@BindView(R.id.root) lateinit var root: ViewGroup
@BindView(R.id.swipe_layout) lateinit var swipeRefreshLayout: SwipeRefreshLayout
@BindView(R.id.text_name) lateinit var textName: TextView
@BindView(R.id.text_pipeline) lateinit var textPipeline: TextView
@BindView(R.id.text_stage) lateinit var textStage: TextView
@BindView(R.id.text_status) lateinit var textStatus: TextView
@BindView(R.id.text_duration) lateinit var textDuration: TextView
@BindView(R.id.text_created) lateinit var textCreated: TextView
Loading
Loading
@@ -61,8 +62,8 @@ class BuildDescriptionFragment : ButterKnifeFragment() {
 
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
project = Parcels.unwrap<Project>(arguments.getParcelable<Parcelable>(KEY_PROJECT))
build = Parcels.unwrap<Build>(arguments.getParcelable<Parcelable>(KEY_BUILD))
project = arguments.getParcelerParcelable<Project>(KEY_PROJECT)!!
build = arguments.getParcelerParcelable<Build>(KEY_BUILD)!!
}
 
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
Loading
Loading
@@ -111,6 +112,12 @@ class BuildDescriptionFragment : ButterKnifeFragment() {
if (startedTime == null) {
startedTime = Date()
}
val name = String.format(getString(R.string.build_name), build.name)
textName.text = name
val pipeline = String.format(getString(R.string.build_pipeline), build.pipeline)
textPipeline.text = pipeline
val stage = String.format(getString(R.string.build_stage), build.stage)
textStage.text = stage
val status = String.format(getString(R.string.build_status), build.status)
textStatus.text = status
val timeTaken = DateUtil.getTimeTaken(startedTime, finishedTime)
Loading
Loading
@@ -130,6 +137,9 @@ class BuildDescriptionFragment : ButterKnifeFragment() {
if (build.runner != null) {
bindRunner(build.runner)
}
if (build.pipeline != null) {
bindPipeline(build.pipeline)
}
if (build.commit != null) {
bindCommit(build.commit)
}
Loading
Loading
@@ -139,6 +149,10 @@ class BuildDescriptionFragment : ButterKnifeFragment() {
val runnerNum = String.format(getString(R.string.runner_number), runner.id.toString())
textRunner.text = runnerNum
}
fun bindPipeline(pipeline: Pipeline) {
val pipelineNum = String.format(getString(R.string.build_pipeline), pipeline.id.toString())
textPipeline.text = pipelineNum
}
 
fun bindCommit(commit: RepositoryCommit) {
val authorText = String.format(getString(R.string.build_commit_author), commit.authorName)
Loading
Loading
package com.commit451.gitlab.fragment
 
import android.os.Bundle
import android.os.Parcelable
import android.support.v4.widget.SwipeRefreshLayout
import android.view.LayoutInflater
import android.view.View
Loading
Loading
@@ -11,7 +10,9 @@ import butterknife.BindView
import com.commit451.gitlab.App
import com.commit451.gitlab.R
import com.commit451.gitlab.event.BuildChangedEvent
import com.commit451.gitlab.extension.getParcelerParcelable
import com.commit451.gitlab.extension.getRawBuildUrl
import com.commit451.gitlab.extension.putParcelParcelableExtra
import com.commit451.gitlab.extension.setup
import com.commit451.gitlab.model.api.Build
import com.commit451.gitlab.model.api.Project
Loading
Loading
@@ -34,8 +35,8 @@ class BuildLogFragment : ButterKnifeFragment() {
fun newInstance(project: Project, build: Build): BuildLogFragment {
val fragment = BuildLogFragment()
val args = Bundle()
args.putParcelable(KEY_PROJECT, Parcels.wrap(project))
args.putParcelable(KEY_BUILD, Parcels.wrap(build))
args.putParcelParcelableExtra(KEY_PROJECT, project)
args.putParcelParcelableExtra(KEY_BUILD, build)
fragment.arguments = args
return fragment
}
Loading
Loading
@@ -50,8 +51,8 @@ class BuildLogFragment : ButterKnifeFragment() {
 
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
project = Parcels.unwrap<Project>(arguments.getParcelable<Parcelable>(KEY_PROJECT))
build = Parcels.unwrap<Build>(arguments.getParcelable<Parcelable>(KEY_BUILD))
project = arguments.getParcelerParcelable<Project>(KEY_PROJECT)!!
build = arguments.getParcelerParcelable<Build>(KEY_BUILD)!!
}
 
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
Loading
Loading
Loading
Loading
@@ -99,7 +99,7 @@ class FeedFragment : ButterKnifeFragment() {
}
textMessage.visibility = View.GONE
swipeRefreshLayout.isRefreshing = true
App.get().gitLabRss.getFeed(feedUrl!!.toString())
App.get().gitLab.getFeed(feedUrl!!.toString())
.setup(bindUntilEvent(FragmentEvent.DESTROY_VIEW))
.subscribe(object : CustomSingleObserver<Feed>() {
override fun success(feed: Feed) {
Loading
Loading
Loading
Loading
@@ -115,7 +115,7 @@ class FilesFragment : ButterKnifeFragment() {
override fun onBackPressed(): Boolean {
if (adapterBreadcrumb.itemCount > 1) {
val breadcrumb = adapterBreadcrumb.getValueAt(adapterBreadcrumb.itemCount - 2)
if (breadcrumb != null && breadcrumb.listener != null) {
if (breadcrumb != null) {
breadcrumb.listener.onClick()
return true
}
Loading
Loading
Loading
Loading
@@ -2,7 +2,6 @@ package com.commit451.gitlab.fragment
 
import android.net.Uri
import android.os.Bundle
import android.os.Parcelable
import android.support.design.widget.Snackbar
import android.support.v4.widget.SwipeRefreshLayout
import android.support.v7.widget.GridLayoutManager
Loading
Loading
@@ -19,6 +18,8 @@ import com.commit451.gitlab.R
import com.commit451.gitlab.adapter.GroupMembersAdapter
import com.commit451.gitlab.dialog.AccessDialog
import com.commit451.gitlab.event.MemberAddedEvent
import com.commit451.gitlab.extension.getParcelerParcelable
import com.commit451.gitlab.extension.putParcelParcelableExtra
import com.commit451.gitlab.extension.setup
import com.commit451.gitlab.model.api.Group
import com.commit451.gitlab.model.api.Member
Loading
Loading
@@ -30,7 +31,6 @@ import com.commit451.gitlab.viewHolder.ProjectMemberViewHolder
import com.trello.rxlifecycle2.android.FragmentEvent
import io.reactivex.Single
import org.greenrobot.eventbus.Subscribe
import org.parceler.Parcels
import retrofit2.Response
import timber.log.Timber
 
Loading
Loading
@@ -42,7 +42,7 @@ class GroupMembersFragment : ButterKnifeFragment() {
 
fun newInstance(group: Group): GroupMembersFragment {
val args = Bundle()
args.putParcelable(KEY_GROUP, Parcels.wrap(group))
args.putParcelParcelableExtra(KEY_GROUP, group)
 
val fragment = GroupMembersFragment()
fragment.arguments = args
Loading
Loading
@@ -111,7 +111,7 @@ class GroupMembersFragment : ButterKnifeFragment() {
 
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
group = Parcels.unwrap<Group>(arguments.getParcelable<Parcelable>(KEY_GROUP))
group = arguments.getParcelerParcelable<Group>(KEY_GROUP)!!
}
 
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
Loading
Loading
@@ -157,10 +157,6 @@ class GroupMembersFragment : ButterKnifeFragment() {
if (view == null) {
return
}
if (group == null) {
swipeRefreshLayout.isRefreshing = false
return
}
textMessage.visibility = View.GONE
swipeRefreshLayout.isRefreshing = true
loadGroupMembers(App.get().gitLab.getGroupMembers(group.id))
Loading
Loading
@@ -218,7 +214,7 @@ class GroupMembersFragment : ButterKnifeFragment() {
 
@Subscribe
fun onMemberAdded(event: MemberAddedEvent) {
if (adapterGroupMembers != null) {
if (view != null) {
adapterGroupMembers.addMember(event.member)
textMessage.visibility = View.GONE
}
Loading
Loading
package com.commit451.gitlab.fragment
import android.app.Activity.RESULT_OK
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.support.design.widget.Snackbar
import android.support.v4.widget.SwipeRefreshLayout
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import butterknife.BindView
import com.commit451.gitlab.App
import com.commit451.gitlab.R
import com.commit451.gitlab.activity.AttachActivity
import com.commit451.gitlab.adapter.MergeRequestDetailAdapter
import com.commit451.gitlab.event.MergeRequestChangedEvent
import com.commit451.gitlab.extension.getParcelerParcelable
import com.commit451.gitlab.extension.putParcelParcelableExtra
import com.commit451.gitlab.extension.setup
import com.commit451.gitlab.model.api.*
import com.commit451.gitlab.navigation.TransitionFactory
import com.commit451.gitlab.rx.CustomResponseSingleObserver
import com.commit451.gitlab.rx.CustomSingleObserver
import com.commit451.gitlab.util.LinkHeaderParser
import com.commit451.gitlab.view.SendMessageView
import com.commit451.teleprinter.Teleprinter
import com.trello.rxlifecycle2.android.FragmentEvent
import org.greenrobot.eventbus.Subscribe
import timber.log.Timber
/**
* Shows the discussion of an issue
*/
class IssueDiscussionFragment : ButterKnifeFragment() {
companion object {
private val KEY_PROJECT = "project"
private val KEY_MERGE_REQUEST = "merge_request"
private val REQUEST_ATTACH = 1
fun newInstance(project: Project, issue: Issue): IssueDiscussionFragment{
val fragment = IssueDiscussionFragment()
val args = Bundle()
args.putParcelParcelableExtra(KEY_PROJECT, project)
args.putParcelParcelableExtra(KEY_MERGE_REQUEST, issue)
fragment.arguments = args
return fragment
}
}
@BindView(R.id.root) lateinit var root: ViewGroup
@BindView(R.id.swipe_layout) lateinit var swipeRefreshLayout: SwipeRefreshLayout
@BindView(R.id.list) lateinit var listNotes: RecyclerView
@BindView(R.id.send_message_view) lateinit var sendMessageView: SendMessageView
@BindView(R.id.progress) lateinit var progress: View
lateinit var adapterMergeRequestDetail: MergeRequestDetailAdapter
lateinit var layoutManagerNotes: LinearLayoutManager
lateinit var teleprinter: Teleprinter
lateinit var project: Project
lateinit var mergeRequest: MergeRequest
var nextPageUrl: Uri? = null
var loading: Boolean = false
val onScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val visibleItemCount = layoutManagerNotes.childCount
val totalItemCount = layoutManagerNotes.itemCount
val firstVisibleItem = layoutManagerNotes.findFirstVisibleItemPosition()
if (firstVisibleItem + visibleItemCount >= totalItemCount && !loading && nextPageUrl != null) {
loadMoreNotes()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
project = arguments.getParcelerParcelable<Project>(KEY_PROJECT)!!
mergeRequest = arguments.getParcelerParcelable<MergeRequest>(KEY_MERGE_REQUEST)!!
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater!!.inflate(R.layout.fragment_merge_request_discussion, container, false)
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
teleprinter = Teleprinter(activity)
adapterMergeRequestDetail = MergeRequestDetailAdapter(activity, mergeRequest, project)
layoutManagerNotes = LinearLayoutManager(activity)
listNotes.layoutManager = layoutManagerNotes
listNotes.adapter = adapterMergeRequestDetail
listNotes.addOnScrollListener(onScrollListener)
sendMessageView.callback = object : SendMessageView.Callback {
override fun onSendClicked(message: String) {
postNote(message)
}
override fun onAttachmentClicked() {
val intent = AttachActivity.newIntent(activity, project)
val activityOptions = TransitionFactory.createFadeInOptions(activity)
startActivityForResult(intent, REQUEST_ATTACH, activityOptions.toBundle())
}
}
swipeRefreshLayout.setOnRefreshListener { loadNotes() }
loadNotes()
App.bus().register(this)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_ATTACH -> {
if (resultCode == RESULT_OK) {
val response = data!!.getParcelerParcelable<FileUploadResponse>(AttachActivity.KEY_FILE_UPLOAD_RESPONSE)!!
progress.visibility = View.GONE
sendMessageView.appendText(response.markdown)
} else {
Snackbar.make(root, R.string.failed_to_upload_file, Snackbar.LENGTH_LONG)
.show()
}
}
}
}
override fun onDestroyView() {
App.bus().unregister(this)
super.onDestroyView()
}
fun loadNotes() {
swipeRefreshLayout.isRefreshing = true
App.get().gitLab.getMergeRequestNotes(project.id, mergeRequest.id)
.setup(bindUntilEvent(FragmentEvent.DESTROY_VIEW))
.subscribe(object : CustomResponseSingleObserver<List<Note>>() {
override fun error(e: Throwable) {
loading = false
Timber.e(e)
swipeRefreshLayout.isRefreshing = false
Snackbar.make(root, getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show()
}
override fun responseNonNullSuccess(notes: List<Note>) {
swipeRefreshLayout.isRefreshing = false
loading = false
nextPageUrl = LinkHeaderParser.parse(response()).next
adapterMergeRequestDetail.setNotes(notes)
}
})
}
fun loadMoreNotes() {
adapterMergeRequestDetail.setLoading(true)
App.get().gitLab.getMergeRequestNotes(nextPageUrl!!.toString())
.setup(bindUntilEvent(FragmentEvent.DESTROY_VIEW))
.subscribe(object : CustomResponseSingleObserver<List<Note>>() {
override fun error(e: Throwable) {
loading = false
Timber.e(e)
adapterMergeRequestDetail.setLoading(false)
Snackbar.make(root, getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show()
}
override fun responseNonNullSuccess(notes: List<Note>) {
adapterMergeRequestDetail.setLoading(false)
loading = false
nextPageUrl = LinkHeaderParser.parse(response()).next
adapterMergeRequestDetail.addNotes(notes)
}
})
}
fun postNote(message: String) {
if (message.isNullOrBlank()) {
return
}
progress.visibility = View.VISIBLE
progress.alpha = 0.0f
progress.animate().alpha(1.0f)
// Clear text & collapse keyboard
teleprinter.hideKeyboard()
sendMessageView.clearText()
App.get().gitLab.addMergeRequestNote(project.id, mergeRequest.id, message)
.setup(bindUntilEvent(FragmentEvent.DESTROY_VIEW))
.subscribe(object : CustomSingleObserver<Note>() {
override fun error(e: Throwable) {
Timber.e(e)
progress.visibility = View.GONE
Snackbar.make(root, getString(R.string.connection_error), Snackbar.LENGTH_SHORT)
.show()
}
override fun success(note: Note) {
progress.visibility = View.GONE
adapterMergeRequestDetail.addNote(note)
listNotes.smoothScrollToPosition(MergeRequestDetailAdapter.headerCount)
}
})
}
@Subscribe
fun onMergeRequestChangedEvent(event: MergeRequestChangedEvent) {
if (mergeRequest.id == event.mergeRequest.id) {
mergeRequest = event.mergeRequest
loadNotes()
}
}
}
package com.commit451.gitlab.fragment
 
import android.os.Bundle
import android.os.Parcelable
import android.support.v4.widget.SwipeRefreshLayout
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
Loading
Loading
@@ -15,6 +14,8 @@ import com.commit451.gitlab.R
import com.commit451.gitlab.adapter.CommitAdapter
import com.commit451.gitlab.adapter.DividerItemDecoration
import com.commit451.gitlab.event.MergeRequestChangedEvent
import com.commit451.gitlab.extension.getParcelerParcelable
import com.commit451.gitlab.extension.putParcelParcelableExtra
import com.commit451.gitlab.extension.setup
import com.commit451.gitlab.model.api.MergeRequest
import com.commit451.gitlab.model.api.Project
Loading
Loading
@@ -23,7 +24,6 @@ import com.commit451.gitlab.navigation.Navigator
import com.commit451.gitlab.rx.CustomSingleObserver
import com.trello.rxlifecycle2.android.FragmentEvent
import org.greenrobot.eventbus.Subscribe
import org.parceler.Parcels
import timber.log.Timber
 
/**
Loading
Loading
@@ -39,8 +39,8 @@ class MergeRequestCommitsFragment : ButterKnifeFragment() {
fun newInstance(project: Project, mergeRequest: MergeRequest): MergeRequestCommitsFragment {
val fragment = MergeRequestCommitsFragment()
val args = Bundle()
args.putParcelable(KEY_PROJECT, Parcels.wrap(project))
args.putParcelable(KEY_MERGE_REQUEST, Parcels.wrap(mergeRequest))
args.putParcelParcelableExtra(KEY_PROJECT, project)
args.putParcelParcelableExtra(KEY_MERGE_REQUEST, mergeRequest)
fragment.arguments = args
return fragment
}
Loading
Loading
@@ -72,8 +72,8 @@ class MergeRequestCommitsFragment : ButterKnifeFragment() {
 
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
project = Parcels.unwrap<Project>(arguments.getParcelable<Parcelable>(KEY_PROJECT))
mergeRequest = Parcels.unwrap<MergeRequest>(arguments.getParcelable<Parcelable>(KEY_MERGE_REQUEST))
project = arguments.getParcelerParcelable<Project>(KEY_PROJECT)
mergeRequest = arguments.getParcelerParcelable<MergeRequest>(KEY_MERGE_REQUEST)
}
 
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment