瀏覽代碼

wip: vote on poll

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
Marcel Hibbe 2 年之前
父節點
當前提交
7d8aebe234

+ 2 - 1
app/src/main/java/com/nextcloud/talk/api/NcApi.java

@@ -538,7 +538,8 @@ public interface NcApi {
 
     @POST
     Observable<PollOverall> votePoll(@Header("Authorization") String authorization,
-                                     @Url String url);
+                                     @Url String url,
+                                     @Query("optionIds[]") List<Integer> optionIds);
 
     @DELETE
     Observable<PollOverall> closePoll(@Header("Authorization") String authorization,

+ 8 - 1
app/src/main/java/com/nextcloud/talk/polls/model/Poll.kt

@@ -14,4 +14,11 @@ data class Poll(
     val votedSelf: List<Int>?,
     val numVoters: Int,
     val details: List<PollDetails>?
-)
+) {
+    companion object {
+        const val STATUS_OPEN: Int = 0
+        const val STATUS_CLOSED: Int = 1
+        const val RESULT_MODE_PUBLIC: Int = 0
+        const val RESULT_MODE_HIDDEN: Int = 1
+    }
+}

+ 2 - 0
app/src/main/java/com/nextcloud/talk/polls/repositories/PollRepository.kt

@@ -6,4 +6,6 @@ import io.reactivex.Observable
 interface PollRepository {
 
     fun getPoll(roomToken: String, pollId: String): Observable<Poll>?
+
+    fun vote(roomToken: String, pollId: String, option: Int): Observable<Poll>?
 }

+ 18 - 5
app/src/main/java/com/nextcloud/talk/polls/repositories/PollRepositoryImpl.kt

