Skip to content

Commit

Permalink
⚡️ :: update club
Browse files Browse the repository at this point in the history
  • Loading branch information
shw0471 committed Jul 17, 2022
1 parent 9c426e5 commit 7e738d9
Show file tree
Hide file tree
Showing 22 changed files with 799 additions and 65 deletions.
17 changes: 13 additions & 4 deletions ui/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,37 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.semicolon.shakeit">

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

<uses-feature
android:name="android.hardware.camera"
android:required="true" />

<application
android:name="com.semicolon.shakeit.ShakeItApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:usesCleartextTraffic="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Shakeit">
android:theme="@style/Theme.Shakeit"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.Shakeit">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".feature.club.ClubActivity"
android:exported="false"
android:theme="@style/Theme.AppCompat.NoActionBar" />
</application>

</manifest>
5 changes: 0 additions & 5 deletions ui/src/main/java/com/semicolon/shakeit/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ fun ShakeIt() {
composable(Screen.Main.route) {
MainScaffold(navController)
}
composable(Screen.Club.route) {
// TODO 클럽 화면으로 이동
}
}
}

Expand Down Expand Up @@ -130,8 +127,6 @@ sealed class Screen(val route: String) {
object EditProfile : Screen("profile")

object Main : Screen("main")

object Club : Screen("club")
}

sealed class BottomNavigationScreen(
Expand Down
2 changes: 2 additions & 0 deletions ui/src/main/java/com/semicolon/shakeit/ShakeItApplication.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.semicolon.shakeit;

import android.app.Application
import androidx.appcompat.app.AppCompatDelegate
import com.jakewharton.threetenabp.AndroidThreeTen
import dagger.hilt.android.HiltAndroidApp

Expand All @@ -10,5 +11,6 @@ class ShakeItApplication : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
}
1 change: 0 additions & 1 deletion ui/src/main/java/com/semicolon/shakeit/component/Dialog.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.semicolon.shakeit.component

import android.widget.Space
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
Expand Down
88 changes: 88 additions & 0 deletions ui/src/main/java/com/semicolon/shakeit/component/Tab.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.semicolon.shakeit.component

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.semicolon.design.Button
import com.semicolon.design.color.primary.gray.gray900

@Composable
fun Tab(
tabItems: List<TabItem>,
selectedIndex: Int = 0,
) {
if (tabItems.isEmpty()) return
var selected by remember { mutableStateOf(tabItems[selectedIndex].label) }
Column {
Row(Modifier.fillMaxWidth()) {
tabItems.forEach {
TabItem(
modifier = Modifier.weight(1f),
isSelected = it.label == selected,
label = it.label
) {
selected = it.label
}
}
}
tabItems.first {it.label == selected}.content()
}
}

@Composable
fun TabItem(
modifier: Modifier,
isSelected: Boolean,
label: String,
onClick: () -> Unit,
) {
val interactionSource = remember { MutableInteractionSource() }
val indicatorColor by animateColorAsState(if (isSelected) Color(0xFFFF6262) else gray900)
Box(
modifier
.height(52.dp)
.clickable(
interactionSource = interactionSource,
indication = null
) { onClick() },
contentAlignment = Alignment.BottomCenter
) {
Box(
Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Button(text = label, color = Color.White)
}
Spacer(
Modifier
.fillMaxWidth()
.height(2.dp)
.background(indicatorColor)
)
}
}

data class TabItem(
val label: String,
val content: @Composable () -> Unit
)

@Preview(showBackground = true)
@Composable
fun TabPreview() {
Tab(
tabItems = listOf(
TabItem("클럽") {},
TabItem("참가자") {}
)
)
}
164 changes: 164 additions & 0 deletions ui/src/main/java/com/semicolon/shakeit/feature/club/ClubActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package com.semicolon.shakeit.feature.club

import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.lifecycleScope
import com.amazonaws.services.chime.sdk.meetings.audiovideo.*
import com.amazonaws.services.chime.sdk.meetings.audiovideo.video.RemoteVideoSource
import com.amazonaws.services.chime.sdk.meetings.audiovideo.video.VideoTileObserver
import com.amazonaws.services.chime.sdk.meetings.audiovideo.video.VideoTileState
import com.amazonaws.services.chime.sdk.meetings.realtime.RealtimeObserver
import com.amazonaws.services.chime.sdk.meetings.session.*
import com.amazonaws.services.chime.sdk.meetings.utils.logger.ConsoleLogger
import com.amazonaws.services.chime.sdk.meetings.utils.logger.LogLevel
import com.semicolon.domain.entity.room.ClubEntity
import com.semicolon.shakeit.R
import com.semicolon.shakeit.databinding.ActivityClubBinding
import com.semicolon.shakeit.feature.club.ClubActivity.IntentKey.ROOM_ID
import com.semicolon.shakeit.feature.club.ClubActivity.IntentKey.ROOM_IMAGE_PATH
import com.semicolon.shakeit.feature.club.ClubActivity.IntentKey.ROOM_PERSONNEL
import com.semicolon.shakeit.feature.club.ClubActivity.IntentKey.ROOM_TITLE
import com.semicolon.shakeit.util.makeToast
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.io.File

