diff --git a/app/build.gradle b/app/build.gradle index dc9addd..71a4028 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,6 +3,7 @@ plugins { id 'kotlin-android' } + android { compileSdk 31 @@ -51,4 +52,8 @@ dependencies { implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.okhttp3:okhttp:4.9.0' implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.4' + + //Glide + implementation 'com.github.bumptech.glide:glide:4.12.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 94286d5..c38b213 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,12 +2,17 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/likefirst/meyouhouse/config/XAccessTokenInterceptor.kt b/app/src/main/java/com/likefirst/meyouhouse/config/XAccessTokenInterceptor.kt index ae0b156..9752266 100644 --- a/app/src/main/java/com/likefirst/meyouhouse/config/XAccessTokenInterceptor.kt +++ b/app/src/main/java/com/likefirst/meyouhouse/config/XAccessTokenInterceptor.kt @@ -9,7 +9,9 @@ class XAccessTokenInterceptor: Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val builder: Request.Builder = chain.request().newBuilder() - val jwtToken: String? = getJwt() + // TODO + // null 대신에 getUser() sharedPreferencesManager에 정의해서 사용해야 합니다 + val jwtToken: String? = null //or host or jwtToken?.let{ builder.addHeader(X_ACCESS_TOKEN, jwtToken) diff --git a/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/Article.kt b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/Article.kt new file mode 100644 index 0000000..a0c8fa1 --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/Article.kt @@ -0,0 +1,10 @@ +package com.likefirst.meyouhouse.data.dto.community + +import com.google.gson.annotations.SerializedName + +data class Article( + @SerializedName("postId") val postId : Int, + @SerializedName("content") val content : String, + @SerializedName("createdAt") val createdAt : String, + @SerializedName("commentCnt") val commentCnt : Int +) \ No newline at end of file diff --git a/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/Articles.kt b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/Articles.kt new file mode 100644 index 0000000..484c38d --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/Articles.kt @@ -0,0 +1,7 @@ +package com.likefirst.meyouhouse.data.dto.community + +import com.google.gson.annotations.SerializedName + +data class Articles( + @SerializedName("items") val items : MutableList
+) diff --git a/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/Comment.kt b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/Comment.kt new file mode 100644 index 0000000..2fc0fb1 --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/Comment.kt @@ -0,0 +1,9 @@ +package com.likefirst.meyouhouse.data.dto.community + +import com.google.gson.annotations.SerializedName + +data class Comment( + @SerializedName("id") val id : Int, + @SerializedName("content") val content : String, + @SerializedName("createdAt") val createdAt : String +) diff --git a/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/DetailArticle.kt b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/DetailArticle.kt new file mode 100644 index 0000000..ee76279 --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/DetailArticle.kt @@ -0,0 +1,10 @@ +package com.likefirst.meyouhouse.data.dto.community + +import com.google.gson.annotations.SerializedName + +data class DetailArticle( + @SerializedName("postId") val postId : Int, + @SerializedName("content") val content : String, + @SerializedName("imgs") val imgs : MutableList, + @SerializedName("comments") val comments : MutableList +) diff --git a/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/DetailImage.kt b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/DetailImage.kt new file mode 100644 index 0000000..a266b83 --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/DetailImage.kt @@ -0,0 +1,7 @@ +package com.likefirst.meyouhouse.data.dto.community + +import com.google.gson.annotations.SerializedName + +data class DetailImage( + @SerializedName("imgs") val url : MutableList, +) diff --git a/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/PostCommentResult.kt b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/PostCommentResult.kt new file mode 100644 index 0000000..2aefaf8 --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/PostCommentResult.kt @@ -0,0 +1,9 @@ +package com.likefirst.meyouhouse.data.dto.community + +import com.google.gson.annotations.SerializedName + +data class PostCommentResult ( + @SerializedName("content") val content : String, + @SerializedName("userId") val userId : Int, + @SerializedName("postId") val postId : Int +) \ No newline at end of file diff --git a/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/SelectedImage.kt b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/SelectedImage.kt new file mode 100644 index 0000000..b630758 --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/data/dto/community/SelectedImage.kt @@ -0,0 +1,8 @@ +package com.likefirst.meyouhouse.data.dto.community + +import android.net.Uri + +data class SelectedImage( + val name : String, + val uri : Uri +) diff --git a/app/src/main/java/com/likefirst/meyouhouse/ui/BaseFragment.kt b/app/src/main/java/com/likefirst/meyouhouse/ui/BaseFragment.kt index 6ea1766..fa986a7 100644 --- a/app/src/main/java/com/likefirst/meyouhouse/ui/BaseFragment.kt +++ b/app/src/main/java/com/likefirst/meyouhouse/ui/BaseFragment.kt @@ -10,16 +10,16 @@ import androidx.viewbinding.ViewBinding import com.likefirst.meyouhouse.util.Inflate abstract class BaseFragment( - private val inflate: Inflate + private val inflate: Inflate, -) : Fragment() { + ) : Fragment() { private var _binding: VB? = null protected val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + savedInstanceState: Bundle?, ): View? { _binding = inflate.invoke(inflater, container, false) @@ -36,6 +36,7 @@ abstract class BaseFragment( _binding = null } + protected abstract fun initAfterBinding() fun showToast(message: String) { diff --git a/app/src/main/java/com/likefirst/meyouhouse/ui/calendar/CalendarFragment.kt b/app/src/main/java/com/likefirst/meyouhouse/ui/calendar/CalendarFragment.kt index a93ec5f..218d5a4 100644 --- a/app/src/main/java/com/likefirst/meyouhouse/ui/calendar/CalendarFragment.kt +++ b/app/src/main/java/com/likefirst/meyouhouse/ui/calendar/CalendarFragment.kt @@ -5,6 +5,6 @@ import com.likefirst.meyouhouse.ui.BaseFragment class CalendarFragment : BaseFragment(FragmentCalendarBinding::inflate) { override fun initAfterBinding() { - TODO("Not yet implemented") + } } \ No newline at end of file diff --git a/app/src/main/java/com/likefirst/meyouhouse/ui/community/ArticleDetailActivity.kt b/app/src/main/java/com/likefirst/meyouhouse/ui/community/ArticleDetailActivity.kt new file mode 100644 index 0000000..80493d8 --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/ui/community/ArticleDetailActivity.kt @@ -0,0 +1,120 @@ +package com.likefirst.meyouhouse.ui.community + +import android.util.Log +import androidx.recyclerview.widget.LinearLayoutManager +import com.likefirst.meyouhouse.data.dto.community.* +import com.likefirst.meyouhouse.databinding.ActivityArticleDetailBinding +import com.likefirst.meyouhouse.ui.BaseActivity +import com.likefirst.meyouhouse.util.RetrofitInterface +import okhttp3.ResponseBody +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import java.text.SimpleDateFormat +import java.util.* + +class ArticleDetailActivity : + BaseActivity(ActivityArticleDetailBinding::inflate) { + + val comments = mutableListOf() + val images = mutableListOf() + + lateinit var retrofit: Retrofit + lateinit var retrofitService : RetrofitInterface + private lateinit var commentAdapter: CommentRVAdapter + private lateinit var detailImageAdapter: DetailImageRVAdapter + private var postId = 0 + private lateinit var date : String + + override fun initAfterBinding() { + postId = intent.getIntExtra(CommunityFragment.POST_ID,0) + date = intent.getStringExtra(CommunityFragment.DATE).toString() + + initCommentRV() + initDetailImageRV() + initRetrofit() + getDetailArticle() + initCommentSubmitButton() + } + + private fun initDetailImageRV() { + detailImageAdapter = DetailImageRVAdapter(images) + binding.detailImageRecyclerView.layoutManager = LinearLayoutManager(this).apply { + orientation = LinearLayoutManager.HORIZONTAL + } + binding.detailImageRecyclerView.adapter = detailImageAdapter + } + + private fun initBodyAndDateTextView(content : String, date : String) { + binding.detailBodyTextView.text = content + binding.detailDate.text = date + } + + private fun initCommentRV() { + commentAdapter = CommentRVAdapter(comments) + binding.commentRecyclerView.layoutManager = LinearLayoutManager(this) + binding.commentRecyclerView.adapter = commentAdapter + } + + + private fun initRetrofit() { + retrofit = Retrofit.Builder().baseUrl(CommunityFragment.BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .build() + + retrofitService = retrofit.create(RetrofitInterface::class.java) + } + + private fun getDetailArticle() { + retrofitService.getArticlesDetail(postId.toString()) + .enqueue(object : Callback{ + override fun onResponse( + call: Call, + response: Response, + ) { + if(response.isSuccessful.not()) return + response.body().let { + if (it == null ) return + initBodyAndDateTextView(it.content,date) + detailImageAdapter.setData(it.imgs) + commentAdapter.setData(it.comments) + } + } + override fun onFailure(call: Call, t: Throwable) { + showToast("데이터 불러오기 실패") + } + }) + } + + private fun initCommentSubmitButton() { + binding.commentSubmitButton.setOnClickListener { + val content = binding.commentEditText.text.toString() + // TODO userID를 어떻게 처리해야하는지 질문 + val userId = 1 + val comment = PostCommentResult(content,userId,postId.toInt()) + + retrofitService.postComment(comment) + .enqueue(object : Callback{ + override fun onResponse( + call: Call, + response: Response, + ) { + if(response.isSuccessful.not()) return + Log.d(TAG,response.body().toString()) + binding.commentEditText.text.clear() + getDetailArticle() + } + override fun onFailure(call: Call, t: Throwable) { + Log.d(TAG,t.message.toString()) + showToast("네트워크 오류") + } + }) + } + } + + companion object { + const val TAG = "ArticleDetailAt" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/likefirst/meyouhouse/ui/community/ArticlePostingActivity.kt b/app/src/main/java/com/likefirst/meyouhouse/ui/community/ArticlePostingActivity.kt new file mode 100644 index 0000000..c75ad58 --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/ui/community/ArticlePostingActivity.kt @@ -0,0 +1,173 @@ +package com.likefirst.meyouhouse.ui.community + +import android.annotation.SuppressLint +import android.content.Intent +import android.net.Uri +import android.util.Log +import androidx.core.net.toUri +import androidx.recyclerview.widget.LinearLayoutManager +import com.likefirst.meyouhouse.data.dto.community.SelectedImage +import com.likefirst.meyouhouse.databinding.ActivityArticlePostingBinding +import com.likefirst.meyouhouse.ui.BaseActivity +import com.likefirst.meyouhouse.util.MultiPartResolver +import com.likefirst.meyouhouse.util.RetrofitInterface +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MultipartBody +import okhttp3.RequestBody.Companion.asRequestBody +import okhttp3.ResponseBody +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import java.io.File + + +class ArticlePostingActivity : + BaseActivity(ActivityArticlePostingBinding::inflate) { + + lateinit var retrofit: Retrofit + lateinit var retrofitService : RetrofitInterface + + override fun initAfterBinding() { + initSelectedImageRV() + initPhotoButton() + initRetroFit() + initSubmitButton() + initCancelButton() + } + + + private val selectedImageList = mutableListOf() + private lateinit var selectedImageAdapter : SelectedImageRVAdapter + + private fun initPhotoButton() { + binding.selectPhotoButton.setOnClickListener { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply { + addCategory(Intent.CATEGORY_OPENABLE) + putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) + type = "image/*" + } + startActivityForResult(intent, READ_REQUEST_CODE) + } + } + + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == READ_REQUEST_CODE) { + if (resultCode == RESULT_OK) { + //선택된 이미지 리스트 초기화 + selectedImageList.clear() + if (data == null) return + val clipData = data.getClipData() + if (clipData == null) { + Log.d(TAG, "한장일때" + data.data.toString()) + selectedImageList.add(SelectedImage("img1",data.data.toString().toUri())) + selectedImageAdapter.setData(selectedImageList) + binding.selectedImageCountTextView.text = "${1}/5" + } else{ + if (clipData.itemCount > 5) { + showToast("사진은 5장까지만 등록가능해요") + } else { + Log.d(TAG, clipData.itemCount.toString()) + for (i in 0 until clipData.itemCount) { + val imageSingleUri = clipData.getItemAt(i).uri + selectedImageList.add(SelectedImage("img${i+1}",imageSingleUri)) + Log.d(TAG, "${i}장일때" + imageSingleUri.toString()) + } + selectedImageAdapter.setData(selectedImageList) + binding.selectedImageCountTextView.text = "${clipData.itemCount}/5" + } + } + } + } + } + + private fun initSelectedImageRV() { + val initList = mutableListOf() + selectedImageAdapter = SelectedImageRVAdapter(initList) + binding.selectedPhotoRecyclerView.layoutManager = LinearLayoutManager(this).apply { + orientation = LinearLayoutManager.HORIZONTAL + } + binding.selectedPhotoRecyclerView.adapter = selectedImageAdapter + } + + private fun initCancelButton() { + binding.cancelTextButton.setOnClickListener { + selectedImageList.clear() + finish() + } + } + + private fun initRetroFit() { + retrofit = Retrofit.Builder() + .baseUrl(CommunityFragment.BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .build() + retrofitService = retrofit.create(RetrofitInterface::class.java) + } + + private fun initSubmitButton() { + binding.submitTextButton.setOnClickListener { + showToast("등록") + val userId = 1 + val homeId = 1 + val content = binding.bodyEditText.text.toString() + val files = arrayListOf() + selectedImageList.forEachIndexed { index, selectedImage -> + val file = File(selectedImage.uri.path) + + } + val fUserId = FormDataUtil.getBody("userId",userId) + val fHomeId = FormDataUtil.getBody("homeId",userId) + val fContent = FormDataUtil.getBody("content",userId) + } + } + + //핸드폰 갤러리에 있는 사진의 uri 를 통해 경로를 얻는 것. + @SuppressLint("Range") + fun getPathFromUri(uri: Uri): String { + val cursor = contentResolver.query(uri, null, null, null, null) + cursor!!.moveToNext() + val path = cursor.getString(cursor!!.getColumnIndex("_data")) + cursor.close() + + return path + } + + override fun onDestroy() { + super.onDestroy() + selectedImageList.clear() + Log.d(TAG,"onDestoryed! list be cleard") + } + + + companion object { + const val READ_REQUEST_CODE = 1000 + const val TAG = "ArticlePostAv" + } +} + +object FormDataUtil { + + fun getBody(key: String, value: Any): MultipartBody.Part { + return MultipartBody.Part.createFormData(key, value.toString()) + } + + fun getImageBody(key: String, file: File): MultipartBody.Part { + return MultipartBody.Part.createFormData( + name = key, + filename = file.name, + body = file.asRequestBody("image/*".toMediaType()) + ) + } + + fun getVideoBody(key: String, file: File): MultipartBody.Part { + return MultipartBody.Part.createFormData( + name = key, + filename = file.name, + body = file.asRequestBody("video/*".toMediaType()) + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/likefirst/meyouhouse/ui/community/ArticleRVAdapter.kt b/app/src/main/java/com/likefirst/meyouhouse/ui/community/ArticleRVAdapter.kt new file mode 100644 index 0000000..9b89bc1 --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/ui/community/ArticleRVAdapter.kt @@ -0,0 +1,49 @@ +package com.likefirst.meyouhouse.ui.community + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import android.widget.Toast +import androidx.recyclerview.widget.RecyclerView +import com.likefirst.meyouhouse.data.dto.community.Article +import com.likefirst.meyouhouse.databinding.ItemCommunityRvBinding +import java.text.SimpleDateFormat +import java.util.* + +class ArticleRVAdapter(val Articles : MutableList
, private val viewOnClickListener : (Int,String)->Unit) : RecyclerView.Adapter() { + + inner class ViewHolder(private val binding: ItemCommunityRvBinding) : RecyclerView.ViewHolder(binding.root) { + fun bind(article : Article) { + binding.articleBodyTextView.text = article.content + binding.communityDate.text = article.createdAt + binding.commentCountTextView.text = article.commentCnt.toString() + binding.root.setOnClickListener { + viewOnClickListener(article.postId,article.createdAt) + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder(ItemCommunityRvBinding.inflate(LayoutInflater.from(parent.context),parent,false)) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(Articles[position]) + } + + override fun getItemCount(): Int { + return Articles.size + } + + + @SuppressLint("NotifyDataSetChanged") + fun setData(list : MutableList
){ + Articles.clear() + Articles.addAll(list) + notifyDataSetChanged() + } + +} diff --git a/app/src/main/java/com/likefirst/meyouhouse/ui/community/CommentRVAdapter.kt b/app/src/main/java/com/likefirst/meyouhouse/ui/community/CommentRVAdapter.kt new file mode 100644 index 0000000..ccacfcb --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/ui/community/CommentRVAdapter.kt @@ -0,0 +1,40 @@ +package com.likefirst.meyouhouse.ui.community + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.likefirst.meyouhouse.data.dto.community.Article +import com.likefirst.meyouhouse.data.dto.community.Comment +import com.likefirst.meyouhouse.databinding.ItemCommentRvBinding +import com.likefirst.meyouhouse.databinding.ItemCommunityRvBinding + +class CommentRVAdapter(val Comments : MutableList) : RecyclerView.Adapter() { + + inner class ViewHolder(private val binding: ItemCommentRvBinding) : RecyclerView.ViewHolder(binding.root) { + fun bind(comment : Comment) { + binding.commentBodyTextView.text = comment.content + binding.commentDetailDate.text = comment.createdAt + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder(ItemCommentRvBinding.inflate(LayoutInflater.from(parent.context),parent,false)) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(Comments[position]) + } + + override fun getItemCount(): Int { + return Comments.size + } + + @SuppressLint("NotifyDataSetChanged") + fun setData(list : MutableList){ + Comments.clear() + Comments.addAll(list) + notifyDataSetChanged() + } + +} diff --git a/app/src/main/java/com/likefirst/meyouhouse/ui/community/CommunityFragment.kt b/app/src/main/java/com/likefirst/meyouhouse/ui/community/CommunityFragment.kt index 57af88c..50d97d2 100644 --- a/app/src/main/java/com/likefirst/meyouhouse/ui/community/CommunityFragment.kt +++ b/app/src/main/java/com/likefirst/meyouhouse/ui/community/CommunityFragment.kt @@ -1,10 +1,93 @@ package com.likefirst.meyouhouse.ui.community +import android.content.Intent +import android.util.Log +import androidx.recyclerview.widget.LinearLayoutManager +import com.likefirst.meyouhouse.data.dto.community.Article +import com.likefirst.meyouhouse.data.dto.community.Articles import com.likefirst.meyouhouse.databinding.FragmentCommunityBinding import com.likefirst.meyouhouse.ui.BaseFragment +import com.likefirst.meyouhouse.util.RetrofitInterface +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory class CommunityFragment : BaseFragment(FragmentCommunityBinding::inflate) { + + //Dummy Article Data + lateinit var retrofit: Retrofit + lateinit var retrofitService : RetrofitInterface + private lateinit var articleAdapter : ArticleRVAdapter + val Articles = mutableListOf
() + override fun initAfterBinding() { - TODO("Not yet implemented") + + initFloatButton() + initRetroFit() + // TODO 리사이클러뷰 만들기 + // TODO 게시글 눌렀을때 상세정보 뿌려주기 + initArticleRecyclerView() + getArticles() + } + + private fun getArticles(){ + retrofitService.getArticles() + .enqueue(object :Callback{ + override fun onResponse(call: Call, response: Response) { + Log.d(TAG,"netwokring good") + if(response.isSuccessful.not()) return + response.body()?.let { + articleAdapter.setData(it.items) + } + } + override fun onFailure(call: Call, t: Throwable) { + Log.d(TAG,t.message.toString()) + showToast("데이터 가져오기 실패!") + } + }) + } + + + private fun initFloatButton() { + binding.addArticleFloatingButton.setOnClickListener { + context?.let{ + val intent = Intent(it,ArticlePostingActivity::class.java) + startActivity(intent) + } + } + } + + private fun initArticleRecyclerView() { + articleAdapter = ArticleRVAdapter(Articles, viewOnClickListener = { postid,date -> + val postId = postid + val date = date + context?.let{ + val intent = Intent(it,ArticleDetailActivity::class.java) + intent.putExtra(POST_ID,postId) + intent.putExtra(DATE,date) + startActivity(intent) + } + }) + binding.communityArticleRecyclerView.layoutManager = LinearLayoutManager(context) + binding.communityArticleRecyclerView.adapter = articleAdapter + } + + private fun initRetroFit() { + retrofit = Retrofit.Builder() + .baseUrl(BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .build() + retrofitService = retrofit.create(RetrofitInterface::class.java) + } + + + + companion object { + const val TAG = "CommunityFg" + const val BASE_URL = "http://52.78.12.56:8080" + const val POST_ID = "POST_ID" + const val DATE = "DATE" } } \ No newline at end of file diff --git a/app/src/main/java/com/likefirst/meyouhouse/ui/community/DetailImageRVAdapter.kt b/app/src/main/java/com/likefirst/meyouhouse/ui/community/DetailImageRVAdapter.kt new file mode 100644 index 0000000..d44594b --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/ui/community/DetailImageRVAdapter.kt @@ -0,0 +1,42 @@ +package com.likefirst.meyouhouse.ui.community + +import android.annotation.SuppressLint +import android.util.Log +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import com.likefirst.meyouhouse.data.dto.community.DetailImage +import com.likefirst.meyouhouse.databinding.ItemDetailImageRvBinding + +class DetailImageRVAdapter (private val Images : MutableList) : RecyclerView.Adapter() { + + inner class ViewHolder(private val binding: ItemDetailImageRvBinding) : RecyclerView.ViewHolder(binding.root) { + fun bind(Image: String) { + Glide.with(binding.detailImageView.context) + .load(Image) + .into(binding.detailImageView) + Log.d("Adapter",Image) + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder(ItemDetailImageRvBinding.inflate(LayoutInflater.from(parent.context),parent,false)) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(Images[position]) + } + + override fun getItemCount(): Int { + return Images.size + } + + @SuppressLint("NotifyDataSetChanged") + fun setData(list : MutableList){ + Images.clear() + Images.addAll(list) + notifyDataSetChanged() + } + +} diff --git a/app/src/main/java/com/likefirst/meyouhouse/ui/community/SelectedImageRVAdapter.kt b/app/src/main/java/com/likefirst/meyouhouse/ui/community/SelectedImageRVAdapter.kt new file mode 100644 index 0000000..db95c3b --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/ui/community/SelectedImageRVAdapter.kt @@ -0,0 +1,39 @@ +package com.likefirst.meyouhouse.ui.community + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.likefirst.meyouhouse.data.dto.community.Article +import com.likefirst.meyouhouse.data.dto.community.SelectedImage +import com.likefirst.meyouhouse.databinding.ItemCommunityRvBinding +import com.likefirst.meyouhouse.databinding.ItemSelectedImageRvBinding + +class SelectedImageRVAdapter(val SelectedImages : MutableList) : RecyclerView.Adapter() { + + inner class ViewHolder(private val binding: ItemSelectedImageRvBinding) : RecyclerView.ViewHolder(binding.root) { + fun bind(SelectedImage : SelectedImage) { + binding.selectedImageView.setImageURI(SelectedImage.uri) + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder(ItemSelectedImageRvBinding.inflate(LayoutInflater.from(parent.context),parent,false)) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(SelectedImages[position]) + } + + override fun getItemCount(): Int { + return SelectedImages.size + } + + @SuppressLint("NotifyDataSetChanged") + fun setData(list : MutableList){ + SelectedImages.clear() + SelectedImages.addAll(list) + notifyDataSetChanged() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/likefirst/meyouhouse/ui/main/MainActivity.kt b/app/src/main/java/com/likefirst/meyouhouse/ui/main/MainActivity.kt index 0831ee2..b4a2d95 100644 --- a/app/src/main/java/com/likefirst/meyouhouse/ui/main/MainActivity.kt +++ b/app/src/main/java/com/likefirst/meyouhouse/ui/main/MainActivity.kt @@ -1,5 +1,6 @@ package com.likefirst.meyouhouse.ui.main +import android.util.Log import androidx.fragment.app.FragmentManager import com.likefirst.meyouhouse.R import com.likefirst.meyouhouse.databinding.ActivityMainBinding @@ -8,10 +9,20 @@ import com.likefirst.meyouhouse.ui.calendar.CalendarFragment import com.likefirst.meyouhouse.ui.community.CommunityFragment import com.likefirst.meyouhouse.ui.home.HomeFragment import com.likefirst.meyouhouse.ui.search.SearchFragment +import com.likefirst.meyouhouse.util.ApplicationClass + class MainActivity : BaseActivity(ActivityMainBinding::inflate) { override fun initAfterBinding() { + // 초기 시작시 홈화면 자동 로딩 + supportFragmentManager.popBackStack("homeFragment", FragmentManager.POP_BACK_STACK_INCLUSIVE) + supportFragmentManager.beginTransaction() + .replace(R.id.main_frm, HomeFragment()) + .addToBackStack("homeFragment") + .commitAllowingStateLoss() + + // 바텀 네비게이션 뷰 binding.mainBnv.setOnItemSelectedListener { when (it.itemId) { diff --git a/app/src/main/java/com/likefirst/meyouhouse/ui/search/SearchFragment.kt b/app/src/main/java/com/likefirst/meyouhouse/ui/search/SearchFragment.kt index 6e0b8cd..aee8fe5 100644 --- a/app/src/main/java/com/likefirst/meyouhouse/ui/search/SearchFragment.kt +++ b/app/src/main/java/com/likefirst/meyouhouse/ui/search/SearchFragment.kt @@ -5,6 +5,5 @@ import com.likefirst.meyouhouse.ui.BaseFragment class SearchFragment : BaseFragment(FragmentSearchBinding::inflate) { override fun initAfterBinding() { - } } \ No newline at end of file diff --git a/app/src/main/java/com/likefirst/meyouhouse/util/ApplicationClass.kt b/app/src/main/java/com/likefirst/meyouhouse/util/ApplicationClass.kt index 2a4d128..783fe90 100644 --- a/app/src/main/java/com/likefirst/meyouhouse/util/ApplicationClass.kt +++ b/app/src/main/java/com/likefirst/meyouhouse/util/ApplicationClass.kt @@ -3,6 +3,7 @@ package com.likefirst.meyouhouse.util import android.app.Application import android.content.Context import android.content.SharedPreferences +import android.util.Log import androidx.appcompat.app.AppCompatDelegate import com.likefirst.meyouhouse.config.XAccessTokenInterceptor import okhttp3.OkHttpClient @@ -14,7 +15,7 @@ import java.net.SocketException import java.util.concurrent.TimeUnit class ApplicationClass : Application() { - companion object{ + companion object { const val X_ACCESS_TOKEN: String = "x-access-token" // JWT Token Key const val TAG: String = "MeYou-APP" // Log, SharedPreference const val APP_DATABASE = "$TAG-DB" diff --git a/app/src/main/java/com/likefirst/meyouhouse/util/MultiPartResolver.kt b/app/src/main/java/com/likefirst/meyouhouse/util/MultiPartResolver.kt new file mode 100644 index 0000000..43eb0b4 --- /dev/null +++ b/app/src/main/java/com/likefirst/meyouhouse/util/MultiPartResolver.kt @@ -0,0 +1,52 @@ +package com.likefirst.meyouhouse.util + +import android.content.Context +import android.database.Cursor +import android.net.Uri +import android.provider.DocumentsContract +import android.provider.MediaStore +import okhttp3.MediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import java.io.File + +class MultiPartResolver { + fun createImgMultiPart(uri: Uri,filename : String, context: Context): MultipartBody.Part { + val file = File((getPath(context, uri).toString())) +// RequestBody.create(MediaType.parse("image/*"), file) -> 수정 +// val surveyBody = RequestBody.create(MediaType.parse("image/*"), file) + val surveyBody = RequestBody.create("image/*".toMediaTypeOrNull(), file) + return MultipartBody.Part.createFormData(filename, file.name, surveyBody) + } + + private fun getPath(context: Context, uri: Uri): String? { + val docId = DocumentsContract.getDocumentId(uri) + val split = docId.split(":".toRegex()).toTypedArray() + val contentUri: Uri? = MediaStore.Images.Media.EXTERNAL_CONTENT_URI + val selection = "_id=?" + val selectionArgs = arrayOf(split[1]) + return getDataColumn(context, contentUri!!, selection, selectionArgs) + } + + private fun getDataColumn( + context: Context, + uri: Uri, + selection: String?, + selectionArgs: Array? + ): String? { + var cursor: Cursor? = null + val column = "_data" + val projection = arrayOf(column) + try { + cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null) + if (cursor != null && cursor.moveToFirst()) { + val columnIndex: Int = cursor.getColumnIndexOrThrow(column) + return cursor.getString(columnIndex) + } + } finally { + cursor?.close() + } + return null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/likefirst/meyouhouse/util/RetrofitInterface.kt b/app/src/main/java/com/likefirst/meyouhouse/util/RetrofitInterface.kt index 2865ce3..040a894 100644 --- a/app/src/main/java/com/likefirst/meyouhouse/util/RetrofitInterface.kt +++ b/app/src/main/java/com/likefirst/meyouhouse/util/RetrofitInterface.kt @@ -1,5 +1,10 @@ package com.likefirst.meyouhouse.util +import com.likefirst.meyouhouse.data.dto.community.Articles +import com.likefirst.meyouhouse.data.dto.community.DetailArticle +import com.likefirst.meyouhouse.data.dto.community.PostCommentResult +import okhttp3.MultipartBody +import okhttp3.ResponseBody import retrofit2.Call import retrofit2.http.* @@ -23,4 +28,27 @@ interface RetrofitInterface { // @Path("userIdx") userIdx: Int, // @Body isSad : UserIsSad // ) : Call> + + + //Community main + @GET("/api/community/home/1") + fun getArticles() : Call + + //Community Detail + @GET("/api/community/post/{postid}") + fun getArticlesDetail(@Path("postid") postid:String) : Call + + //Community Detail comment post + @POST("/api/community/comment") + fun postComment(@Body comment : PostCommentResult) : Call + + // Community article post + @Multipart + @POST("/api/community") + fun postCommunityArticle( + @Part ("userId") userId: MultipartBody.Part, + @Part ("homeId") homeId: MultipartBody.Part, + @Part ("content") content: MultipartBody.Part, + @Part imgs: ArrayList? + ) : Call } \ No newline at end of file diff --git a/app/src/main/java/com/likefirst/meyouhouse/util/SharedPreferencesManager.kt b/app/src/main/java/com/likefirst/meyouhouse/util/SharedPreferencesManager.kt index 7306eb1..8e6dc80 100644 --- a/app/src/main/java/com/likefirst/meyouhouse/util/SharedPreferencesManager.kt +++ b/app/src/main/java/com/likefirst/meyouhouse/util/SharedPreferencesManager.kt @@ -15,4 +15,4 @@ import com.likefirst.meyouhouse.util.ApplicationClass.Companion.mSharedPreferenc // val editor = mSharedPreferences.edit() // editor.remove("jwt") // editor.commit() -//} \ No newline at end of file +//} diff --git a/app/src/main/res/drawable/bottom_nav_menu_archive_selector.xml b/app/src/main/res/drawable/bottom_nav_menu_archive_selector.xml new file mode 100644 index 0000000..0e680d7 --- /dev/null +++ b/app/src/main/res/drawable/bottom_nav_menu_archive_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bottom_nav_menu_history_selector.xml b/app/src/main/res/drawable/bottom_nav_menu_history_selector.xml new file mode 100644 index 0000000..6c95937 --- /dev/null +++ b/app/src/main/res/drawable/bottom_nav_menu_history_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bottom_nav_menu_home_selector.xml b/app/src/main/res/drawable/bottom_nav_menu_home_selector.xml new file mode 100644 index 0000000..3d6520e --- /dev/null +++ b/app/src/main/res/drawable/bottom_nav_menu_home_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bottom_nav_menu_profile_selector.xml b/app/src/main/res/drawable/bottom_nav_menu_profile_selector.xml new file mode 100644 index 0000000..5d6cbee --- /dev/null +++ b/app/src/main/res/drawable/bottom_nav_menu_profile_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_bnv_archive.xml b/app/src/main/res/drawable/ic_bnv_archive.xml new file mode 100644 index 0000000..ee5014a --- /dev/null +++ b/app/src/main/res/drawable/ic_bnv_archive.xml @@ -0,0 +1,49 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_bnv_history.xml b/app/src/main/res/drawable/ic_bnv_history.xml new file mode 100644 index 0000000..da63b07 --- /dev/null +++ b/app/src/main/res/drawable/ic_bnv_history.xml @@ -0,0 +1,28 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_bnv_home.xml b/app/src/main/res/drawable/ic_bnv_home.xml new file mode 100644 index 0000000..839785c --- /dev/null +++ b/app/src/main/res/drawable/ic_bnv_home.xml @@ -0,0 +1,21 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_bnv_profile.xml b/app/src/main/res/drawable/ic_bnv_profile.xml new file mode 100644 index 0000000..6f2e4f2 --- /dev/null +++ b/app/src/main/res/drawable/ic_bnv_profile.xml @@ -0,0 +1,21 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_icon_camera_grey.xml b/app/src/main/res/drawable/ic_icon_camera_grey.xml new file mode 100644 index 0000000..78271ec --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_camera_grey.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_icon_comment_black.xml b/app/src/main/res/drawable/ic_icon_comment_black.xml new file mode 100644 index 0000000..85bf9fd --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_comment_black.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_icon_comment_blue.xml b/app/src/main/res/drawable/ic_icon_comment_blue.xml new file mode 100644 index 0000000..4c80fd8 --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_comment_blue.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_icon_default_thumbnail_image.xml b/app/src/main/res/drawable/ic_icon_default_thumbnail_image.xml new file mode 100644 index 0000000..3f8e195 --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_default_thumbnail_image.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_icon_float_add_white.xml b/app/src/main/res/drawable/ic_icon_float_add_white.xml new file mode 100644 index 0000000..70046c4 --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_float_add_white.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_icon_float_addbtn_blue.xml b/app/src/main/res/drawable/ic_icon_float_addbtn_blue.xml new file mode 100644 index 0000000..59e0175 --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_float_addbtn_blue.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_icon_home_bell.xml b/app/src/main/res/drawable/ic_icon_home_bell.xml new file mode 100644 index 0000000..d79dbbf --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_home_bell.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_icon_home_elec.xml b/app/src/main/res/drawable/ic_icon_home_elec.xml new file mode 100644 index 0000000..0fc7408 --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_home_elec.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_icon_home_gas.xml b/app/src/main/res/drawable/ic_icon_home_gas.xml new file mode 100644 index 0000000..3feceb2 --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_home_gas.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_icon_home_logo.xml b/app/src/main/res/drawable/ic_icon_home_logo.xml new file mode 100644 index 0000000..6ffe6f4 --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_home_logo.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_icon_home_water.xml b/app/src/main/res/drawable/ic_icon_home_water.xml new file mode 100644 index 0000000..ce743ab --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_home_water.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/round_button_5.xml b/app/src/main/res/drawable/round_button_5.xml new file mode 100644 index 0000000..e3049d8 --- /dev/null +++ b/app/src/main/res/drawable/round_button_5.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/select_bnv_archive.xml b/app/src/main/res/drawable/select_bnv_archive.xml new file mode 100644 index 0000000..93fd21e --- /dev/null +++ b/app/src/main/res/drawable/select_bnv_archive.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/select_bnv_history.xml b/app/src/main/res/drawable/select_bnv_history.xml new file mode 100644 index 0000000..1a00791 --- /dev/null +++ b/app/src/main/res/drawable/select_bnv_history.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/select_bnv_home.xml b/app/src/main/res/drawable/select_bnv_home.xml new file mode 100644 index 0000000..09b8098 --- /dev/null +++ b/app/src/main/res/drawable/select_bnv_home.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/select_bnv_profile.xml b/app/src/main/res/drawable/select_bnv_profile.xml new file mode 100644 index 0000000..20d4f5e --- /dev/null +++ b/app/src/main/res/drawable/select_bnv_profile.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_bnv.png b/app/src/main/res/drawable/selector_bnv.png new file mode 100644 index 0000000..f247541 Binary files /dev/null and b/app/src/main/res/drawable/selector_bnv.png differ diff --git a/app/src/main/res/layout/activity_article_detail.xml b/app/src/main/res/layout/activity_article_detail.xml new file mode 100644 index 0000000..1db4c13 --- /dev/null +++ b/app/src/main/res/layout/activity_article_detail.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_article_posting.xml b/app/src/main/res/layout/activity_article_posting.xml new file mode 100644 index 0000000..dbbb799 --- /dev/null +++ b/app/src/main/res/layout/activity_article_posting.xml @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_community.xml b/app/src/main/res/layout/fragment_community.xml index 77d9ef6..222defe 100644 --- a/app/src/main/res/layout/fragment_community.xml +++ b/app/src/main/res/layout/fragment_community.xml @@ -1,6 +1,62 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 63d12a4..a6f17ee 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -1,7 +1,312 @@ - + + + android:layout_height="match_parent" + android:background="#f8f9fa"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/app/src/main/res/layout/item_comment_rv.xml b/app/src/main/res/layout/item_comment_rv.xml new file mode 100644 index 0000000..c1a82b9 --- /dev/null +++ b/app/src/main/res/layout/item_comment_rv.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_community_rv.xml b/app/src/main/res/layout/item_community_rv.xml new file mode 100644 index 0000000..3120b1a --- /dev/null +++ b/app/src/main/res/layout/item_community_rv.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_detail_image_rv.xml b/app/src/main/res/layout/item_detail_image_rv.xml new file mode 100644 index 0000000..bf0b7c8 --- /dev/null +++ b/app/src/main/res/layout/item_detail_image_rv.xml @@ -0,0 +1,27 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_selected_image_rv.xml b/app/src/main/res/layout/item_selected_image_rv.xml new file mode 100644 index 0000000..0e7ef6a --- /dev/null +++ b/app/src/main/res/layout/item_selected_image_rv.xml @@ -0,0 +1,29 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5572221..a3cb5c0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,9 @@ MeYouHouse + 익명 + 커뮤니티 + 글쓰기 + 취소 + 등록 + 글을 작성해 주세요. \ No newline at end of file