@@ -33,12 +33,12 @@ import io.reactivex.Observable
 class PollRepositoryImpl(private val ncApi: NcApi, private val currentUserProvider: CurrentUserProvider) :
     PollRepository {
 
-    override fun getPoll(roomToken: String, pollId: String): Observable<Poll> {
+    val credentials = ApiUtils.getCredentials(
+        currentUserProvider.currentUser?.username,
+        currentUserProvider.currentUser?.token
+    )
 
-        val credentials = ApiUtils.getCredentials(
-            currentUserProvider.currentUser?.username,
-            currentUserProvider.currentUser?.token
-        )
+    override fun getPoll(roomToken: String, pollId: String): Observable<Poll> {
 
         return ncApi.getPoll(
             credentials,
@@ -69,6 +69,19 @@ class PollRepositoryImpl(private val ncApi: NcApi, private val currentUserProvid
         // )
     }
 
+    override fun vote(roomToken: String, pollId: String, option: Int): Observable<Poll>? {
+
+        return ncApi.votePoll(
+            credentials,
+            ApiUtils.getUrlForPoll(
+                currentUserProvider.currentUser?.baseUrl,
+                roomToken,
+                pollId
+            ),
+            arrayOf(option).asList()
+        ).map { mapToPoll(it.ocs?.data!!) }
+    }
+
     companion object {
 
         private fun mapToPoll(pollResponse: PollResponse): Poll {

+ 5 - 1
app/src/main/java/com/nextcloud/talk/polls/ui/PollMainDialogFragment.kt

@@ -60,7 +60,11 @@ class PollMainDialogFragment(
                 PollViewModel.InitialState -> {}
                 is PollViewModel.PollClosedState -> TODO()
                 is PollViewModel.PollOpenState -> {
-                    val contentFragment = PollVoteFragment(viewModel)
+                    val contentFragment = PollVoteFragment(
+                        viewModel,
+                        roomToken,
+                        pollId
+                    )
                     val transaction = childFragmentManager.beginTransaction()
                     transaction.replace(binding.messagePollContentFragment.id, contentFragment)
                     transaction.commit()

+ 31 - 13
app/src/main/java/com/nextcloud/talk/polls/ui/PollVoteFragment.kt

@@ -37,7 +37,11 @@ import com.nextcloud.talk.polls.viewmodels.PollVoteViewModel
 import javax.inject.Inject
 
 @AutoInjector(NextcloudTalkApplication::class)
-class PollVoteFragment(private val parentViewModel: PollViewModel) : Fragment() {
+class PollVoteFragment(
+    private val parentViewModel: PollViewModel,
+    private val roomToken: String,
+    private val pollId: String
+) : Fragment() {
 
     @Inject
     lateinit var viewModelFactory: ViewModelProvider.Factory
@@ -70,29 +74,43 @@ class PollVoteFragment(private val parentViewModel: PollViewModel) : Fragment()
                 val poll = state.poll
                 binding.radioGroup.removeAllViews()
                 poll.options?.map { option ->
-                    RadioButton(context)
-                        .apply { text = option }
-                        .also {
-                            it.setOnClickListener {
-                                // todo
-                                Log.d("bb", "click1")
-                            }
-                        }
-                }?.forEach {
-                    binding.radioGroup.addView(it)
+                    RadioButton(context).apply { text = option }
+                }?.forEachIndexed { index, radioButton ->
+                    radioButton.id = index
+                    binding.radioGroup.addView(radioButton)
                 }
             }
         }
+
+        viewModel.viewState.observe(viewLifecycleOwner) { state ->
+            when (state) {
+                PollVoteViewModel.InitialState -> {}
+                is PollVoteViewModel.PollVoteFailedState -> {
+                    Log.d(TAG, "fail")
+                }
+                is PollVoteViewModel.PollVoteSuccessState -> {
+                    parentViewModel.voted()
+                }
+            }
+        }
+
         binding.radioGroup.setOnCheckedChangeListener { group, checkedId ->
-            // todo set selected in viewmodel
+            // todo set selected in viewmodel.
             Log.d("bb", "click")
         }
         // todo observe viewmodel checked, set view checked with it
-        // todo listen to button click, submit
+
+        binding.submitVote.setOnClickListener {
+            viewModel.vote(roomToken, pollId, binding.radioGroup.checkedRadioButtonId)
+        }
     }
 
     override fun onDestroyView() {
         super.onDestroyView()
         _binding = null
     }
+
+    companion object {
+        private val TAG = PollVoteFragment::class.java.simpleName
+    }
 }

+ 10 - 9
app/src/main/java/com/nextcloud/talk/polls/viewmodels/PollViewModel.kt

@@ -31,6 +31,7 @@ class PollViewModel @Inject constructor(private val repository: PollRepository)
     sealed interface ViewState
     object InitialState : ViewState
     open class PollOpenState(val poll: Poll) : ViewState
+    open class PollVotedState(val poll: Poll) : ViewState
     open class PollClosedState(val poll: Poll) : ViewState
 
     private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState)
@@ -46,14 +47,9 @@ class PollViewModel @Inject constructor(private val repository: PollRepository)
         loadPoll()
     }
 
-    // private fun loadPoll() {
-    //     disposable = repository.getPoll(roomToken, pollId)
-    //         ?.subscribeOn(Schedulers.io())
-    //         ?.observeOn(AndroidSchedulers.mainThread())
-    //         ?.subscribe { poll ->
-    //             _viewState.value = PollOpenState(poll)
-    //         }
-    // }
+    fun voted() {
+        loadPoll() // TODO load other view
+    }
 
     private fun loadPoll() {
         repository.getPoll(roomToken, pollId)
@@ -83,7 +79,12 @@ class PollViewModel @Inject constructor(private val repository: PollRepository)
         }
 
         override fun onComplete() {
-            _viewState.value = PollOpenState(poll)
+            // TODO check attributes and decide if poll is open/closed/selfvoted...
+
+            when (poll.status) {
+                Poll.STATUS_OPEN -> _viewState.value = PollOpenState(poll)
+                Poll.STATUS_CLOSED -> _viewState.value = PollClosedState(poll)
+            }
         }
     }
 

+ 57 - 1
app/src/main/java/com/nextcloud/talk/polls/viewmodels/PollVoteViewModel.kt

@@ -21,12 +21,31 @@
 
 package com.nextcloud.talk.polls.viewmodels
 
+import android.util.Log
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
+import com.nextcloud.talk.polls.model.Poll
+import com.nextcloud.talk.polls.repositories.PollRepository
+import io.reactivex.Observer
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
+import io.reactivex.schedulers.Schedulers
 import javax.inject.Inject
 
-class PollVoteViewModel @Inject constructor() : ViewModel() {
+class PollVoteViewModel @Inject constructor(private val repository: PollRepository) : ViewModel() {
+
+    sealed interface ViewState
+    object InitialState : ViewState
+    open class PollVoteSuccessState(val poll: Poll) : ViewState
+    open class PollVoteFailedState() : ViewState
+
+    private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState)
+    val viewState: LiveData<ViewState>
+        get() = _viewState
+
+    private var disposable: Disposable? = null
+
     private val _selectedOptions: MutableLiveData<List<String>> = MutableLiveData(emptyList())
     val selectedOptions: LiveData<List<String>>
         get() = _selectedOptions
@@ -34,4 +53,41 @@ class PollVoteViewModel @Inject constructor() : ViewModel() {
     fun selectOption(option: String) {
         _selectedOptions.value = listOf(option)
     }
+
+    fun vote(roomToken: String, pollId: String, option: Int) {
+        repository.vote(roomToken, pollId, option)
+            ?.doOnSubscribe { disposable = it }
+            ?.subscribeOn(Schedulers.io())
+            ?.observeOn(AndroidSchedulers.mainThread())
+            ?.subscribe(PollObserver())
+    }
+
+    override fun onCleared() {
+        super.onCleared()
+        disposable?.dispose()
+    }
+
+    inner class PollObserver : Observer<Poll> {
+
+        lateinit var poll: Poll
+
+        override fun onSubscribe(d: Disposable) = Unit
+
+        override fun onNext(response: Poll) {
+            poll = response
+        }
+
+        override fun onError(e: Throwable) {
+            Log.d(TAG, "An error occurred: $e")
+            _viewState.value = PollVoteFailedState()
+        }
+
+        override fun onComplete() {
+            _viewState.value = PollVoteSuccessState(poll)
+        }
+    }
+
+    companion object {
+        private val TAG = PollVoteViewModel::class.java.simpleName
+    }
 }

+ 1 - 1
app/src/main/res/layout/dialog_poll_vote.xml

@@ -33,7 +33,7 @@
     </RadioGroup>
 
     <com.google.android.material.button.MaterialButton
-        android:id="@+id/setStatus"
+        android:id="@+id/submitVote"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         app:cornerRadius="@dimen/button_corner_radius"