Skip to content

Commit 9831bda

Browse files
anhanh11001iamareebjamal
authored andcommitted
feat: Add sponsors section to show details of all sponsor (#1685)
Fixes: #1679
1 parent 5237ed9 commit 9831bda

File tree

12 files changed

+343
-5
lines changed

12 files changed

+343
-5
lines changed

app/src/main/java/org/fossasia/openevent/general/di/Modules.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ import org.fossasia.openevent.general.speakers.SpeakerViewModel
8787
import org.fossasia.openevent.general.sponsor.Sponsor
8888
import org.fossasia.openevent.general.sponsor.SponsorApi
8989
import org.fossasia.openevent.general.sponsor.SponsorService
90+
import org.fossasia.openevent.general.sponsor.SponsorsViewModel
9091
import org.fossasia.openevent.general.ticket.Ticket
9192
import org.fossasia.openevent.general.ticket.TicketApi
9293
import org.fossasia.openevent.general.ticket.TicketId
@@ -205,6 +206,7 @@ val viewModelModule = module {
205206
viewModel { GeoLocationViewModel(get()) }
206207
viewModel { SmartAuthViewModel() }
207208
viewModel { SpeakerViewModel(get(), get()) }
209+
viewModel { SponsorsViewModel(get(), get()) }
208210
}
209211

210212
val networkModule = module {

app/src/main/java/org/fossasia/openevent/general/event/EventDetailsFragment.kt

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ import org.fossasia.openevent.general.event.topic.SimilarEventsFragment
7474
import org.fossasia.openevent.general.social.SocialLinksFragment
7575
import org.fossasia.openevent.general.speakers.SpeakerFragmentArgs
7676
import org.fossasia.openevent.general.speakers.SpeakerRecyclerAdapter
77+
import org.fossasia.openevent.general.sponsor.SponsorClickListener
7778
import org.fossasia.openevent.general.sponsor.SponsorRecyclerAdapter
79+
import org.fossasia.openevent.general.sponsor.SponsorsFragmentArgs
7880
import org.fossasia.openevent.general.ticket.TicketsFragmentArgs
7981
import org.fossasia.openevent.general.utils.Utils
8082
import org.fossasia.openevent.general.utils.Utils.getAnimSlide
@@ -205,6 +207,20 @@ class EventDetailsFragment : Fragment() {
205207
rootView.sponsorsRecyclerView.layoutManager = sponsorLinearLayoutManager
206208
rootView.sponsorsRecyclerView.adapter = sponsorsAdapter
207209

210+
val sponsorClickListener: SponsorClickListener = object : SponsorClickListener {
211+
override fun onClick() {
212+
moveToSponsorSection()
213+
}
214+
}
215+
216+
sponsorsAdapter.apply {
217+
onSponsorClick = sponsorClickListener
218+
}
219+
220+
rootView.sponsorsSummaryContainer.setOnClickListener {
221+
moveToSponsorSection()
222+
}
223+
208224
// Set toolbar title to event name
209225
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
210226
rootView.nestedContentEventScroll.setOnScrollChangeListener { _, _, scrollY, _, _ ->
@@ -513,7 +529,7 @@ class EventDetailsFragment : Fragment() {
513529
}
514530
private fun checkForAuthentication() {
515531
if (eventViewModel.isLoggedIn())
516-
writefeedback()
532+
writeFeedback()
517533
else {
518534
rootView.nestedContentEventScroll.longSnackbar(getString(R.string.log_in_first))
519535
redirectToLogin()
@@ -528,7 +544,7 @@ class EventDetailsFragment : Fragment() {
528544
}
529545
}
530546

531-
private fun writefeedback() {
547+
private fun writeFeedback() {
532548
val layout = layoutInflater.inflate(R.layout.dialog_feedback, null)
533549

534550
val alertDialog = AlertDialog.Builder(requireContext())
@@ -564,6 +580,14 @@ class EventDetailsFragment : Fragment() {
564580
})
565581
}
566582

583+
private fun moveToSponsorSection() {
584+
SponsorsFragmentArgs(safeArgs.eventId)
585+
.toBundle()
586+
.also { bundle ->
587+
findNavController(rootView).navigate(R.id.sponsorsFragment, bundle, getAnimSlide())
588+
}
589+
}
590+
567591
override fun onDestroy() {
568592
Picasso.get().cancelRequest(rootView.eventImage)
569593
super.onDestroy()

app/src/main/java/org/fossasia/openevent/general/sponsor/SponsorRecyclerAdapter.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,19 @@ const val MAXIMUM_PREVIEW_SPONSOR = 8
99

1010
class SponsorRecyclerAdapter : RecyclerView.Adapter<SponsorViewHolder>() {
1111
private val sponsorList = ArrayList<Sponsor>()
12+
lateinit var onSponsorClick: SponsorClickListener
1213

1314
fun addAll(newSponsors: List<Sponsor>) {
1415
if (sponsorList.isNotEmpty()) sponsorList.clear()
1516
sponsorList.addAll(SponsorUtil.sortSponsorByLevel(newSponsors))
1617
}
1718

1819
override fun onBindViewHolder(holder: SponsorViewHolder, position: Int) {
19-
holder.bind(sponsorList[position],
20-
sponsorList.size > MAXIMUM_PREVIEW_SPONSOR && position == MAXIMUM_PREVIEW_SPONSOR - 1, sponsorList.size)
20+
holder.apply {
21+
bind(sponsorList[position], sponsorList.size > MAXIMUM_PREVIEW_SPONSOR &&
22+
position == MAXIMUM_PREVIEW_SPONSOR - 1, sponsorList.size)
23+
sponsorClickListener = onSponsorClick
24+
}
2125
}
2226

2327
override fun getItemCount(): Int {

app/src/main/java/org/fossasia/openevent/general/sponsor/SponsorViewHolder.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@ import org.fossasia.openevent.general.utils.Utils
1010

1111
class SponsorViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
1212

13-
fun bind(sponsor: Sponsor, isLastPreviewSponsor: Boolean, sponsorListSize: Int) {
13+
lateinit var sponsorClickListener: SponsorClickListener
14+
15+
fun bind(
16+
sponsor: Sponsor,
17+
isLastPreviewSponsor: Boolean,
18+
sponsorListSize: Int
19+
) {
20+
1421
Picasso.get()
1522
.load(sponsor.logoUrl)
1623
.placeholder(Utils.requireDrawable(itemView.context, R.drawable.ic_account_circle_grey))
@@ -21,5 +28,9 @@ class SponsorViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
2128
itemView.sponsorImageView.foreground = itemView.context.getDrawable(R.drawable.foreground_black_blur)
2229
itemView.sponsorTextView.text = "+$sponsorListSize"
2330
}
31+
32+
itemView.setOnClickListener {
33+
sponsorClickListener.onClick()
34+
}
2435
}
2536
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package org.fossasia.openevent.general.sponsor
2+
3+
import android.view.LayoutInflater
4+
import android.view.View
5+
import android.view.ViewGroup
6+
import androidx.recyclerview.widget.RecyclerView
7+
import com.squareup.picasso.Picasso
8+
import kotlinx.android.synthetic.main.item_sponsor_detail.view.sponsorDetailURL
9+
import kotlinx.android.synthetic.main.item_sponsor_detail.view.sponsorDetailLogo
10+
import kotlinx.android.synthetic.main.item_sponsor_detail.view.sponsorDetailDescription
11+
import kotlinx.android.synthetic.main.item_sponsor_detail.view.sponsorDetailType
12+
import kotlinx.android.synthetic.main.item_sponsor_detail.view.sponsorDetailName
13+
import org.fossasia.openevent.general.R
14+
import org.fossasia.openevent.general.utils.Utils
15+
16+
class SponsorsDetailAdapter : RecyclerView.Adapter<SponsorsDetailViewHolder>() {
17+
18+
private val sponsorList = mutableListOf<Sponsor>()
19+
lateinit var onURLClickListener: SponsorURLClickListener
20+
21+
fun addAll(newSponsors: List<Sponsor>) {
22+
if (sponsorList.isNotEmpty()) sponsorList.clear()
23+
sponsorList.addAll(SponsorUtil.sortSponsorByLevel(newSponsors))
24+
notifyDataSetChanged()
25+
}
26+
27+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SponsorsDetailViewHolder {
28+
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_sponsor_detail, parent, false)
29+
return SponsorsDetailViewHolder(itemView)
30+
}
31+
32+
override fun getItemCount(): Int = sponsorList.size
33+
34+
override fun onBindViewHolder(holder: SponsorsDetailViewHolder, position: Int) {
35+
holder.apply {
36+
bind(sponsorList[position])
37+
sponsorURLClickListener = onURLClickListener
38+
}
39+
}
40+
}
41+
42+
class SponsorsDetailViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
43+
lateinit var sponsorURLClickListener: SponsorURLClickListener
44+
45+
fun bind(sponsor: Sponsor) {
46+
Picasso.get()
47+
.load(sponsor.logoUrl)
48+
.placeholder(Utils.requireDrawable(itemView.context, R.drawable.ic_account_circle_grey))
49+
.error(Utils.requireDrawable(itemView.context, R.drawable.ic_account_circle_grey))
50+
.into(itemView.sponsorDetailLogo)
51+
52+
itemView.sponsorDetailName.text = sponsor.name
53+
if (sponsor.type.isNullOrBlank()) {
54+
itemView.sponsorDetailType.visibility = View.GONE
55+
} else {
56+
itemView.sponsorDetailType.text = "Type: ${sponsor.type}"
57+
itemView.sponsorDetailType.visibility = View.VISIBLE
58+
}
59+
if (sponsor.description.isNullOrBlank()) {
60+
itemView.sponsorDetailDescription.visibility = View.GONE
61+
} else {
62+
itemView.sponsorDetailDescription.text = sponsor.description
63+
itemView.sponsorDetailDescription.visibility = View.VISIBLE
64+
}
65+
66+
itemView.sponsorDetailURL.setOnClickListener {
67+
sponsorURLClickListener?.onClick(sponsor.url)
68+
}
69+
}
70+
}
71+
72+
interface SponsorURLClickListener {
73+
fun onClick(sponsorURL: String?)
74+
}
75+
76+
interface SponsorClickListener {
77+
fun onClick()
78+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package org.fossasia.openevent.general.sponsor
2+
3+
import android.os.Bundle
4+
import android.view.LayoutInflater
5+
import android.view.MenuItem
6+
import android.view.View
7+
import android.view.ViewGroup
8+
import androidx.core.view.isVisible
9+
import androidx.fragment.app.Fragment
10+
import androidx.lifecycle.Observer
11+
import androidx.navigation.fragment.navArgs
12+
import androidx.recyclerview.widget.LinearLayoutManager
13+
import androidx.recyclerview.widget.RecyclerView
14+
import kotlinx.android.synthetic.main.fragment_sponsors.view.sponsorsDetailRecyclerView
15+
import kotlinx.android.synthetic.main.fragment_sponsors.view.sponsorDetailProgressBar
16+
import org.fossasia.openevent.general.R
17+
import org.fossasia.openevent.general.utils.Utils
18+
import org.fossasia.openevent.general.utils.extensions.nonNull
19+
import org.jetbrains.anko.design.snackbar
20+
import org.koin.androidx.viewmodel.ext.android.viewModel
21+
22+
class SponsorsFragment : Fragment() {
23+
private lateinit var rootView: View
24+
private val sponsorsDetailViewModel by viewModel<SponsorsViewModel>()
25+
private val sponsorsAdapter = SponsorsDetailAdapter()
26+
private val safeArgs: SponsorsFragmentArgs by navArgs()
27+
28+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
29+
rootView = inflater.inflate(R.layout.fragment_sponsors, container, false)
30+
31+
Utils.setToolbar(activity, getString(R.string.sponsors))
32+
setHasOptionsMenu(true)
33+
34+
val sponsorURLClickListener = object : SponsorURLClickListener {
35+
override fun onClick(sponsorURL: String?) {
36+
if (sponsorURL.isNullOrBlank()) return
37+
context?.let { Utils.openUrl(it, sponsorURL) }
38+
}
39+
}
40+
sponsorsAdapter.apply {
41+
onURLClickListener = sponsorURLClickListener
42+
}
43+
44+
val layoutManager = LinearLayoutManager(context)
45+
layoutManager.orientation = RecyclerView.VERTICAL
46+
rootView.sponsorsDetailRecyclerView.layoutManager = layoutManager
47+
rootView.sponsorsDetailRecyclerView.adapter = sponsorsAdapter
48+
49+
sponsorsDetailViewModel.error
50+
.nonNull()
51+
.observe(viewLifecycleOwner, Observer {
52+
rootView.snackbar(it)
53+
})
54+
55+
sponsorsDetailViewModel.sponsors
56+
.nonNull()
57+
.observe(viewLifecycleOwner, Observer { sponsors ->
58+
sponsorsAdapter.addAll(sponsors)
59+
})
60+
61+
sponsorsDetailViewModel.progress
62+
.nonNull()
63+
.observe(viewLifecycleOwner, Observer { isLoading ->
64+
rootView.sponsorDetailProgressBar.isVisible = isLoading
65+
})
66+
67+
sponsorsDetailViewModel.loadSponsors(safeArgs.eventId)
68+
69+
return rootView
70+
}
71+
72+
override fun onOptionsItemSelected(item: MenuItem): Boolean {
73+
return when (item.itemId) {
74+
android.R.id.home -> {
75+
activity?.onBackPressed()
76+
true
77+
}
78+
else -> super.onOptionsItemSelected(item)
79+
}
80+
}
81+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package org.fossasia.openevent.general.sponsor
2+
3+
import androidx.lifecycle.LiveData
4+
import androidx.lifecycle.MutableLiveData
5+
import androidx.lifecycle.ViewModel
6+
import io.reactivex.android.schedulers.AndroidSchedulers
7+
import io.reactivex.disposables.CompositeDisposable
8+
import io.reactivex.schedulers.Schedulers
9+
import org.fossasia.openevent.general.R
10+
import org.fossasia.openevent.general.data.Resource
11+
import timber.log.Timber
12+
13+
class SponsorsViewModel(
14+
private val sponsorService: SponsorService,
15+
private val resource: Resource
16+
) : ViewModel() {
17+
18+
private val compositeDisposable = CompositeDisposable()
19+
20+
private val mutableSponsors = MutableLiveData<List<Sponsor>>()
21+
val sponsors: LiveData<List<Sponsor>> = mutableSponsors
22+
private val mutableError = MutableLiveData<String>()
23+
val error: LiveData<String> = mutableError
24+
private val mutableProgress = MutableLiveData<Boolean>()
25+
val progress: LiveData<Boolean> = mutableProgress
26+
27+
fun loadSponsors(id: Long) {
28+
if (id == -1L) {
29+
mutableError.value = resource.getString(R.string.error_fetching_event_message)
30+
return
31+
}
32+
33+
compositeDisposable.add(sponsorService.fetchSponsorsWithEvent(id)
34+
.subscribeOn(Schedulers.io())
35+
.observeOn(AndroidSchedulers.mainThread())
36+
.subscribe({
37+
mutableSponsors.value = it
38+
mutableProgress.value = false
39+
}, {
40+
Timber.e("Error fetching speaker for id $id")
41+
mutableError.value = resource.getString(R.string.error_fetching_event_message)
42+
})
43+
)
44+
}
45+
46+
override fun onCleared() {
47+
super.onCleared()
48+
compositeDisposable.clear()
49+
}
50+
}

app/src/main/res/layout/content_event.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@
237237
app:layout_constraintHorizontal_bias="0.5"
238238
app:layout_constraintStart_toStartOf="parent"
239239
app:layout_constraintTop_toBottomOf="@+id/aboutEventContainer"
240+
android:descendantFocusability="blocksDescendants"
240241
tools:visibility="visible">
241242

242243
<View
@@ -478,6 +479,8 @@
478479
app:layout_constraintBottom_toTopOf="@+id/similarEventsContainer"
479480
app:layout_constraintEnd_toEndOf="parent"
480481
app:layout_constraintStart_toStartOf="parent"
482+
android:descendantFocusability="blocksDescendants"
483+
android:background="?selectableItemBackground"
481484
tools:visibility="visible">
482485
<View
483486
android:layout_width="match_parent"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:orientation="vertical"
4+
android:layout_width="match_parent"
5+
android:layout_height="match_parent">
6+
<androidx.recyclerview.widget.RecyclerView
7+
android:id="@+id/sponsorsDetailRecyclerView"
8+
android:layout_width="match_parent"
9+
android:layout_height="wrap_content"
10+
android:layout_margin="@dimen/layout_margin_medium"/>
11+
<ProgressBar
12+
android:id="@+id/sponsorDetailProgressBar"
13+
android:layout_width="wrap_content"
14+
android:layout_height="wrap_content"
15+
android:layout_gravity="center"/>
16+
</LinearLayout>

0 commit comments

Comments
 (0)