Skip to content

Commit

Permalink
(#2) Add Notice Detail feature
Browse files Browse the repository at this point in the history
  • Loading branch information
myung jun Hyun authored and myung6024 committed Nov 22, 2019
1 parent 59f1901 commit 90a5510
Show file tree
Hide file tree
Showing 28 changed files with 765 additions and 45 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,4 @@ dependencies {
implementation 'joda-time:joda-time:2.10.4'
}
apply plugin: 'com.google.gms.google-services'
com.google.gms.googleservices.GoogleServicesPlugin.config.disableVersionCheck = true
com.google.gms.googleservices.GoogleServicesPlugin.config.disableVersionCheck = true
17 changes: 9 additions & 8 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mashup">
package="com.mashup">

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

Expand All @@ -11,18 +11,19 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".app.noticedetail.NoticeDetailActivity"></activity>
<activity android:name=".SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.mashup.app.notices.NoticesActivity"
android:name=".app.notices.NoticesActivity"
android:label="@string/title_activity_notice"
android:theme="@style/AppTheme.NoActionBar">
</activity>
<activity android:name=".app.auth.LoginActivity"/>
android:theme="@style/AppTheme.NoActionBar"></activity>
<activity android:name=".app.auth.LoginActivity" />
</application>

</manifest>
</manifest>
6 changes: 5 additions & 1 deletion app/src/main/java/com/mashup/MashupApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package com.mashup
import android.app.Application
import com.facebook.stetho.Stetho
import com.jakewharton.threetenabp.AndroidThreeTen
import com.mashup.app.attendees.AttendeesDialogModule
import com.mashup.app.noticedetail.NoticeDetailModule
import com.mashup.app.notices.NoticeModule
import com.mashup.di.ApiModule
import com.mashup.di.ApplicationModule
Expand All @@ -27,7 +29,9 @@ class MashupApplication : Application() {
ApplicationModule,
ApiModule,
NetworkModule,
NoticeModule
NoticeModule,
NoticeDetailModule,
AttendeesDialogModule
))
}
initJSR310()
Expand Down
17 changes: 0 additions & 17 deletions app/src/main/java/com/mashup/MyApplication.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.mashup.app.attendees

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import com.mashup.databinding.AttendeesDialogFragmentBinding
import com.mashup.model.NoticeAttendance
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf

class AttendeesDialogFragment(attendanceList: List<NoticeAttendance>) : DialogFragment() {

companion object {
fun newInstance(attendanceList: List<NoticeAttendance>) = AttendeesDialogFragment(attendanceList)
const val TAG_ATTENDEES_DIALOG = "tag_attendees_dialog"
}

private val viewModel: AttendeesDialogViewModel by viewModel { parametersOf(attendanceList) }
private lateinit var viewDataBinding: AttendeesDialogFragmentBinding
private lateinit var listAdapter: AttendessDialogAdapter

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
viewDataBinding = AttendeesDialogFragmentBinding.inflate(inflater, container, false).apply {
viewmodel = viewModel
}
return viewDataBinding.root
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewDataBinding.setLifecycleOwner(this.viewLifecycleOwner)
setupListAdapter()
}

