Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: View social links in event details #105

Merged
merged 19 commits into from
Jun 14, 2018
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ dependencies {
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation "com.android.support:customtabs:27.1.1"
implementation 'com.android.support:exifinterface:27.1.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.koin:koin-android:$koin_version"
Expand Down
13 changes: 12 additions & 1 deletion app/src/main/java/org/fossasia/openevent/general/di/Modules.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ import org.fossasia.openevent.general.auth.*
import org.fossasia.openevent.general.data.Preference
import org.fossasia.openevent.general.event.*
import org.fossasia.openevent.general.search.SearchViewModel
import org.fossasia.openevent.general.social.SocialLink
import org.fossasia.openevent.general.social.SocialLinkApi
import org.fossasia.openevent.general.social.SocialLinksService
import org.fossasia.openevent.general.social.SocialLinksViewModel
import org.fossasia.openevent.general.ticket.*
import org.koin.android.architecture.ext.viewModel
import org.koin.android.ext.koin.androidApplication
import org.koin.dsl.module.applicationContext
Expand All @@ -39,12 +44,17 @@ val apiModule = applicationContext {
val retrofit: Retrofit = get()
retrofit.create(TicketApi::class.java)
}
bean {
val retrofit: Retrofit = get()
retrofit.create(SocialLinkApi::class.java)
}

factory { AuthHolder(get()) }
bean { AuthService(get(), get()) } // TODO: Convert to factory once database is implemented

factory { EventService(get(), get()) }
factory { TicketService(get()) }
factory { SocialLinksService(get()) }
}

