diff --git a/app/build.gradle b/app/build.gradle index 84a44145..53b53def 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,8 +4,8 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' def versionMajor = 2 -def versionMinor = 0 -def versionPatch = 2 +def versionMinor = 1 +def versionPatch = 0 def appVersionCode = versionMajor * 100 + versionMinor * 10 + versionPatch def appVersionName = "${versionMajor}.${versionMinor}.${versionPatch}" diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/api/SyncPodApi.kt b/app/src/main/kotlin/com/cyder/android/syncpod/api/SyncPodApi.kt index f8b13b97..1d136ea1 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/api/SyncPodApi.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/api/SyncPodApi.kt @@ -23,6 +23,9 @@ interface SyncPodApi { @GET("joined_rooms") fun getEnteredRooms(@Header("Authorization") token: String): Single + @GET("rooms/popular") + fun getPopularRooms(@Header("Authorization") token: String): Single + @GET("rooms") fun getRoom(@Header("Authorization") token: String, @Query("room_key") roomKey: String): Single diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/api/mapper/RoomDataMapper.kt b/app/src/main/kotlin/com/cyder/android/syncpod/api/mapper/RoomDataMapper.kt index 381865fd..3ac14158 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/api/mapper/RoomDataMapper.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/api/mapper/RoomDataMapper.kt @@ -17,6 +17,7 @@ fun RoomResponse.toModel(): Room = this.name, this.description, this.key, + this.isPublic, this.nowPlayingVideo?.toModel(), this.lastPlayedVideo?.toModel(), this.onlineUsers?.toModel()) \ No newline at end of file diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/api/request/CreateRoom.kt b/app/src/main/kotlin/com/cyder/android/syncpod/api/request/CreateRoom.kt index 634f3db7..d61f9414 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/api/request/CreateRoom.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/api/request/CreateRoom.kt @@ -4,11 +4,12 @@ package com.cyder.android.syncpod.api.request * Created by chigichan24 on 2018/03/31. */ -class CreateRoom(name: String, description: String) { - private val room = Room(name, description) +class CreateRoom(name: String, description: String, isPublic: Boolean) { + private val room = Room(name, description, isPublic) } private data class Room ( val name: String, - val description: String + val description: String, + val public: Boolean ) \ No newline at end of file diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/api/response/Response.kt b/app/src/main/kotlin/com/cyder/android/syncpod/api/response/Response.kt index 1c937dae..910df465 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/api/response/Response.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/api/response/Response.kt @@ -10,5 +10,6 @@ data class Response( val result: String, val user: User?, val room: Room?, - @SerializedName("joined_rooms") val joinedRooms: List? + @SerializedName("joined_rooms") val joinedRooms: List?, + @SerializedName("rooms") val popularRooms: List? ) \ No newline at end of file diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/api/response/Room.kt b/app/src/main/kotlin/com/cyder/android/syncpod/api/response/Room.kt index cb5a748b..5139c489 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/api/response/Room.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/api/response/Room.kt @@ -11,6 +11,7 @@ data class Room( val name: String, val description: String, val key: String, + @SerializedName("public") val isPublic: Boolean, @SerializedName("now_playing_video") val nowPlayingVideo: Video?, @SerializedName("last_played_video") val lastPlayedVideo: Video?, @SerializedName("online_users") val onlineUsers: List? diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/model/Room.kt b/app/src/main/kotlin/com/cyder/android/syncpod/model/Room.kt index 9b61e7e2..f0ea2ab4 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/model/Room.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/model/Room.kt @@ -9,6 +9,7 @@ data class Room( val name: String, val description: String, val key: String, + val isPublic: Boolean, val nowPlayingVideo: Video?, val lastPlayedVideo: Video?, val onlineUsers: List? diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/repository/RoomDataRepository.kt b/app/src/main/kotlin/com/cyder/android/syncpod/repository/RoomDataRepository.kt index c99c1704..c70b1240 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/repository/RoomDataRepository.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/repository/RoomDataRepository.kt @@ -33,9 +33,9 @@ class RoomDataRepository @Inject constructor( return syncPodWsApi.exitRoom() } - override fun createNewRoom(name: String, description: String): Single { + override fun createNewRoom(name: String, description: String, isPublic: Boolean): Single { return createNewRoomValidation(name, description) - .andThen(syncPodApi.createNewRoom(token, CreateRoom(name, description))) + .andThen(syncPodApi.createNewRoom(token, CreateRoom(name, description, isPublic))) .map { it.room } .map { it.toModel() } .subscribeOn(Schedulers.computation()) @@ -58,6 +58,14 @@ class RoomDataRepository @Inject constructor( .observeOn(AndroidSchedulers.mainThread()) } + override fun fetchPopularRooms(): Single> { + return syncPodApi.getPopularRooms(token) + .map { it.popularRooms } + .map { it.toModel() } + .subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()) + } + override fun exitForce(user: User) { syncPodWsApi.exitForce(user) } diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/repository/RoomRepository.kt b/app/src/main/kotlin/com/cyder/android/syncpod/repository/RoomRepository.kt index 5389587f..16e77975 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/repository/RoomRepository.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/repository/RoomRepository.kt @@ -11,8 +11,9 @@ import io.reactivex.Single */ interface RoomRepository { val isEntered: Flowable - fun createNewRoom(name: String, description: String): Single + fun createNewRoom(name: String, description: String, isPublic: Boolean): Single fun fetchJoinedRooms(): Single> + fun fetchPopularRooms(): Single> fun fetch(roomKey: String): Single fun joinRoom(roomKey: String): Completable fun exitRoom(): Completable diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/util/CustomBinder.kt b/app/src/main/kotlin/com/cyder/android/syncpod/util/CustomBinder.kt index 5e9ee023..75b74192 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/util/CustomBinder.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/util/CustomBinder.kt @@ -3,15 +3,17 @@ package com.cyder.android.syncpod.util import android.databinding.BindingAdapter import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView +import android.support.v7.widget.SwitchCompat import android.support.v7.widget.Toolbar import android.text.method.LinkMovementMethod import android.view.View +import android.view.animation.AccelerateDecelerateInterpolator +import android.view.animation.Animation +import android.widget.CompoundButton import android.widget.EditText import android.widget.ImageView import android.widget.TextView import com.bumptech.glide.Glide -import android.view.animation.AccelerateDecelerateInterpolator -import android.view.animation.Animation import com.cyder.android.syncpod.view.helper.ResizeAnimation import com.cyder.android.syncpod.view.helper.dpToPx import com.cyder.android.syncpod.view.helper.hideSoftwareKeyBoard @@ -102,4 +104,9 @@ fun View.hideSoftwareKeyboard(flag: Boolean) { if (flag) { hideSoftwareKeyBoard() } -} \ No newline at end of file +} + +@BindingAdapter("isChecked") +fun SwitchCompat.setCheck(listener: CompoundButton.OnCheckedChangeListener) { + setOnCheckedChangeListener(listener) +} diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/view/activity/CreateRoomActivity.kt b/app/src/main/kotlin/com/cyder/android/syncpod/view/activity/CreateRoomActivity.kt index 395a47bd..69674746 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/view/activity/CreateRoomActivity.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/view/activity/CreateRoomActivity.kt @@ -4,6 +4,7 @@ import android.content.Context import android.content.Intent import android.databinding.DataBindingUtil import android.os.Bundle +import android.widget.SimpleAdapter import com.cyder.android.syncpod.R import com.cyder.android.syncpod.databinding.ActivityCreateRoomBinding import com.cyder.android.syncpod.view.helper.setUpSnackbar @@ -26,7 +27,19 @@ class CreateRoomActivity : BaseActivity() { binding = DataBindingUtil.setContentView(this, R.layout.activity_create_room) binding.viewModel = viewModel + viewModel.resources = this.resources viewModel.callback = setUpSnackbar() + setUpSpinner() + } + + private fun setUpSpinner() { + val adapter = SimpleAdapter( + this, + viewModel.publishingSettingItems, + R.layout.spinner_item_with_description, + viewModel.publishingSettingKeys, + intArrayOf(R.id.title, R.id.description)) + binding.publishingSetting.adapter = adapter } companion object { diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/view/activity/TopActivity.kt b/app/src/main/kotlin/com/cyder/android/syncpod/view/activity/TopActivity.kt index de5971d8..cbc9c1e4 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/view/activity/TopActivity.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/view/activity/TopActivity.kt @@ -7,6 +7,7 @@ import android.databinding.DataBindingUtil import android.databinding.ObservableList import android.os.Bundle import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView import android.view.ViewGroup import com.cyder.android.syncpod.R import com.cyder.android.syncpod.databinding.ActivityTopBinding @@ -41,7 +42,8 @@ class TopActivity : BaseActivity() { setUpDialog() viewModel.snackbarCallback = setUpSnackbar() - initRecyclerView() + initRecyclerView(binding.joinedRoomRecycler, viewModel.joinedRoomViewModels) + initRecyclerView(binding.popularRoomRecycler, viewModel.populardRoomViewModels) } private fun setUpDialog() { @@ -62,15 +64,15 @@ class TopActivity : BaseActivity() { viewModel.dialogCallback = callback } - private fun initRecyclerView() { - binding.joinedRoomRecycler.isNestedScrollingEnabled = false - val adapter = JoinedRoomAdapter(viewModel.roomViewModels) - binding.joinedRoomRecycler.adapter = adapter - binding.joinedRoomRecycler.layoutManager = LinearLayoutManager(this) + private fun initRecyclerView(recyclerView: RecyclerView, viewModels: ObservableList) { + recyclerView.isNestedScrollingEnabled = false + val adapter = RoomAdapter(viewModels) + recyclerView.adapter = adapter + recyclerView.layoutManager = LinearLayoutManager(this@TopActivity) } - inner class JoinedRoomAdapter(list: ObservableList) : ObservableListAdapter>(list) { + inner class RoomAdapter(list: ObservableList) : ObservableListAdapter>(list) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder = BindingHolder(parent, R.layout.item_room) diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/view/fragment/ChatFragment.kt b/app/src/main/kotlin/com/cyder/android/syncpod/view/fragment/ChatFragment.kt index ea4735c5..4ccded41 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/view/fragment/ChatFragment.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/view/fragment/ChatFragment.kt @@ -70,7 +70,7 @@ class ChatFragment : BaseFragment() { val lastVisiblePosition = manager.findLastVisibleItemPosition() val lastListPosition = adapter.itemCount - 1 if (lastListPosition - 1 == lastVisiblePosition) { - binding.chatList.smoothScrollToPosition(lastListPosition) + binding.chatList.smoothScrollToPosition(lastListPosition + 1) } } } diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/viewmodel/CreateRoomActivityViewModel.kt b/app/src/main/kotlin/com/cyder/android/syncpod/viewmodel/CreateRoomActivityViewModel.kt index 8d84e779..6a8984f2 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/viewmodel/CreateRoomActivityViewModel.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/viewmodel/CreateRoomActivityViewModel.kt @@ -1,6 +1,8 @@ package com.cyder.android.syncpod.viewmodel +import android.content.res.Resources import android.databinding.ObservableField +import android.databinding.ObservableInt import com.cyder.android.syncpod.R import com.cyder.android.syncpod.repository.RoomRepository import com.cyder.android.syncpod.util.NotFilledFormsException @@ -17,6 +19,21 @@ class CreateRoomActivityViewModel @Inject constructor( ) : ActivityViewModel() { var roomName: ObservableField = ObservableField() var roomDescription: ObservableField = ObservableField() + var publishingSetting = ObservableInt() + lateinit var resources: Resources + val publishingSettingItems: MutableList> by lazy { + val publicRoom = hashMapOf( + ID to PUBLIC_ROOM, + TITLE to resources.getString(R.string.public_room), + DESCRIPTION to resources.getString(R.string.public_room_description)) + val privateRoom = hashMapOf( + ID to PRIVATE_ROOM, + TITLE to resources.getString(R.string.private_room), + DESCRIPTION to resources.getString(R.string.private_room_description)) + mutableListOf(publicRoom, privateRoom) + } + + val publishingSettingKeys = arrayOf(TITLE, DESCRIPTION) var callback: SnackbarCallback? = null override fun onStart() { @@ -37,7 +54,9 @@ class CreateRoomActivityViewModel @Inject constructor( fun onBackButtonClicked() = navigator.closeActivity() fun onSubmit() { - repository.createNewRoom(roomName.get() ?: "", roomDescription.get() ?: "") + val isPublic = publishingSettingItems[publishingSetting.get()][ID] == PUBLIC_ROOM + + repository.createNewRoom(roomName.get() ?: "", roomDescription.get() ?: "", isPublic) .subscribe({ response -> repository.joinRoom(response.key) .subscribe({ @@ -53,4 +72,12 @@ class CreateRoomActivityViewModel @Inject constructor( } }) } + + companion object { + private const val ID = "id" + private const val TITLE = "title" + private const val DESCRIPTION = "description" + private const val PUBLIC_ROOM = "public_room" + private const val PRIVATE_ROOM = "private_room" + } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/cyder/android/syncpod/viewmodel/TopActivityViewModel.kt b/app/src/main/kotlin/com/cyder/android/syncpod/viewmodel/TopActivityViewModel.kt index 60f3ccc9..d26f2241 100644 --- a/app/src/main/kotlin/com/cyder/android/syncpod/viewmodel/TopActivityViewModel.kt +++ b/app/src/main/kotlin/com/cyder/android/syncpod/viewmodel/TopActivityViewModel.kt @@ -11,6 +11,7 @@ import com.cyder.android.syncpod.util.CannotJoinRoomException import com.cyder.android.syncpod.view.helper.Navigator import com.cyder.android.syncpod.viewmodel.base.ActivityViewModel import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.rxkotlin.Singles import javax.inject.Inject /** @@ -22,9 +23,11 @@ class TopActivityViewModel @Inject constructor( private val navigator: Navigator ) : ActivityViewModel() { - var roomViewModels: ObservableList = ObservableArrayList() + var joinedRoomViewModels: ObservableList = ObservableArrayList() + var populardRoomViewModels: ObservableList = ObservableArrayList() var isLoading: ObservableBoolean = ObservableBoolean() var hasEntered: ObservableBoolean = ObservableBoolean(false) + var hasPopularRoom: ObservableBoolean = ObservableBoolean(false) var errorMessageId: Int? = null var dialogCallback: DialogCallback? = null var snackbarCallback: SnackbarCallback? = null @@ -73,23 +76,26 @@ class TopActivityViewModel @Inject constructor( } private fun getRooms() { - roomRepository.fetchJoinedRooms() - .map { convertToViewModel(it) } - .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ response -> - response.forEachIndexed { index, viewModel -> - when (index) { - in 0..(this.roomViewModels.size - 1) -> - if (isChanged(this.roomViewModels[index], viewModel)) { - this.roomViewModels[index] = viewModel - } - else -> this.roomViewModels.add(viewModel) - } - } + Singles.zip( + roomRepository.fetchJoinedRooms() + .map { convertToViewModel(it) } + .observeOn(AndroidSchedulers.mainThread()), + roomRepository.fetchPopularRooms() + .map { convertToViewModel(it) } + .observeOn(AndroidSchedulers.mainThread()) + ) + .subscribe({ + val joinedRooms = it.first + joinedRoomViewModels.clear() + joinedRoomViewModels.addAll(joinedRooms) + hasEntered.set(joinedRooms.isNotEmpty()) + + val popularRooms = it.second + populardRoomViewModels.clear() + populardRoomViewModels.addAll(popularRooms) + hasPopularRoom.set(popularRooms.isNotEmpty()) + isLoading.set(false) - if (response.isNotEmpty()) { - hasEntered.set(true) - } }, { isLoading.set(false) }) @@ -98,8 +104,4 @@ class TopActivityViewModel @Inject constructor( private fun convertToViewModel(rooms: List): List { return rooms.map { RoomViewModel(roomRepository, navigator, ObservableField(it)) } } - - private fun isChanged(a: RoomViewModel, b: RoomViewModel): Boolean { - return a.room.get() != b.room.get() - } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_create_room.xml b/app/src/main/res/layout/activity_create_room.xml index bcaef97b..1c5032ea 100644 --- a/app/src/main/res/layout/activity_create_room.xml +++ b/app/src/main/res/layout/activity_create_room.xml @@ -60,6 +60,28 @@ android:inputType="textMultiLine" android:text="@={viewModel.roomDescription}" /> + + + + + + + + +