private fun setupListAdapter() {
val viewModel = viewDataBinding.viewmodel
if (viewModel != null) {
listAdapter = AttendessDialogAdapter(viewModel)
viewDataBinding.attendanceList.adapter = listAdapter
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.mashup.app.attendees

import com.mashup.model.NoticeAttendance
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module

val AttendeesDialogModule = module {
viewModel { (attendanceList: List<NoticeAttendance>) -> AttendeesDialogViewModel(attendanceList) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.mashup.app.attendees

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.mashup.model.NoticeAttendance

class AttendeesDialogViewModel(
attendanceList: List<NoticeAttendance>
) : ViewModel() {
private val _items = MutableLiveData<List<NoticeAttendance>>().apply { value = emptyList() }
val items: LiveData<List<NoticeAttendance>> = _items

init {
_items.value = attendanceList
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.mashup.app.attendees

import androidx.databinding.BindingAdapter
import androidx.recyclerview.widget.RecyclerView
import com.mashup.model.NoticeAttendance

@BindingAdapter("app:items")
fun setItems(listView: RecyclerView, items: List<NoticeAttendance>) {
(listView.adapter as AttendessDialogAdapter).submitList(items)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.mashup.app.attendees

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.mashup.databinding.AttendeesDialogItemBinding
import com.mashup.model.NoticeAttendance

class AttendessDialogAdapter(private val viewModel: AttendeesDialogViewModel) :
ListAdapter<NoticeAttendance, AttendessDialogAdapter.ViewHolder>(TaskDiffCallback()) {

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = getItem(position)

holder.bind(viewModel, item)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder.from(parent)
}

class ViewHolder private constructor(val binding: AttendeesDialogItemBinding) :
RecyclerView.ViewHolder(binding.root) {

fun bind(viewModel: AttendeesDialogViewModel, item: NoticeAttendance) {

binding.viewmodel = viewModel
binding.item = item
binding.executePendingBindings()
}

companion object {
fun from(parent: ViewGroup): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = AttendeesDialogItemBinding.inflate(layoutInflater, parent, false)

return ViewHolder(binding)
}
}
}
}

/**
* Callback for calculating the diff between two non-null items in a list.
*
* Used by ListAdapter to calculate the minimum number of changes between and old list and a new
* list that's been passed to `submitList`.
*/
class TaskDiffCallback : DiffUtil.ItemCallback<NoticeAttendance>() {
override fun areItemsTheSame(oldItem: NoticeAttendance, newItem: NoticeAttendance): Boolean {
return oldItem.pk == newItem.pk
}

override fun areContentsTheSame(oldItem: NoticeAttendance, newItem: NoticeAttendance): Boolean {
return oldItem == newItem
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.mashup.app.noticedetail

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.mashup.R
import com.mashup.model.Notice

class NoticeDetailActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.notice_detail_activity)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, NoticeDetailFragment.newInstance(
intent.getParcelableExtra<Notice>(NoticeDetailFragment.EXTRA_NOTICE))
)
.commitNow()
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.mashup.app.noticedetail

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.mashup.databinding.NoticeDetailFragmentBinding
import com.mashup.model.Notice
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf

class NoticeDetailFragment(notice: Notice) : Fragment() {

companion object {
fun newInstance(notice: Notice) = NoticeDetailFragment(notice)
const val EXTRA_NOTICE = "ExtraNotice"
const val REQUEST_NOTICE_ACTION = 1100
}

private val viewModel: NoticeDetailViewModel by viewModel { parametersOf(notice) }
private lateinit var viewDataBinding: NoticeDetailFragmentBinding


override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewDataBinding = NoticeDetailFragmentBinding.inflate(inflater, container, false).apply {
viewmodel = viewModel
}
return viewDataBinding.root
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewDataBinding.setLifecycleOwner(this.viewLifecycleOwner)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.mashup.app.noticedetail

import com.mashup.model.Notice
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module

val NoticeDetailModule = module {
viewModel { (notice: Notice) -> NoticeDetailViewModel(notice) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.mashup.app.noticedetail

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.mashup.model.Notice

class NoticeDetailViewModel(
notice: Notice
) : ViewModel() {

private val _item = MutableLiveData<Notice>()
val item: LiveData<Notice> = _item

init {
_item.value = notice
}

}
16 changes: 14 additions & 2 deletions app/src/main/java/com/mashup/app/notices/NoticeListBindings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package com.mashup.app.notices
import android.widget.TextView
import androidx.databinding.BindingAdapter
import androidx.recyclerview.widget.RecyclerView
import com.mashup.R
import com.mashup.model.Notice
import com.mashup.model.NoticeAttendance
import com.mashup.model.VoteStatus
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import java.util.*
Expand All @@ -14,13 +17,22 @@ fun setItems(listView: RecyclerView, items: List<Notice>) {
}

@BindingAdapter("app:noticeTime")
fun setNoticeTimeFormat(textView: TextView, date: Date) {
fun setNoticeTimeFormat(textView: TextView, date: Date?) {
if (date == null)
return
textView.text = DateTimeFormat.forPattern("yyyy년 M월 dd일 (E)").print(DateTime(date))
}

@BindingAdapter(value = ["app:startAt", "app:duration"])
fun setNoticeDurationFormat(textView: TextView, startAt: Date, duration: String) {
fun setNoticeDurationFormat(textView: TextView, startAt: Date?, duration: String?) {
if (startAt == null || duration == null)
return
val startDate = DateTime(startAt)
val endDate = startDate.plusHours(DateTimeFormat.forPattern("HH:mm:ss").parseLocalTime(duration).hourOfDay)
textView.text = "${DateTimeFormat.forPattern("a h시").print(startDate)}-${DateTimeFormat.forPattern("h시").print(endDate)}"
}

@BindingAdapter("app:attendanceSize")
fun setAttendanceSize(textView: TextView, attendanceList: List<NoticeAttendance>) {
textView.text = textView.context.getString(R.string.notice_attendance_set_format(attendanceList.count { it.vote != VoteStatus.UNSELECTED }))
}
Loading

0 comments on commit 90a5510

Please sign in to comment.