Skip to content
Snippets Groups Projects
Commit 7d46fff6 authored by Jawnnypoo's avatar Jawnnypoo
Browse files

Some more cleanup things

parent 0b0c2b5c
No related branches found
No related tags found
No related merge requests found
package com.commit451.gitlab.extension
import android.os.Bundle
//Bundle extensions
fun Bundle.putParcelParcelableExtra(key: String, thing: Any?) {
this.putParcelable(key, org.parceler.Parcels.wrap(thing))
}
\ No newline at end of file
Loading
Loading
@@ -6,7 +6,7 @@ import io.reactivex.Single
//String extension methods
 
fun String.base64Decode(): Single<ByteArray> {
return Single.defer {
Single.just(Base64.decode(this, Base64.DEFAULT))
return Single.fromCallable {
Base64.decode(this, Base64.DEFAULT)
}
}
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.os.Parcelable
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.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 org.parceler.Parcels
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 = MergeRequestDiscussionFragment()
val args = Bundle()
args.putParcelable(KEY_PROJECT, Parcels.wrap(project))
args.putParcelable(KEY_MERGE_REQUEST, Parcels.wrap(mergeRequest))
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 = Parcels.unwrap<Project>(arguments.getParcelable<Parcelable>(KEY_PROJECT))
mergeRequest = Parcels.unwrap<MergeRequest>(arguments.getParcelable<Parcelable>(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 = Parcels.unwrap<FileUploadResponse>(data!!.getParcelableExtra<Parcelable>(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()
}
}
}
Loading
Loading
@@ -15,11 +15,7 @@ import java.lang.ref.WeakReference
*/
class BrowserFallback(context: Context) : NavigationFallback {
 
private val context: WeakReference<Context>
init {
this.context = WeakReference(context)
}
private val context: WeakReference<Context> = WeakReference(context)
 
override fun onFallbackNavigateTo(url: Uri) {
val intent = Intent(Intent.ACTION_VIEW)
Loading
Loading
Loading
Loading
@@ -13,11 +13,7 @@ import java.lang.ref.WeakReference
*/
class LabCoatIntentCustomizer(activity: Activity, private val colorToolbar: Int) : IntentCustomizer {
 
private val activity: WeakReference<Activity>
init {
this.activity = WeakReference(activity)
}
private val activity: WeakReference<Activity> = WeakReference(activity)
 
override fun onCustomiseIntent(simpleChromeCustomTabsIntentBuilder: SimpleChromeCustomTabsIntentBuilder): SimpleChromeCustomTabsIntentBuilder {
val activity = this.activity.get() ?: return simpleChromeCustomTabsIntentBuilder
Loading
Loading
package com.commit451.gitlab.util;
import android.net.Uri;
import com.commit451.gitlab.ssl.X509Util;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public final class Gravatar {
private Gravatar() {
}
public static Builder init() {
return init(null);
}
public static Builder init(String email) {
if (email != null && email.isEmpty()) {
email = null;
}
return new Builder(email);
}
private static String md5(String raw) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(raw.getBytes(Charset.forName("UTF-8")));
return X509Util.hexify(digest.digest());
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
}
}
public static class Builder {
private final String mEmail;
private boolean mSSL = false;
private boolean mExtension = false;
private int mSize = -1;
private String mDefaultImage = null;
private boolean mForceDefault = false;
private String mRating = null;
private Builder(String email) {
this.mEmail = email;
}
public Builder ssl() {
mSSL = true;
return this;
}
public Builder extension() {
mExtension = true;
return this;
}
public Builder size(int size) {
if (size < 1 || size > 2048) {
throw new IllegalArgumentException("Image size must be from 1px up to 2048px");
}
mSize = size;
return this;
}
public Builder defaultImage(DefaultImage defaultImage) {
switch (defaultImage) {
case _404:
mDefaultImage = "404";
break;
case MYSTERY_MAN:
mDefaultImage = "mm";
break;
case IDENTICON:
mDefaultImage = "identicon";
break;
case MONSTERID:
mDefaultImage = "monsterid";
break;
case WAVATAR:
mDefaultImage = "wavatar";
break;
case RETRO:
mDefaultImage = "retro";
break;
case BLANK:
mDefaultImage = "blank";
break;
}
return this;
}
public Builder defaultImage(Uri defaultImage) {
try {
mDefaultImage = URLEncoder.encode(defaultImage.toString(), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(e);
}
return this;
}
public Builder forceDefault() {
mForceDefault = true;
return this;
}
public Builder rating(Rating rating) {
switch (rating) {
case G:
mRating = "g";
break;
case PG:
mRating = "pg";
break;
case R:
mRating = "r";
break;
case X:
mRating = "x";
break;
}
return this;
}
public Uri build() {
StringBuilder uriBuilder = new StringBuilder();
if (mSSL) {
uriBuilder.append("https://secure.gravatar.com/avatar/");
} else {
uriBuilder.append("http://www.gravatar.com/avatar/");
}
if (mEmail != null) {
uriBuilder.append(md5(mEmail));
} else {
uriBuilder.append("00000000000000000000000000000000");
}
if (mExtension) {
uriBuilder.append(".jpg");
}
StringBuilder queryBuilder = new StringBuilder();
if (mSize != -1) {
queryBuilder.append("&s=").append(mSize);
}
if (mDefaultImage != null) {
queryBuilder.append("&d=").append(mDefaultImage);
}
if (mForceDefault) {
queryBuilder.append("&f=y");
}
if (mRating != null) {
queryBuilder.append("&r=").append(mRating);
}
String query = queryBuilder.toString();
if (query.length() > 0) {
uriBuilder.append("?").append(query.substring(1));
}
return Uri.parse(uriBuilder.toString());
}
}
public enum Rating {
G, PG, R, X
}
public enum DefaultImage {
_404, MYSTERY_MAN, IDENTICON, MONSTERID, WAVATAR, RETRO, BLANK
}
}
package com.commit451.gitlab.util
import android.net.Uri
import com.commit451.gitlab.ssl.X509Util
import java.io.UnsupportedEncodingException
import java.net.URLEncoder
import java.nio.charset.Charset
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
object Gravatar {
@JvmOverloads
fun init(email: String? = null): Builder {
return Builder(email)
}
private fun md5(raw: String): String {
try {
val digest = MessageDigest.getInstance("MD5")
digest.update(raw.toByteArray(Charset.forName("UTF-8")))
return X509Util.hexify(digest.digest())
} catch (e: NoSuchAlgorithmException) {
throw IllegalStateException(e)
}
}
class Builder constructor(private val mEmail: String?) {
private var mSSL = false
private var mExtension = false
private var mSize = -1
private var mDefaultImage: String? = null
private var mForceDefault = false
private var mRating: String? = null
fun ssl(): Builder {
mSSL = true
return this
}
fun extension(): Builder {
mExtension = true
return this
}
fun size(size: Int): Builder {
if (size < 1 || size > 2048) {
throw IllegalArgumentException("Image size must be from 1px up to 2048px")
}
mSize = size
return this
}
fun defaultImage(defaultImage: DefaultImage): Builder {
when (defaultImage) {
Gravatar.DefaultImage._404 -> mDefaultImage = "404"
Gravatar.DefaultImage.MYSTERY_MAN -> mDefaultImage = "mm"
Gravatar.DefaultImage.IDENTICON -> mDefaultImage = "identicon"
Gravatar.DefaultImage.MONSTERID -> mDefaultImage = "monsterid"
Gravatar.DefaultImage.WAVATAR -> mDefaultImage = "wavatar"
Gravatar.DefaultImage.RETRO -> mDefaultImage = "retro"
Gravatar.DefaultImage.BLANK -> mDefaultImage = "blank"
}
return this
}
fun build(): Uri {
val uriBuilder = StringBuilder()
if (mSSL) {
uriBuilder.append("https://secure.gravatar.com/avatar/")
} else {
uriBuilder.append("http://www.gravatar.com/avatar/")
}
if (mEmail != null) {
uriBuilder.append(md5(mEmail))
} else {
uriBuilder.append("00000000000000000000000000000000")
}
if (mExtension) {
uriBuilder.append(".jpg")
}
val queryBuilder = StringBuilder()
if (mSize != -1) {
queryBuilder.append("&s=").append(mSize)
}
if (mDefaultImage != null) {
queryBuilder.append("&d=").append(mDefaultImage)
}
if (mForceDefault) {
queryBuilder.append("&f=y")
}
if (mRating != null) {
queryBuilder.append("&r=").append(mRating)
}
val query = queryBuilder.toString()
if (query.length > 0) {
uriBuilder.append("?").append(query.substring(1))
}
return Uri.parse(uriBuilder.toString())
}
}
enum class Rating {
G, PG, R, X
}
enum class DefaultImage {
_404, MYSTERY_MAN, IDENTICON, MONSTERID, WAVATAR, RETRO, BLANK
}
}
Loading
Loading
@@ -23,10 +23,10 @@ object ImageUtil {
}
}
 
return getAvatarUrl("", size)
return getAvatarUrl(null as? String?, size)
}
 
fun getAvatarUrl(email: String, size: Int): Uri {
fun getAvatarUrl(email: String?, size: Int): Uri {
return Gravatar
.init(email)
.ssl()
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