social-aggregator/app/src/main/java/pl/edu/amu/wmi/socialaggregator/socialplatforms/Facebook.kt

235 lines
8.6 KiB
Kotlin

package pl.edu.amu.wmi.socialaggregator.socialplatforms
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import com.facebook.*
import com.facebook.login.LoginManager
import com.facebook.login.LoginResult
import com.facebook.login.widget.LoginButton
import com.facebook.share.Sharer
import com.facebook.share.model.ShareMediaContent
import com.facebook.share.model.SharePhoto
import com.facebook.share.widget.ShareDialog
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import org.json.JSONArray
import org.json.JSONObject
import pl.edu.amu.wmi.socialaggregator.R
import pl.edu.amu.wmi.socialaggregator.utils.Utils
import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithButtonRecycler
class Facebook : SocialPlatform {
private var callbackManager: CallbackManager = CallbackManager.Factory.create()
override fun getName(): String = "Facebook"
override fun getLogo(): Int = R.mipmap.ic_logo_facebook
override fun login(context: Context) {
}
override fun logout(context: Context) {
}
override fun isLoggedIn(context: Context): Boolean {
val accessToken = AccessToken.getCurrentAccessToken()
return accessToken != null && !accessToken.isExpired
}
override fun addPost(
publishSubject: PublishSubject<Any>,
context: Context,
text: String,
images: List<Bitmap>,
imagePaths: List<String>
) {
val content = ShareMediaContent.Builder().apply {
images.forEach {
addMedium(
SharePhoto.Builder().setBitmap(it).build()
)
}
}.build()
val shareDialog = ShareDialog(context as Activity)
shareDialog.registerCallback(callbackManager, object : FacebookCallback<Sharer.Result?> {
override fun onSuccess(result: Sharer.Result?) {
publishSubject.onNext(Any())
}
override fun onCancel() {
publishSubject.onNext(Any())
}
override fun onError(error: FacebookException?) {
publishSubject.onError(Exception(error?.localizedMessage))
}
})
shareDialog.show(content, ShareDialog.Mode.AUTOMATIC)
}
override fun getPosts(context: Context): Single<List<Post>> {
return Single.just(AccessToken.getCurrentAccessToken())
.observeOn(Schedulers.io())
.map { token ->
if (token.isExpired) {
return@map emptyList<Post>()
} else {
val request = GraphRequest.newGraphPathRequest(
AccessToken.getCurrentAccessToken(),
"/me/posts"
) {
Log.i(getName(), it.toString())
}
val parameters = Bundle()
parameters.putString(
"fields",
"likes.summary(true),created_time,message,attachments{url,unshimmed_url,media,subattachments}"
)
request.parameters = parameters
val res = request.executeAndWait()
val data = res.jsonObject["data"] as JSONArray
val size = data.length()
return@map (0 until size).map {
val obj = data[it] as JSONObject
val msg = if (obj.has("message")) obj.getString("message") else ""
val date =
if (obj.has("created_time")) obj.getString("created_time") else ""
// SimpleDateFormat("YYYY-MM-DD\'T\'hh:mm:ssZ").parse(date)
Post(this, msg, date, getImages(obj))
}
}
}
.observeOn(AndroidSchedulers.mainThread())
}
private fun getImages(obj: JSONObject): List<String> {
val list = emptyList<String>().toMutableList()
if (obj.has("attachments")) {
val attachments = obj.getJSONObject("attachments").getJSONArray("data")
try {
list.addAll((0 until attachments.length())
.map { attachments[it] as JSONObject }
.flatMap {
val urls = mutableListOf<String>()
if (it.has("media")) {
urls.add(
it.getJSONObject("media")
.getJSONObject("image")
.getString("src")
)
}
if (it.has("subattachments")) {
val subattachments =
it.getJSONObject("subattachments").getJSONArray("data")
urls.addAll((0 until subattachments.length())
.map { subattachments[it] as JSONObject }
.map {
it.getJSONObject("media")
.getJSONObject("image")
.getString("src")
})
}
return@flatMap urls
})
} catch (e: Exception) {
Log.e(getName(), e.toString())
}
}
return list
}
override fun handleButtonView(context: Context): (SocialWithButtonRecycler.ViewHolder) -> Unit =
{ viewHolder ->
viewHolder.textView.text = this.getName()
val constraintSet = ConstraintSet()
val button = LoginButton(context)
button.id = View.generateViewId()
val parent = viewHolder.image.parent as ViewGroup
parent.removeView(viewHolder.image)
parent.addView(button)
constraintSet.clone(parent as ConstraintLayout)
constraintSet.connect(
button.id, ConstraintSet.TOP,
parent.id, ConstraintSet.TOP, 8.toPx(context)
)
constraintSet.connect(
button.id, ConstraintSet.END,
parent.id, ConstraintSet.END
)
constraintSet.connect(
button.id, ConstraintSet.BOTTOM,
parent.id, ConstraintSet.BOTTOM, 8.toPx(context)
)
constraintSet.connect(
viewHolder.textView.id, ConstraintSet.BOTTOM,
button.id, ConstraintSet.BOTTOM
)
constraintSet.connect(
viewHolder.textView.id, ConstraintSet.END,
button.id, ConstraintSet.START, 8.toPx(context)
)
constraintSet.connect(
viewHolder.textView.id, ConstraintSet.START,
parent.id, ConstraintSet.START
)
constraintSet.connect(
viewHolder.textView.id, ConstraintSet.TOP,
button.id, ConstraintSet.TOP
)
constraintSet.setHorizontalBias(viewHolder.textView.id, 0.toFloat())
constraintSet.applyTo(parent)
button.setPermissions(listOf("email"))
val callback = object : FacebookCallback<LoginResult> {
override fun onSuccess(result: LoginResult?) {
Log.i(getName(), "SUCCESS!")
LoginManager.getInstance().logInWithReadPermissions(
context as Activity,
listOf("email")
)
}
override fun onCancel() {
Log.i(getName(), "CANCEL!")
}
override fun onError(error: FacebookException?) {
Log.i(getName(), "FAIL!")
}
}
button.registerCallback(callbackManager, callback)
LoginManager.getInstance().registerCallback(callbackManager, callback)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
callbackManager.onActivityResult(requestCode, resultCode, data)
}
private fun Int.toPx(context: Context): Int {
return Utils.convertDpToPixel(this.toFloat(), context).toInt()
}
}