val viewModelModule = applicationContext {
Expand All @@ -55,6 +65,7 @@ val viewModelModule = applicationContext {
viewModel { EventDetailsViewModel(get()) }
viewModel { SearchViewModel(get()) }
viewModel { TicketsViewModel(get()) }
viewModel { SocialLinksViewModel(get()) }
}

val networkModule = applicationContext {
Expand Down Expand Up @@ -88,7 +99,7 @@ val networkModule = applicationContext {
Retrofit.Builder()
.client(get())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(JSONAPIConverterFactory(objectMapper, Event::class.java, User::class.java, SignUp::class.java, Ticket::class.java))
.addConverterFactory(JSONAPIConverterFactory(objectMapper, Event::class.java, User::class.java, SignUp::class.java, Ticket::class.java, SocialLink::class.java))
.addConverterFactory(JacksonConverterFactory.create(objectMapper))
.baseUrl(baseUrl)
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.content_event.view.*
import org.fossasia.openevent.general.MainActivity
import org.fossasia.openevent.general.R
import org.fossasia.openevent.general.social.SocialLinksFragment
import org.fossasia.openevent.general.ticket.TicketsFragment
import org.koin.android.architecture.ext.viewModel
import timber.log.Timber

Expand Down Expand Up @@ -43,6 +45,7 @@ class EventDetailsFragment : Fragment() {
eventShare = it
}
loadTicketFragment()
loadSocialLinksFragment()
Timber.d("Fetched events of id %d", eventId)
})

Expand Down Expand Up @@ -147,4 +150,14 @@ class EventDetailsFragment : Fragment() {
val transaction = childFragmentManager.beginTransaction()
transaction.add(R.id.frameContainer, ticketFragment).commit()
}

private fun loadSocialLinksFragment(){
//Initialise SocialLinks Fragment
val socialLinksFragemnt = SocialLinksFragment()
val bundle = Bundle()
bundle.putLong("EVENT_ID", eventId)
socialLinksFragemnt.arguments = bundle
val transaction = childFragmentManager.beginTransaction()
transaction.add(R.id.frameContainerSocial, socialLinksFragemnt).commit()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.fossasia.openevent.general.social

import android.arch.persistence.room.*
import com.fasterxml.jackson.databind.PropertyNamingStrategy
import com.fasterxml.jackson.databind.annotation.JsonNaming
import com.github.jasminb.jsonapi.IntegerIdHandler
import com.github.jasminb.jsonapi.annotations.Id
import com.github.jasminb.jsonapi.annotations.Type

@Type("social-link")
@JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
data class SocialLink(
@Id(IntegerIdHandler::class)
val id: Int,
val link: String,
val name: String
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add foreign key

)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.fossasia.openevent.general.social

import io.reactivex.Flowable
import retrofit2.http.GET
import retrofit2.http.Path

interface SocialLinkApi {

@GET("events/{id}/social-links")
fun getSocialLinks(@Path("id") id: Long): Flowable<List<SocialLink>>

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.fossasia.openevent.general.social

import android.arch.persistence.room.Dao
import android.arch.persistence.room.Insert
import android.arch.persistence.room.OnConflictStrategy
import android.arch.persistence.room.Query
import io.reactivex.Flowable
import org.fossasia.openevent.general.event.Event

@Dao
interface SocialLinksDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertSocialLinks(socialLinks: List<SocialLink>)

@Query("DELETE FROM SocialLink")
fun deleteAll()

@Query("SELECT * from SocialLink ORDER BY startsAt DESC")
fun getAllSocialLinks(id: Long): Flowable<List<SocialLink>>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong logic, should get social links for an event

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah Actually I haven't implemented db storage yet, I am doing it 👍

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.fossasia.openevent.general.social

import android.arch.lifecycle.Observer
import android.os.Bundle
import android.provider.CalendarContract.Instances.EVENT_ID
import android.support.v4.app.Fragment
import android.support.v7.widget.LinearLayoutManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import jp.wasabeef.recyclerview.animators.SlideInUpAnimator
import kotlinx.android.synthetic.main.fragment_social_links.view.*
import org.fossasia.openevent.general.R
import org.fossasia.openevent.general.event.EventDetailsFragment
import org.fossasia.openevent.general.event.EventsRecyclerAdapter
import org.fossasia.openevent.general.event.EventsViewModel
import org.fossasia.openevent.general.event.RecyclerViewClickListener
import org.koin.android.architecture.ext.viewModel
import timber.log.Timber

class SocialLinksFragment : Fragment() {
private val socialLinksRecyclerAdapter: SocialLinksRecyclerAdapter = SocialLinksRecyclerAdapter()
private val socialLinksViewModel by viewModel<SocialLinksViewModel>()
private lateinit var rootView: View
private var id: Long = -1
private val EVENT_ID: String = "EVENT_ID"
private lateinit var linearLayoutManager: LinearLayoutManager

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val bundle = this.arguments
if (bundle != null) {
id = bundle.getLong(EVENT_ID, -1)
}
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
rootView = inflater.inflate(R.layout.fragment_social_links, container, false)

rootView.progressBarSocial.isIndeterminate = true

linearLayoutManager = LinearLayoutManager(context)
linearLayoutManager.orientation = LinearLayoutManager.HORIZONTAL
rootView.socialLinksRecycler.layoutManager = linearLayoutManager

rootView.socialLinksRecycler.adapter = socialLinksRecyclerAdapter
rootView.socialLinksRecycler.isNestedScrollingEnabled = false

socialLinksViewModel.socialLinks.observe(this, Observer {
it?.let {
socialLinksRecyclerAdapter.addAll(it)
}
socialLinksRecyclerAdapter.notifyDataSetChanged()
Timber.d("Fetched social-links of size %s", socialLinksRecyclerAdapter.itemCount)
})

socialLinksViewModel.error.observe(this, Observer {
Toast.makeText(context, it, Toast.LENGTH_LONG).show()
})

socialLinksViewModel.progress.observe(this, Observer {
it?.let { showProgressBar(it) }
})

socialLinksViewModel.loadSocialLinks(id)

return rootView
}

private fun showProgressBar(show: Boolean) {
rootView.progressBarSocial.isIndeterminate = show
rootView.progressBarSocial.visibility = if (show) View.VISIBLE else View.GONE
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.fossasia.openevent.general.social

import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.ViewGroup
import org.fossasia.openevent.general.R
import org.fossasia.openevent.general.ticket.Ticket
import org.fossasia.openevent.general.ticket.TicketViewHolder
import java.util.ArrayList

class SocialLinksRecyclerAdapter : RecyclerView.Adapter<SocialLinksViewHolder>() {

private val socialLinks = ArrayList<SocialLink>()

fun addAll(socialLinkList: List<SocialLink>) {
if (socialLinkList.isNotEmpty())
this.socialLinks.clear()
this.socialLinks.addAll(socialLinkList)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SocialLinksViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_social_link, parent, false)
return SocialLinksViewHolder(view, parent.context)
}

override fun onBindViewHolder(holder: SocialLinksViewHolder, position: Int) {
val socialLink = socialLinks[position]

holder.bind(socialLink)
}

override fun getItemCount(): Int {
return socialLinks.size
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.fossasia.openevent.general.social

import io.reactivex.Flowable

class SocialLinksService(private val socialLinkApi: SocialLinkApi) {

fun getSocialLinks(id: Long): Flowable<List<SocialLink>> {
return socialLinkApi.getSocialLinks(id)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.fossasia.openevent.general.social

import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.drawable.Drawable
import android.net.Uri
import android.support.customtabs.CustomTabsIntent
import android.support.v4.content.ContextCompat
import android.support.v7.widget.RecyclerView
import android.view.View
import kotlinx.android.synthetic.main.item_social_link.view.*
import org.fossasia.openevent.general.R
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter

class SocialLinksViewHolder(itemView: View, private var context: Context) : RecyclerView.ViewHolder(itemView) {

fun bind(event: SocialLink) {
val imageDrawable :Drawable? = ContextCompat.getDrawable(context, getSocialLinkDrawableId(event.name))
imageDrawable?.colorFilter = PorterDuffColorFilter(context.resources.getColor(R.color.greyMore), PorterDuff.Mode.SRC_IN)

itemView.img_social_link.setImageDrawable(imageDrawable)

itemView.setOnClickListener{
setUpCustomTab(context, event.link)
}
}

private fun getSocialLinkDrawableId(name: String): Int {
var id = 1
when (name) {
"Github Url" -> id = R.drawable.ic_github_24dp
"Twitter Url" -> id = R.drawable.ic_twitter_24dp
"Facebook Url" -> id = R.drawable.ic_facebook_24dp
"LinkedIn Url" -> id = R.drawable.ic_linkedin_24dp
"Youtube Url" -> id = R.drawable.ic_youtube_24dp
"Google Url" -> id = R.drawable.ic_google_plus_24dp
else -> {
}
}
return id
}

private fun setUpCustomTab(context: Context, url: String) {

var URL = url
if (!url.startsWith("http://") && !url.startsWith("https://")) {
URL = "http://$url"
}

val customTabsBuilder = CustomTabsIntent.Builder()
customTabsBuilder.setToolbarColor(ContextCompat.getColor(context, R.color.colorPrimaryDark))
customTabsBuilder.setCloseButtonIcon(BitmapFactory.decodeResource(context.resources, R.drawable.ic_arrow_back_white_cct_24dp))
customTabsBuilder.setStartAnimations(context, R.anim.slide_in_right, R.anim.slide_out_left)
customTabsBuilder.setExitAnimations(context, R.anim.slide_in_left, R.anim.slide_out_right)
val customTabsIntent = customTabsBuilder.build()
customTabsIntent.launchUrl(context, Uri.parse(URL))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.fossasia.openevent.general.social

import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import timber.log.Timber

class SocialLinksViewModel(private val socialLinksService: SocialLinksService) : ViewModel() {

private val compositeDisposable = CompositeDisposable()

val progress = MutableLiveData<Boolean>()
val socialLinks = MutableLiveData<List<SocialLink>>()
val error = MutableLiveData<String>()

fun loadSocialLinks(id: Long) {
compositeDisposable.add(socialLinksService.getSocialLinks(id)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe({
progress.value = true
}).doFinally({
progress.value = false
}).subscribe({
socialLinks.value = it
}, {
Timber.e(it, "Error fetching events")
error.value = "Error fetching events"
}))
}

override fun onCleared() {
super.onCleared()
compositeDisposable.clear()
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.fossasia.openevent.general.event
package org.fossasia.openevent.general.ticket

import android.arch.persistence.room.*
import com.fasterxml.jackson.databind.PropertyNamingStrategy
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.fossasia.openevent.general.event
package org.fossasia.openevent.general.ticket

import io.reactivex.Flowable
import io.reactivex.Single
import retrofit2.http.GET
import retrofit2.http.Path

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.fossasia.openevent.general.event
package org.fossasia.openevent.general.ticket

import io.reactivex.Flowable

Expand Down
Loading