@AndroidEntryPoint
class ClubActivity : AppCompatActivity() {

lateinit var binding: ActivityClubBinding
lateinit var audioVideo: AudioVideoFacade

private val viewModel: ClubViewModel by viewModels()
private val friendRequestViewModel: FriendRequestViewModel by viewModels()
private val videoAdapter = VideoAdapter {
viewModel.fetchProfile(it)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_club)
val roomId = intent.getStringExtra(ROOM_ID)
val roomTitle = intent.getStringExtra(ROOM_TITLE)
val roomImagePath = intent.getStringExtra(ROOM_IMAGE_PATH)
val roomPersonnel = intent.getIntExtra(ROOM_PERSONNEL, 0)
binding.rvVideos.adapter = videoAdapter
binding.tvTitle.text = roomTitle
binding.btnLeave.setOnClickListener { finish() }
lifecycleScope.launch {
viewModel.eventFlow.collect {
when (it) {
is ClubViewModel.Event.JoinRoomEvent.Success ->
setChime(it.clubEntity)
is ClubViewModel.Event.JoinRoomEvent.Failure ->
finish()
is ClubViewModel.Event.CreateRoom.Success ->
viewModel.joinRoom(it.clubEntity.meeting.MeetingId)
is ClubViewModel.Event.CreateRoom.Failure ->
finish()
is ClubViewModel.Event.FetchProfile.Success ->
ProfileDialog(
this@ClubActivity,
friendRequestViewModel,
it.profileEntity
).createDialog()
is ClubViewModel.Event.FetchProfile.Failure ->
makeToast(this@ClubActivity, "프로필 정보를 가져오지 못했습니다")
}
}
}
if (roomId != null)
viewModel.joinRoom(roomId)
else if (roomTitle != null && roomImagePath != null && roomPersonnel != 0)
viewModel.createRoom(File(roomImagePath), roomTitle, roomPersonnel)
}

override fun onDestroy() {
runBlocking { viewModel.leaveRoom() }
if (this::audioVideo.isInitialized) {
audioVideo.stopLocalVideo()
audioVideo.stopRemoteVideo()
audioVideo.stop()
}
super.onDestroy()
}

private fun setChime(room: ClubEntity) {
val meetingSession = DefaultMeetingSession(
MeetingSessionConfiguration(
CreateMeetingResponse(room.meeting),
CreateAttendeeResponse(room.attendee!!)
),
ConsoleLogger(),
this
)
audioVideo = meetingSession.audioVideo
videoAdapter.setAudioVideo(audioVideo)
audioVideo.addAudioVideoObserver(object : AudioVideoObserver {
override fun onAudioSessionCancelledReconnect() {}
override fun onAudioSessionDropped() {}
override fun onAudioSessionStarted(reconnecting: Boolean) {}
override fun onAudioSessionStartedConnecting(reconnecting: Boolean) {}
override fun onAudioSessionStopped(sessionStatus: MeetingSessionStatus) {}
override fun onConnectionBecamePoor() {}
override fun onConnectionRecovered() {}
override fun onRemoteVideoSourceAvailable(sources: List<RemoteVideoSource>) {}
override fun onRemoteVideoSourceUnavailable(sources: List<RemoteVideoSource>) {}
override fun onVideoSessionStarted(sessionStatus: MeetingSessionStatus) {
audioVideo.startLocalVideo()
audioVideo.startRemoteVideo()
}

override fun onVideoSessionStartedConnecting() {}
override fun onVideoSessionStopped(sessionStatus: MeetingSessionStatus) {}
})
audioVideo.addVideoTileObserver(object : VideoTileObserver {
override fun onVideoTileAdded(tileState: VideoTileState) {
println("asdf " + tileState.attendeeId)
videoAdapter.addVideoTile(tileState)
}

override fun onVideoTileRemoved(tileState: VideoTileState) {
audioVideo.unbindVideoView(tileState.tileId)
videoAdapter.removeVideoTile(tileState)
}

override fun onVideoTilePaused(tileState: VideoTileState) {}
override fun onVideoTileResumed(tileState: VideoTileState) {}
override fun onVideoTileSizeChanged(tileState: VideoTileState) {}
})
audioVideo.addRealtimeObserver(object : RealtimeObserver {
override fun onAttendeesDropped(attendeeInfo: Array<AttendeeInfo>) {
println("asdf " + attendeeInfo.toList())
videoAdapter.setAttendees(attendeeInfo)
}

override fun onAttendeesJoined(attendeeInfo: Array<AttendeeInfo>) {
println("asdf " + attendeeInfo.toList())
videoAdapter.addAttendees(attendeeInfo)
}

override fun onAttendeesLeft(attendeeInfo: Array<AttendeeInfo>) {
println("asdf " + attendeeInfo.toList())
videoAdapter.removeAttendees(attendeeInfo)
}

override fun onAttendeesMuted(attendeeInfo: Array<AttendeeInfo>) {}
override fun onAttendeesUnmuted(attendeeInfo: Array<AttendeeInfo>) {}
override fun onSignalStrengthChanged(signalUpdates: Array<SignalUpdate>) {}
override fun onVolumeChanged(volumeUpdates: Array<VolumeUpdate>) {}

})
audioVideo.start()
}

object IntentKey {
const val ROOM_ID = "KEY_ROOM_ID"
const val ROOM_TITLE = "KEY_ROOM_TITLE"
const val ROOM_IMAGE_PATH = "KEY_ROOM_IMAGE"
const val ROOM_PERSONNEL = "KEY_ROOM_PERSONNEL"
}
}
Loading

0 comments on commit 7e738d9

Please sign in to comment.