diff options
Diffstat (limited to 'Client/BrzoDoLokacije/app/src/main/java/com/example')
54 files changed, 2361 insertions, 659 deletions
diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityAddPost.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityAddPost.kt index 746d8b0..aaa2733 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityAddPost.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityAddPost.kt @@ -2,6 +2,7 @@ package com.example.brzodolokacije.Activities import android.Manifest import android.app.ProgressDialog +import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.graphics.Color @@ -11,19 +12,16 @@ import android.util.Log import android.util.TypedValue import android.view.KeyEvent import android.view.View +import android.view.inputmethod.InputMethodManager import android.widget.* import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.widget.AppCompatImageView import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.core.view.setMargins -import com.example.brzodolokacije.Models.Location -import com.example.brzodolokacije.Models.LocationType import com.example.brzodolokacije.Models.PostPreview import com.example.brzodolokacije.R -import com.example.brzodolokacije.Services.GeocoderHelper import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper import okhttp3.MediaType.Companion.toMediaTypeOrNull @@ -39,7 +37,7 @@ class ActivityAddPost : AppCompatActivity() { private lateinit var takePhoto: Button private lateinit var showNextImage:Button private lateinit var showPreviousImage:Button - private lateinit var switcher: ImageSwitcher + private lateinit var switcher: ImageView private var uploadedImages:ArrayList<Uri?>?=null private lateinit var location:EditText @@ -75,7 +73,7 @@ class ActivityAddPost : AppCompatActivity() { uploadFromGallery=findViewById<View>(R.id.btnActivityAddPostUploadFromGalleryVisible) as Button showNextImage=findViewById<View>(R.id.nextImage) as Button showPreviousImage=findViewById<View>(R.id.previousImage) as Button - switcher=findViewById<View>(R.id.isActivityAddPostSwitcher) as ImageSwitcher + switcher=findViewById<View>(R.id.isActivityAddPostSwitcher) as ImageView description=findViewById<View>(R.id.etActivityAddPostDescription) as EditText post=findViewById<View>(R.id.btnActivityAddPostPost) as Button addLocation=findViewById<View>(R.id.btnActivityAddPostAddLocation) as Button @@ -97,11 +95,6 @@ class ActivityAddPost : AppCompatActivity() { progressDialog!!.setCanceledOnTouchOutside(false) - switcher?.setFactory{ - val imgView = ImageView(applicationContext) - imgView.scaleType = ImageView.ScaleType.CENTER_CROP - imgView.setPadding(8, 8, 8, 8) - imgView} addLocation.setOnClickListener { val myIntent = Intent(this, MapsActivity::class.java) startActivityForResult(myIntent,LOCATIONREQCODE) @@ -109,17 +102,23 @@ class ActivityAddPost : AppCompatActivity() { addDescription.setOnClickListener { description.isGone=false description.isVisible=true + description.requestFocus() + showKeyboard(description) } //dodavanje i brisanje tagova tagButtonAdd.setOnClickListener { addTag() + tagText.requestFocus() + showKeyboard(tagText) } tagText.setOnKeyListener(View.OnKeyListener { v1, keyCode, event -> // If the event is a key-down event on the "enter" button - if (event.action === KeyEvent.ACTION_DOWN && + if (event.action === KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_ENTER ) { // Perform action on key press addTag() + tagText.requestFocus() + showKeyboard(tagText) return@OnKeyListener true } false @@ -180,7 +179,11 @@ class ActivityAddPost : AppCompatActivity() { description.setHintTextColor(Color.RED) } if(locationId==null || locationId!!.trim()==""){ - Toast.makeText(this,"Unesite lokaciju klikom na dugme",Toast.LENGTH_LONG) + Toast.makeText(this@ActivityAddPost,"Unesite lokaciju klikom na dugme",Toast.LENGTH_LONG).show() + } + if(uploadedImages==null ||uploadedImages!!.size<=0) + { + Toast.makeText(this@ActivityAddPost,"Unesite fotografije",Toast.LENGTH_LONG).show() } if(!descriptionString.isEmpty() && uploadedImages!!.size>0){ @@ -188,6 +191,17 @@ class ActivityAddPost : AppCompatActivity() { } } } + + fun showKeyboard(item:EditText){ + var imm: InputMethodManager =this.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.showSoftInput(item, InputMethodManager.SHOW_IMPLICIT) + } + + fun hideKeyboard(item: EditText){ + var imm: InputMethodManager =this.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.hideSoftInputFromWindow(item.windowToken, InputMethodManager.HIDE_NOT_ALWAYS) + } + fun addTag(){ tagText.isGone=false tagText.isVisible=true diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityCapturePost.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityCapturePost.kt index 79062c9..ccccc0e 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityCapturePost.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityCapturePost.kt @@ -18,6 +18,7 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat +import androidx.core.net.toUri import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.core.view.setMargins @@ -28,6 +29,7 @@ import com.example.brzodolokacije.R import com.example.brzodolokacije.Services.GeocoderHelper import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper +import com.google.android.material.button.MaterialButton import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MultipartBody import okhttp3.RequestBody @@ -37,6 +39,8 @@ import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.File import java.io.InputStream +import java.util.* +import kotlin.collections.ArrayList class ActivityCapturePost : AppCompatActivity() { @@ -51,12 +55,14 @@ class ActivityCapturePost : AppCompatActivity() { private lateinit var tagButtons:MutableList<Button> private lateinit var tagText: EditText private lateinit var tagButtonAdd:Button + private lateinit var addImage:MaterialButton private lateinit var tagList: MutableList<String> private var tagidcounter:Int = 0 private lateinit var addDescription:Button private lateinit var locText: EditText - - + private lateinit var showNextImage:Button + private lateinit var showPreviousImage:Button + private var place=0; val LOCATIONREQCODE=123 var locationId:String?=null @@ -77,7 +83,9 @@ class ActivityCapturePost : AppCompatActivity() { tagText =findViewById<View>(R.id.acTagsCap) as EditText tagButtonAdd = findViewById<View>(R.id.btnActivityAddPostAddTagCap) as Button tagLayout = findViewById<View>(R.id.llTagsCap) as LinearLayout - + addImage=findViewById<View>(R.id.btnActivityCapturePostCaptureVisible1) as MaterialButton + showNextImage=findViewById<View>(R.id.nextImage) as Button + showPreviousImage=findViewById<View>(R.id.previousImage) as Button addDescription=findViewById<View>(R.id.tvActivityCapturePostDescriptiontext)as Button locText=findViewById<View>(R.id.etActivityAddPostLocationText) as EditText @@ -110,6 +118,21 @@ class ActivityCapturePost : AppCompatActivity() { } false }) + showPreviousImage.setOnClickListener{ + if(fileList!=null && fileList!!.size>0) + if(place>0){ + place=place-1 + showImage.setImageURI(fileList!![place].toUri()) + } + } + showNextImage.setOnClickListener{ + if(fileList!=null && fileList!!.size>0) + if(place<fileList!!.size-1){ + place=place+1 + showImage.setImageURI(fileList!![place].toUri()) + } + + } //dodavanje sa kamere @@ -168,34 +191,32 @@ class ActivityCapturePost : AppCompatActivity() { val APP_TAG = "BrzoDoLokacije" val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) - /* val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) - //val storageDir: File? = getExternalFilesDir(Environment.DIRECTORY_PICTURES) - //val photo= File(storageDir,"JPEG_${timeStamp}.jpg") - - val mediaStorageDir = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), APP_TAG) - if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()) { - Log.d(APP_TAG, "failed to create directory") - } - var photoFile = File(mediaStorageDir.path + File.separator + "${APP_TAG}_${timeStamp}.jpg") - - if (photoFile != null) { - val fileProvider: Uri = - FileProvider.getUriForFile(this, "com.codepath.fileprovider", photoFile!!) - intent.putExtra(MediaStore.EXTRA_OUTPUT, fileProvider) - } - -*/ + cameraActivityResultLauncher.launch(takePictureIntent) + } + addImage.setOnClickListener { + val APP_TAG = "BrzoDoLokacije" + val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) cameraActivityResultLauncher.launch(takePictureIntent) } post.setOnClickListener { + Log.d("tsdadasdsa","dsadasdas") // locationString = location.text.toString().trim() descriptionString = description.text.toString().trim() //prazan unos? if (descriptionString.isEmpty()) { description.hint = "Unesite opis" description.setHintTextColor(Color.RED) - }else if(f!=null && locationId!=null && locationId!!.trim()!=""){ + } + if(f==null) + { + Toast.makeText(this@ActivityCapturePost,"Unesite fotografije",Toast.LENGTH_LONG).show() + } + if(locationId==null || locationId!!.trim()=="") + { + Toast.makeText(this@ActivityCapturePost,"Unesite lokaciju klikom na dugme",Toast.LENGTH_LONG).show() + } + if(f!=null && locationId!=null && locationId!!.trim()!="" &&!descriptionString.isEmpty()){ uploadLocation() } @@ -251,6 +272,7 @@ class ActivityCapturePost : AppCompatActivity() { locText.setText(name,TextView.BufferType.EDITABLE) } } + var fileList:ArrayList<File>?=null var f:File?=null private val cameraActivityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> @@ -261,13 +283,21 @@ class ActivityCapturePost : AppCompatActivity() { bitmap!!.compress(Bitmap.CompressFormat.PNG,100,outputStream) val bitmapdata = outputStream.toByteArray() val inputstream: InputStream = ByteArrayInputStream(bitmapdata) - f=File.createTempFile("temp","12345") - f!!.writeBytes(inputstream!!.readBytes()) - + if(fileList==null) + fileList=ArrayList<File>() + var r= Random().nextInt(100000) + f=File.createTempFile("temp","12345"+r.toString()) + f!!.writeBytes(inputstream!!.readBytes()) + fileList!!.add(f!!) showImage.setImageBitmap(bitmap) + takePhoto.isVisible=false + if(!addImage.isVisible) + addImage.isVisible=true + place=fileList!!.size-1 + } @@ -296,11 +326,15 @@ class ActivityCapturePost : AppCompatActivity() { var tagReq=RequestBody.create("text/plain".toMediaTypeOrNull(),tagliststring) val imagesParts = arrayOfNulls<MultipartBody.Part>( - 1 + fileList!!.size ) - var imageBody= RequestBody.create("image/*".toMediaTypeOrNull(),f!!) - imagesParts[0]= MultipartBody.Part.createFormData("images",f!!.name,imageBody) + + for (i in 0 until fileList!!.size) { + var imageBody= RequestBody.create("image/*".toMediaTypeOrNull(),fileList!![i]) + imagesParts[i]= MultipartBody.Part.createFormData("images",fileList!![i].name,imageBody) + + } var jwtString= SharedPreferencesHelper.getValue("jwt",this) var data=api.addPost("Bearer "+jwtString,imagesParts,idReq,descReq,locReq,tagReq) diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityChangePassword.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityChangePassword.kt new file mode 100644 index 0000000..dc732ee --- /dev/null +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityChangePassword.kt @@ -0,0 +1,131 @@ +package com.example.brzodolokacije.Activities + +import android.graphics.Color +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle + +import com.example.brzodolokacije.R +import android.widget.Button +import android.widget.EditText +import android.widget.ImageView +import android.widget.TextView +import android.widget.Toast +import androidx.core.view.isVisible +import com.exam.DBHelper.Companion.activity +import com.example.brzodolokacije.Models.Auth.ChangePass +import com.example.brzodolokacije.Models.UserReceive +import com.example.brzodolokacije.Services.RetrofitHelper +import com.example.brzodolokacije.Services.SharedPreferencesHelper +import kotlinx.android.synthetic.main.fragment_my_profile_info.* +import retrofit2.Call +import retrofit2.Response + + +class ActivityChangePassword : AppCompatActivity() { + + private lateinit var oldPass:EditText + private lateinit var oldPassError:TextView + private lateinit var newPass:EditText + private lateinit var newPassError:TextView + private lateinit var confirmPass:EditText + private lateinit var confirmPassError:TextView + private lateinit var forgotten:TextView + private lateinit var submit:Button + private lateinit var backButton:ImageView + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_change_password) + + oldPass=findViewById(R.id.tvActivityChangePasswordCurrentPass) + oldPassError=findViewById(R.id.ActivityChangePasswordOldError) + newPass=findViewById(R.id.tvActivityChangePasswordNewPass) + newPassError=findViewById(R.id.btnActivityChangePasswordNewError) + confirmPass=findViewById(R.id.ActivityChangePasswordNewPasswordConfirm) + confirmPassError=findViewById(R.id.btnActivityChangePasswordConfirmError) + forgotten=findViewById(R.id.btnActivityChangePasswordForgottenPass) + submit=findViewById(R.id.ActivityChangePasswordChangePassword) + backButton=findViewById(R.id.btnBackToUser) + + oldPassError.isVisible=false + newPassError.isVisible=false + confirmPassError.isVisible=false + backButton.setOnClickListener{ + finish() + } + + submit.setOnClickListener{ + oldPassError.isVisible=false + newPassError.isVisible=false + confirmPassError.isVisible=false + if(oldPass.text.toString().trim().isEmpty()) + { + oldPassError.isVisible=true + oldPassError.text="Unesite trenutnu lozinku." + oldPassError.setTextColor(Color.RED) + } + if(newPass.text.toString().trim().isEmpty()) + { + newPassError.isVisible=true + newPassError.text="Unesite novu lozinku." + newPassError.setTextColor(Color.RED) + } + if(confirmPass.text.toString().trim().isEmpty()) + { + confirmPassError.isVisible=true + confirmPassError.text="Potvrdite novu lozinku." + confirmPassError.setTextColor(Color.RED) + } + + if(oldPass.text.toString().trim().isNotEmpty()&&newPass.text.toString().trim().isNotEmpty() + &&confirmPass.text.toString().trim().isNotEmpty()){ + + if(newPass.text.toString().trim() == confirmPass.text.toString().trim()){ + + //PROVERI DA LI JE TRENUTA LOZINKA ISTA KAO TRENUTNI UNOS + var cp= ChangePass(oldPass.text.toString(),newPass.text.toString()) + val authApi= RetrofitHelper.getInstance() + val token= SharedPreferencesHelper.getValue("jwt",this@ActivityChangePassword) + val request=authApi.changePass("Bearer "+token,cp) + + request.enqueue(object : retrofit2.Callback<Int> { + override fun onResponse(call: Call<Int>, response: Response<Int>) { + if(response.isSuccessful()){ + var done=response.body()!! + if(done==1){ + Toast.makeText(this@ActivityChangePassword, "Lozinka je uspešno promenjena.", Toast.LENGTH_LONG).show(); + } + else if(done==-1){ + oldPassError.isVisible=true + oldPassError.text="Uneta lozinka nije odgovarajuća, pokušajte ponovo." + oldPassError.setTextColor(Color.RED) + + } + else if(done==-2){ + Toast.makeText(this@ActivityChangePassword, "Lozinka nije promenjena. Pokušajte ponovo", Toast.LENGTH_LONG).show(); + } + }else{ + if(response.errorBody()!=null) + Toast.makeText(this@ActivityChangePassword, response.errorBody()!!.string(), Toast.LENGTH_LONG).show(); + } + } + override fun onFailure(call: Call<Int>, t: Throwable) { + Toast.makeText( + activity, t.toString(), Toast.LENGTH_LONG + ).show(); + } + }) + } + else{ + confirmPassError.isVisible=true + confirmPassError.text="Lozinke se ne podudaraju." + confirmPassError.setTextColor(Color.RED) + } + } + } + + + + + } +}
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityChangeUserData.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityChangeUserData.kt index d84b850..ab5d676 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityChangeUserData.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityChangeUserData.kt @@ -79,23 +79,10 @@ class ActivityChangeUserData : AppCompatActivity() { getUser() editUsername.setOnClickListener{ - username.setText("") - editUsername.isClickable=false - editUsername.isVisible=false - editUsername.isEnabled=false - editUsername.isGone=true - confirmUsername.isClickable=true - confirmUsername.isVisible=true - confirmUsername.isEnabled=true - confirmUsername.isGone=false + changeUsername() + getUser() - //dodati on change listener - confirmUsername.setOnClickListener { - changeUsername() - getUser() - - } } changeProfilePicture.setOnClickListener { @@ -103,20 +90,7 @@ class ActivityChangeUserData : AppCompatActivity() { } editName.setOnClickListener{ - name.setText("") - editName.isClickable=false - editName.isVisible=false - editName.isEnabled=false - editName.isGone=true - confirmName.isClickable=true - confirmName.isVisible=true - confirmName.isEnabled=true - confirmName.isGone=false - - confirmName.setOnClickListener { - changeName() - - } + changeName() } back.setOnClickListener { @@ -153,6 +127,11 @@ class ActivityChangeUserData : AppCompatActivity() { } fun changeUsername(){ + if(username.text==null || username.text.trim().toString()=="") + { + Toast.makeText(this@ActivityChangeUserData,"Unesite korisničko ime",Toast.LENGTH_SHORT).show() + return + } val api = RetrofitHelper.getInstance() val token = SharedPreferencesHelper.getValue("jwt", this@ActivityChangeUserData) var data = api.changeMyUsername("Bearer " + token,username.text.trim().toString()); @@ -200,6 +179,11 @@ class ActivityChangeUserData : AppCompatActivity() { } fun changeName(){ + if(name.text==null || name.text.trim().toString()=="") + { + Toast.makeText(this@ActivityChangeUserData,"Unesite ime",Toast.LENGTH_SHORT).show() + return + } val api = RetrofitHelper.getInstance() val token = SharedPreferencesHelper.getValue("jwt", this@ActivityChangeUserData) var data = api.changeMyName("Bearer " + token,name.text.trim().toString()); diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityForgottenPassword.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityForgottenPassword.kt index b0b7f5e..6dfbeb0 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityForgottenPassword.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityForgottenPassword.kt @@ -46,13 +46,19 @@ class ActivityForgottenPassword : AppCompatActivity() { val intent = Intent(cont, ActivityForgottenPasswordVerify::class.java) intent.putExtra("email", emailString) startActivity(intent) + }else{ + Toast.makeText(this@ActivityForgottenPassword,"Email ne postoji",Toast.LENGTH_LONG).show() } } override fun onFailure(call: Call<ResponseBody?>, t: Throwable) { + Toast.makeText(this@ActivityForgottenPassword,"Email ne postoji",Toast.LENGTH_LONG).show() } }) } + else{ + Toast.makeText(this@ActivityForgottenPassword,"Unesite validan email",Toast.LENGTH_LONG).show() + } } } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityForgottenPasswordVerify.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityForgottenPasswordVerify.kt index a1db97f..a519a32 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityForgottenPasswordVerify.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityForgottenPasswordVerify.kt @@ -1,6 +1,7 @@ package com.example.brzodolokacije.Activities import android.content.Intent +import android.graphics.Color import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.View @@ -36,6 +37,19 @@ class ActivityForgottenPasswordVerify : AppCompatActivity() { var pwstr=pw.text.toString().trim() var pwchkstr=pwchk.text.toString().trim() var kodstr=kod.text.toString().trim() + if(kodstr.isEmpty()) + { + kod.hint = "Unesite kod" + kod.setHintTextColor(Color.RED) + } + if(pwstr.isEmpty()){ + pw.hint = "Unesite novu lozinku" + pw.setHintTextColor(Color.RED) + } + if(pwchkstr.isEmpty()){ + pwchk.hint = "Potvrdite novu lozinku" + pwchk.setHintTextColor(Color.RED) + } if(!kodstr.isEmpty() && checkPassword(pwstr,pwchkstr)){ var resetData= ResetPass(email!!,kodstr,pwstr) @@ -47,6 +61,8 @@ class ActivityForgottenPasswordVerify : AppCompatActivity() { if(response.code()==200){ intent = Intent(cont, ActivityLoginRegister::class.java) startActivity(intent) + }else{ + Toast.makeText(this@ActivityForgottenPasswordVerify,"Nevalidan kod",Toast.LENGTH_LONG).show() } } override fun onFailure(call: Call<ResponseBody?>, t: Throwable) { diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityOpenedImages.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityOpenedImages.kt new file mode 100644 index 0000000..f1c704e --- /dev/null +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityOpenedImages.kt @@ -0,0 +1,91 @@ +package com.example.brzodolokacije.Activities + +import LinePagerIndicatorDecoration +import android.graphics.Bitmap +import android.graphics.drawable.Drawable +import android.os.Build +import android.os.Bundle +import android.provider.MediaStore +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.PagerSnapHelper +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.SnapHelper +import com.bumptech.glide.Glide +import com.bumptech.glide.request.target.CustomTarget +import com.bumptech.glide.request.transition.Transition +import com.example.brzodolokacije.Adapters.OpenedPostImageAdapter +import com.example.brzodolokacije.Models.PostImage +import com.example.brzodolokacije.Models.PostPreview +import com.example.brzodolokacije.R +import com.example.brzodolokacije.Services.RetrofitHelper +import com.example.brzodolokacije.databinding.ActivityOpenedImagesBinding +import java.util.* + +class ActivityOpenedImages : AppCompatActivity() { + lateinit var binding:ActivityOpenedImagesBinding + var rvImages: RecyclerView?=null + var linearLayout:LinearLayoutManager?=null + var adapter:OpenedPostImageAdapter?=null + var images:List<PostImage>?=null + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding= ActivityOpenedImagesBinding.inflate(layoutInflater) + setContentView(binding.root) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + images=(intent.extras?.getParcelable("post",PostPreview::class.java) as PostPreview).images + } + else{ + images=(intent.extras?.getParcelable("post") as PostPreview?)?.images + } + + setRecyclerView() + setListeners() + } + + fun setListeners(){ + binding.btnBackToPost.setOnClickListener { + finish() + } + binding.btnDownload.setOnClickListener { + //uzmi id trenutne slike + var selected:PostImage?=null + linearLayout?.findFirstVisibleItemPosition()?.let { it1 -> selected=images?.get(it1) } + if(selected!=null){ + //sacuvaj na telefonu + var image=Glide.with(this) + .asBitmap() + .load(RetrofitHelper.baseUrl + "/api/post/image/" + selected!!._id) + .into(object : CustomTarget<Bitmap>(){ + override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) { + Toast.makeText(this@ActivityOpenedImages,"Slika se preuzima...",Toast.LENGTH_LONG).show() + MediaStore.Images.Media.insertImage(contentResolver, resource, "odyssey_"+ Calendar.getInstance().timeInMillis , ""); + Toast.makeText(this@ActivityOpenedImages,"Slika je sačuvana.",Toast.LENGTH_LONG).show() + } + override fun onLoadCleared(placeholder: Drawable?) { + } + }) + } + } + } + + fun setRecyclerView(){ + rvImages=binding.rvImages + linearLayout= LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false) + adapter= OpenedPostImageAdapter(images,this) + rvImages!!.setHasFixedSize(true) + var snap:SnapHelper=PagerSnapHelper() + snap.attachToRecyclerView(rvImages) + rvImages!!.layoutManager=linearLayout + rvImages!!.adapter=adapter + //tackice + var color = ContextCompat.getColor(this@ActivityOpenedImages, R.color.unfollow) + var color1 = ContextCompat.getColor(this@ActivityOpenedImages, R.color.button_main) + if(images!!.size>1) + rvImages!!.addItemDecoration(LinePagerIndicatorDecoration(10,10,100,color,color1)) + } + +}
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivitySinglePost.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivitySinglePost.kt index 34a9e6b..d2a820f 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivitySinglePost.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivitySinglePost.kt @@ -1,21 +1,32 @@ package com.example.brzodolokacije.Activities +import LinePagerIndicatorDecoration import android.content.Intent import android.graphics.Color import android.os.Bundle import android.preference.PreferenceManager +import android.util.Log +import android.util.TypedValue +import android.view.GestureDetector +import android.view.MotionEvent import android.view.ViewGroup -import android.widget.FrameLayout -import android.widget.ImageView -import android.widget.TextView +import android.view.ViewGroup.MarginLayoutParams +import android.widget.* import androidx.appcompat.app.AppCompatActivity import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.ContextCompat +import androidx.core.view.GestureDetectorCompat import androidx.core.view.isGone import androidx.core.view.isVisible +import androidx.core.view.setMargins import androidx.fragment.app.FragmentTransaction import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.PagerSnapHelper import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.SnapHelper +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener +import com.auth0.android.jwt.JWT import com.example.brzodolokacije.Adapters.CommentsAdapter import com.example.brzodolokacije.Adapters.PostImageAdapter import com.example.brzodolokacije.Fragments.FragmentSinglePostComments @@ -29,7 +40,7 @@ import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper import com.example.brzodolokacije.databinding.ActivitySinglePostBinding import com.google.gson.Gson -import kotlinx.android.synthetic.main.fragment_single_post_description.* +import kotlinx.android.synthetic.main.activity_single_post.* import org.osmdroid.config.Configuration import org.osmdroid.tileprovider.tilesource.TileSourceFactory import org.osmdroid.util.GeoPoint @@ -37,9 +48,11 @@ import org.osmdroid.views.MapView import org.osmdroid.views.overlay.Marker import retrofit2.Call import retrofit2.Response +import java.text.SimpleDateFormat -class ActivitySinglePost : AppCompatActivity() { +class ActivitySinglePost : AppCompatActivity(),OnRefreshListener { + private lateinit var swipeRefreshLayout: SwipeRefreshLayout private lateinit var binding: ActivitySinglePostBinding private var layoutManagerImages: RecyclerView.LayoutManager? = null private var layoutManagerComments: RecyclerView.LayoutManager? = null @@ -48,8 +61,12 @@ class ActivitySinglePost : AppCompatActivity() { private var recyclerViewImages: RecyclerView?=null private var recyclerViewComments: RecyclerView?=null private var favouriteImage: ImageView?=null + private lateinit var tagLayout: LinearLayout + private lateinit var createdAt:TextView public lateinit var post: PostPreview + public lateinit var ratings:TextView + public lateinit var ratingscount:TextView private var comments:MutableList<CommentSend>?=mutableListOf() private var starNumber:Number=0 @@ -59,7 +76,7 @@ class ActivitySinglePost : AppCompatActivity() { private lateinit var btnChangeHeightUp:ImageView private lateinit var btnChangeHeightDown:ImageView private lateinit var fragmentContainer: FrameLayout - + //private lateinit var detector: GestureDetectorCompat override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding=ActivitySinglePostBinding.inflate(layoutInflater) @@ -76,41 +93,44 @@ class ActivitySinglePost : AppCompatActivity() { btnChangeHeightUp.isVisible=true btnChangeHeightUp.isGone=false btnChangeHeightUp.isClickable=true - linearLayout2=findViewById(R.id.linearLayout2) + linearLayout2.setOnClickListener { linearLayout2.getLayoutParams().height= ViewGroup.LayoutParams.MATCH_PARENT; } - + //detector= GestureDetectorCompat(this,SwipeGestureListener()) //instantiate adapter and linearLayout adapterImages= PostImageAdapter(this@ActivitySinglePost, post.images as MutableList<PostImage>) layoutManagerImages= LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false) recyclerViewImages = binding.rvMain + //tackice image + var color = ContextCompat.getColor(this@ActivitySinglePost, R.color.unfollow) + var color1 = ContextCompat.getColor(this@ActivitySinglePost, R.color.button_main) + if(post.images.size>1) + recyclerViewImages!!.addItemDecoration(LinePagerIndicatorDecoration(10,10,100,color,color1)) //DODATI SLIKE recyclerViewImages?.setHasFixedSize(true) + var snap: SnapHelper = PagerSnapHelper() + snap.attachToRecyclerView(recyclerViewImages) recyclerViewImages?.layoutManager = layoutManagerImages recyclerViewImages?.adapter = adapterImages - loadTextComponents() - var fm: FragmentTransaction =supportFragmentManager.beginTransaction() - val fragment = FragmentSinglePostDescription() - val b = Bundle() - b.putString("post", Gson().toJson(post)) - fragment.arguments = b - fm.replace(R.id.flSinglePostFragmentContainer, fragment) - fm.commit() + setUpFirstFragment() + - /* favouriteImage=binding.ivFavourite + tagLayout = binding.llTags + + // set recyclerView attributes - loadFavourite() - */ + + translateOwnerIdToName(post.ownerId) binding.tvUser.setOnClickListener { @@ -134,7 +154,6 @@ class ActivitySinglePost : AppCompatActivity() { recyclerViewImages?.setHasFixedSize(true) recyclerViewImages?.layoutManager = layoutManagerImages recyclerViewImages?.adapter = adapterImages - } btnChangeHeightDown.setOnClickListener { btnChangeHeightDown.isVisible=false @@ -152,10 +171,10 @@ class ActivitySinglePost : AppCompatActivity() { } - /*favouriteImage!!.setOnClickListener{ + favouriteImage!!.setOnClickListener{ addRemoveFavourite() } -*/ + binding.btnActivitySinglePostDescription.setOnClickListener { var fm: FragmentTransaction =supportFragmentManager.beginTransaction() val fragment = FragmentSinglePostDescription() @@ -175,9 +194,115 @@ class ActivitySinglePost : AppCompatActivity() { fm.commit() } + swipeRefreshLayout = binding.PostSwipeRefresh + swipeRefreshLayout.setOnRefreshListener(this@ActivitySinglePost) + swipeRefreshLayout.setColorSchemeResources( + R.color.purple_200, + R.color.teal_200, + R.color.dark_blue_transparent, + R.color.purple_700 + ) + + btnChangeHeightUp.performClick() + btnChangeHeightDown.performClick() + } + + /*override fun onTouchEvent(event: MotionEvent?): Boolean { + return if(event?.let { detector.onTouchEvent(it) } == true){ + Log.d("testing swipeup","------------------------") + true + } + else return super.onTouchEvent(event) + } + + inner class SwipeGestureListener : GestureDetector.SimpleOnGestureListener() { + private val SWIPE_THRESHOLD = 20 + private val SWIPE_VELOCITY_THRESHOLD = 20 + override fun onFling( + downEvent: MotionEvent, + moveEvent: MotionEvent, + velocityX: Float, + velocityY: Float + ): Boolean { + + Log.d("testing swipeup","------------------------") + var diffX = moveEvent?.x?.minus(downEvent!!.x) ?: 0.0F + var diffY = moveEvent?.y?.minus(downEvent!!.y) ?: 0.0F + + if (Math.abs(diffX) < Math.abs(diffY)) { + if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) { + if (diffY > 0 ) { + //top to bot + + } + else { + //bot to top + btnChangeHeightUp.performClick() + } + + } + return true + }else{ + return super.onFling(downEvent, moveEvent, velocityX, velocityY) + } + return super.onFling(downEvent, moveEvent, velocityX, velocityY) + } + }*/ + + fun setUpFirstFragment(){ + var fm: FragmentTransaction =supportFragmentManager.beginTransaction() + val fragment = FragmentSinglePostDescription() + val b = Bundle() + b.putString("post", Gson().toJson(post)) + fragment.arguments = b + fm.replace(R.id.flSinglePostFragmentContainer, fragment) + fm.commit() + } + override fun onRefresh(){ + onResume() } - /* + + override fun onResume(){ + super.onResume() + loadTextComponents() + loadTags() + loadFavourite() + setUpFirstFragment() + btnChangeHeightUp.performClick() + btnChangeHeightDown.performClick() + swipeRefreshLayout.isRefreshing=false + } + + fun loadTags(){ + + tagLayout.removeAllViews() + if(post.tags!=null) + for( item in post.tags!!){ + var newbtn = Button(this) + newbtn.text = item + var layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + 50 + ) + layoutParams.setMargins(3) + + newbtn.layoutParams = layoutParams + newbtn.setBackgroundColor(Color.parseColor("#1C789A")) + newbtn.setTextColor(Color.WHITE) + newbtn.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10F) + newbtn.setPadding(3, 1, 3, 1) + newbtn.isClickable = false + tagLayout.addView(newbtn) + } + } + + public fun updateratings(rc:Int,r:Double){ + binding.tvRating.text=r.toString() + binding.tvNumberOfRatings.text=rc.toString() + } + + fun loadFavourite(){ if(post.favourites!=null){ var jwtString=SharedPreferencesHelper.getValue("jwt",this) @@ -212,12 +337,12 @@ class ActivitySinglePost : AppCompatActivity() { } - */ + fun getMap(){ var map: MapView? = null Configuration.getInstance().load(this, PreferenceManager.getDefaultSharedPreferences(this)); - map=findViewById(R.id.MapDialogueMapView) + map=findViewById(R.id.MapDialogueMap) //findViewById(R.id.MapDialogueMapView) as MapView map!!.setTileSource(TileSourceFactory.MAPNIK); map!!.setBuiltInZoomControls(true); @@ -251,7 +376,8 @@ class ActivitySinglePost : AppCompatActivity() { tvNumberOfRatings.invalidate() //tvRating.text=String.format("%.2f",data.ratings) //tvNumberOfRatings.text=String.format("%d",data.ratingscount) - + tvDatePosted.text=SimpleDateFormat("dd/MM/yyyy").format(post.createdAt) + tvDatePosted.invalidate() } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityUserProfile.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityUserProfile.kt index 4962006..0bbcf79 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityUserProfile.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityUserProfile.kt @@ -4,25 +4,34 @@ import android.annotation.SuppressLint import android.content.Intent import android.os.Bundle import android.util.Log +import android.view.View import android.widget.* import androidx.appcompat.app.AppCompatActivity +import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible -import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentTransaction +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener +import com.auth0.android.jwt.JWT import com.bumptech.glide.Glide +import com.exam.DBHelper +import com.example.brzodolokacije.FragmentProfileStatistics import com.example.brzodolokacije.Fragments.FragmentUserPostsProfileActivity import com.example.brzodolokacije.Models.UserReceive import com.example.brzodolokacije.R -import com.example.brzodolokacije.R.* +import com.example.brzodolokacije.R.id +import com.example.brzodolokacije.R.layout import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper +import com.example.brzodolokacije.UserPostsMapFragment import com.google.gson.Gson import retrofit2.Call import retrofit2.Callback import retrofit2.Response -class ActivityUserProfile : AppCompatActivity() { +class ActivityUserProfile : AppCompatActivity(),OnRefreshListener { + private lateinit var swipeRefreshLayout: SwipeRefreshLayout private lateinit var name:TextView private lateinit var postsNumber:TextView private lateinit var followersNumber:TextView @@ -34,6 +43,10 @@ class ActivityUserProfile : AppCompatActivity() { private lateinit var userObject:UserReceive private lateinit var openChat:ImageButton private lateinit var unfollowUser:Button + private lateinit var btnSendMessage:ImageButton + private lateinit var followChatRow:ConstraintLayout + private lateinit var mapButton:Button + private lateinit var statisticsButton:Button private lateinit var showFollowers:Button private lateinit var showFollowing:Button @@ -56,6 +69,10 @@ class ActivityUserProfile : AppCompatActivity() { openChat=findViewById(id.activityUserProfileOpenChat) showFollowing=findViewById(id.tvActivityUserProfileFollow) showFollowers=findViewById(R.id.tvActivityUserProfileFollowers) + btnSendMessage=findViewById(R.id.activityUserProfileOpenChat) + followChatRow=findViewById(R.id.clActivityUserProfileFollow_Chat_Row) + mapButton=findViewById(R.id.btnFragmentUserProfileShowData) + statisticsButton=findViewById(R.id.btnFragmentUserProfileShowRecensions) val jsonMyObject: String @@ -65,85 +82,68 @@ class ActivityUserProfile : AppCompatActivity() { //val myObject: UserReceive = Gson().fromJson(jsonMyObject, UserReceive::class.java) userObject= Gson().fromJson(jsonMyObject, UserReceive::class.java) + updateUserData() - name.text=userObject.name - postsNumber.text=userObject.postNumber.toString() - followersNumber.text=userObject?.followersCount.toString() - followingNumber.text=userObject?.followingCount.toString() - if(userObject.pfp!=null) { - Glide.with(this@ActivityUserProfile) - .load(RetrofitHelper.baseUrl + "/api/post/image/" + userObject.pfp!!._id) - .circleCrop()//Round image - .into(profilePicture) - } + } + else{ + finish() } - checkIfAlreadyFollow() - updateUserData() + showFollowers.setOnClickListener { + val bundle = Bundle() + bundle.putString("userId", userObject._id.toString()) + bundle.putString("show","followers") + bundle.putString("showMy","no") + val intent = Intent(this@ActivityUserProfile,ActivityShowFollowersAndFollowing::class.java) + intent.putExtras(bundle) + startActivity(intent) - followUser.setOnClickListener{ - val api = RetrofitHelper.getInstance() - val token = SharedPreferencesHelper.getValue("jwt", this@ActivityUserProfile) - var data = api.addFollower("Bearer " + token, userObject._id); - data.enqueue(object : Callback<Boolean> { - override fun onResponse( - call: Call<Boolean>, - response: Response<Boolean> - ) { - unfollowUser.isVisible=true - unfollowUser.isClickable=true - unfollowUser.isEnabled=true - followUser.isVisible=false - followUser.isClickable=false - followUser.isEnabled=false + } + mapButton.setOnClickListener { + val bundle = Bundle() - updateUserData() + bundle.putString("id", userObject._id) + bundle.putString("other","true") + val userMapFragment = UserPostsMapFragment() + userMapFragment.setArguments(bundle) + var fm: FragmentTransaction =supportFragmentManager.beginTransaction() + fm.replace(R.id.flActivityProfileFragmentContainer, userMapFragment) + fm.commit() - Toast.makeText( - this@ActivityUserProfile, "PRATITE KORISNIKA", Toast.LENGTH_LONG - ).show(); - } - override fun onFailure(call: Call<Boolean>, t: Throwable) { - Toast.makeText( - this@ActivityUserProfile, t.toString(), Toast.LENGTH_LONG - ).show(); - } - }) + } + statisticsButton.setOnClickListener{ + + + var fragment: FragmentProfileStatistics = FragmentProfileStatistics() + val bundle = Bundle() + bundle.putString("username", userObject.username) + fragment.arguments=bundle + var fm: FragmentTransaction =supportFragmentManager.beginTransaction() + fm.replace(R.id.flActivityProfileFragmentContainer, fragment) + fm.commit() } - unfollowUser.setOnClickListener { - val api = RetrofitHelper.getInstance() - val token = SharedPreferencesHelper.getValue("jwt", this@ActivityUserProfile) - var data = api.unfollow("Bearer " + token, userObject._id); - data.enqueue(object : Callback<Boolean> { - override fun onResponse( - call: Call<Boolean>, - response: Response<Boolean> - ) { - unfollowUser.isVisible = false - unfollowUser.isClickable = false - unfollowUser.isEnabled = false - followUser.isVisible = true - followUser.isClickable = true - followUser.isEnabled = true - updateUserData() - Toast.makeText( - this@ActivityUserProfile, "VIŠE NE PRATITE KORISNIKA", Toast.LENGTH_LONG - ).show(); - } - override fun onFailure(call: Call<Boolean>, t: Throwable) { - Toast.makeText( - this@ActivityUserProfile, t.toString(), Toast.LENGTH_LONG - ).show(); - } - }) + showFollowing.setOnClickListener { + val bundle = Bundle() + bundle.putString("userId", userObject._id.toString()) + bundle.putString("show","following") + bundle.putString("showMy","no") + val intent = Intent(this@ActivityUserProfile,ActivityShowFollowersAndFollowing::class.java) + intent.putExtras(bundle) + startActivity(intent) } - showFollowers.setOnClickListener { + setFollowerChatRow() + + showUserPosts.setOnClickListener { + showUserPostsFragment() + } + + followersNumber.setOnClickListener { val bundle = Bundle() bundle.putString("userId", userObject._id.toString()) bundle.putString("show","followers") @@ -154,7 +154,7 @@ class ActivityUserProfile : AppCompatActivity() { } - showFollowing.setOnClickListener { + followingNumber.setOnClickListener { val bundle = Bundle() bundle.putString("userId", userObject._id.toString()) bundle.putString("show","following") @@ -164,19 +164,112 @@ class ActivityUserProfile : AppCompatActivity() { startActivity(intent) } + swipeRefreshLayout = findViewById<View>(R.id.ProfileSwipeRefresh) as SwipeRefreshLayout + swipeRefreshLayout.setOnRefreshListener(this@ActivityUserProfile) + swipeRefreshLayout.setColorSchemeResources( + R.color.purple_200, + R.color.teal_200, + R.color.dark_blue_transparent, + R.color.purple_700 + ) + } + fun setFollowerChatRow(){ + if(userObject._id != SharedPreferencesHelper.getValue("jwt",this@ActivityUserProfile) + ?.let { it1 -> JWT(it1).claims["id"]?.asString() }){ + followChatRow.visibility=View.VISIBLE + followChatRow.forceLayout() + + + btnSendMessage.setOnClickListener{ + val intent: Intent = Intent(this@ActivityUserProfile, ChatActivityConversation::class.java) + intent.putExtra("userId",userObject._id) + intent.putExtra("username",userObject.username) + intent.putExtra("pfp",userObject.pfp?._id) + DBHelper.getInstance(this).readContact(userObject._id) + this.startActivity(intent) + } + + followUser.setOnClickListener{ + val api = RetrofitHelper.getInstance() + val token = SharedPreferencesHelper.getValue("jwt", this@ActivityUserProfile) + var data = api.addFollower("Bearer " + token, userObject._id); + data.enqueue(object : Callback<Boolean> { + override fun onResponse( + call: Call<Boolean>, + response: Response<Boolean> + ) { + if(response.body()==true) { + unfollowUser.isVisible = true + unfollowUser.isClickable = true + unfollowUser.isEnabled = true + followUser.isVisible = false + followUser.isClickable = false + followUser.isEnabled = false + + updateUserData() + } + } - showUserPosts.setOnClickListener { - var fm: FragmentTransaction =supportFragmentManager.beginTransaction() - val fragment = FragmentUserPostsProfileActivity() - val b = Bundle() - b.putString("userId", userObject._id.toString()) - fragment.arguments = b - fm.replace(R.id.flActivityProfileFragmentContainer, fragment) - fm.commit() + override fun onFailure(call: Call<Boolean>, t: Throwable) { + Toast.makeText( + this@ActivityUserProfile, t.toString(), Toast.LENGTH_LONG + ).show(); + } + }) + + } + unfollowUser.setOnClickListener { + val api = RetrofitHelper.getInstance() + val token = SharedPreferencesHelper.getValue("jwt", this@ActivityUserProfile) + var data = api.unfollow("Bearer " + token, userObject._id); + data.enqueue(object : Callback<Boolean> { + override fun onResponse( + call: Call<Boolean>, + response: Response<Boolean> + ) { + if(response.body()==true) { + unfollowUser.isVisible = false + unfollowUser.isClickable = false + unfollowUser.isEnabled = false + followUser.isVisible = true + followUser.isClickable = true + followUser.isEnabled = true + updateUserData() + } + } + + override fun onFailure(call: Call<Boolean>, t: Throwable) { + Toast.makeText( + this@ActivityUserProfile, t.toString(), Toast.LENGTH_LONG + ).show(); + } + }) + } } } + override fun onRefresh() { + onResume() + } + + override fun onResume(){ + super.onResume() + checkIfAlreadyFollow() + updateUserData() + showUserPostsFragment() + } + fun showUserPostsFragment(){ + var fm: FragmentTransaction =supportFragmentManager.beginTransaction() + val fragment = FragmentUserPostsProfileActivity() + val b = Bundle() + b.putString("userId", userObject._id.toString()) + fragment.arguments = b + fm.replace(R.id.flActivityProfileFragmentContainer, fragment) + fm.commit() + swipeRefreshLayout.isRefreshing=false + } + fun checkIfAlreadyFollow(){ val api = RetrofitHelper.getInstance() val token= SharedPreferencesHelper.getValue("jwt", this@ActivityUserProfile) @@ -186,6 +279,7 @@ class ActivityUserProfile : AppCompatActivity() { override fun onFailure(call: Call<Boolean>, t: Throwable) {; Log.d("fail","faillllllllllllllllllllllllllllllllllllllllllllllllllllllll") Log.d("fail",t.toString()) + swipeRefreshLayout.isRefreshing=false } @SuppressLint("ResourceAsColor") @@ -195,6 +289,7 @@ class ActivityUserProfile : AppCompatActivity() { return } var follow = response.body()!! + swipeRefreshLayout.isRefreshing=false if(follow){ Log.d("success","follow") @@ -234,7 +329,7 @@ class ActivityUserProfile : AppCompatActivity() { fun updateUserData(){ val api = RetrofitHelper.getInstance() val token = SharedPreferencesHelper.getValue("jwt", this@ActivityUserProfile) - var data = api.getProfileFromId("Bearer " + token, userObject._id); + var data = api.getProfile("Bearer " + token, userObject.username); data.enqueue(object : Callback<UserReceive> { override fun onResponse( call: Call<UserReceive>, @@ -243,15 +338,23 @@ class ActivityUserProfile : AppCompatActivity() { var userData=response.body()!! name.text=userData.name - postsNumber.text=userData.postNumber.toString() + postsNumber.text=userData.postcount.toString() followersNumber.text=userData.followersCount.toString() followingNumber.text=userData.followingCount.toString() + swipeRefreshLayout.isRefreshing=false + if(userData.pfp!=null) { + Glide.with(this@ActivityUserProfile) + .load(RetrofitHelper.baseUrl + "/api/post/image/" + userData.pfp!!._id) + .circleCrop()//Round image + .into(profilePicture) + } } override fun onFailure(call: Call<UserReceive>, t: Throwable) { Toast.makeText( this@ActivityUserProfile, t.toString(), Toast.LENGTH_LONG ).show(); + swipeRefreshLayout.isRefreshing=false } }) } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ChatActivity.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ChatActivity.kt index efbfd7a..18ff392 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ChatActivity.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ChatActivity.kt @@ -1,8 +1,6 @@ package com.example.brzodolokacije.Activities import android.Manifest -import android.app.AlertDialog -import android.content.Intent import android.content.pm.PackageManager import android.os.Build import android.os.Bundle @@ -11,6 +9,7 @@ import android.widget.Toast import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.content.res.AppCompatResources import androidx.core.content.ContextCompat import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -24,8 +23,12 @@ import com.example.brzodolokacije.Models.MessageReceive import com.example.brzodolokacije.R import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper +import com.example.brzodolokacije.chat.Notifications import com.example.brzodolokacije.chat.SignalRListener import com.example.brzodolokacije.databinding.ActivityChatBinding +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.launch import retrofit2.Call import retrofit2.Callback import retrofit2.Response @@ -48,47 +51,14 @@ class ChatActivity : AppCompatActivity(), SwipeRefreshLayout.OnRefreshListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding= ActivityChatBinding.inflate(layoutInflater) - permissionLauncher=registerForActivityResult( - ActivityResultContracts.RequestPermission() - ) { isGranted: Boolean -> - if (!isGranted) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (Build.VERSION.SDK_INT >= 33) { - //ako je upravo odbijena dozvola na uredjaju na kome je ona neophodna - binding.btnNotifications.setImageResource(R.drawable.bell_off) - } - else{ - //ako je upravo odbijena dozvola na uredjaju na kome nije ona neophodna - binding.btnNotifications.setImageResource(R.drawable.bell_on) - } - } - else{ - //ako je upravo odbijena dozvola na uredjaju na kome nije ona neophodna - binding.btnNotifications.setImageResource(R.drawable.bell_on) - } - } - else{ - //ako je upravo prihvacena dozvola na uredjaju na kome nije ona neophodna - binding.btnNotifications.setImageResource(R.drawable.bell_on) - } - } - //provera da li je dozvoljeno - when { - ContextCompat.checkSelfPermission(this,Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED -> { - binding.btnNotifications.setImageResource(R.drawable.bell_on) - } - else -> { - binding.btnNotifications.setImageResource(R.drawable.bell_off) - } - } - - + Notifications.makeChannel(this) + setPermissionLauncher() + checkPermissions() setContentView(binding.root) dbConnection= DBHelper(this@ChatActivity,null) ws=SignalRListener.getInstance(this@ChatActivity) setListeners() setRecyclerView() - requestNewMessages() swipeRefreshLayout = binding.swipeContainer swipeRefreshLayout?.setOnRefreshListener(this@ChatActivity) swipeRefreshLayout?.setColorSchemeResources( @@ -97,11 +67,52 @@ class ChatActivity : AppCompatActivity(), SwipeRefreshLayout.OnRefreshListener { R.color.dark_blue_transparent, R.color.purple_700 ) - swipeRefreshLayout?.post(kotlinx.coroutines.Runnable { - swipeRefreshLayout?.isRefreshing=true - requestNewMessages() - }) + } + + override fun onResume() { + super.onResume() + clickedChat=null + requestNewMessages() + } + + fun setPermissionLauncher(){ + permissionLauncher=registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { isGranted: Boolean -> + if (!isGranted) { + binding.btnNotifications.setImageResource(R.drawable.bell_off) + } + else{ + binding.btnNotifications.setImageResource(R.drawable.bell_on) + } + } + } + + fun checkPermissions(){ + when { + //treba proveriti permisije + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU-> { + if(ContextCompat.checkSelfPermission(this,Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) { + binding.btnNotifications.setImageResource(R.drawable.bell_on) + } + else{ + binding.btnNotifications.setImageResource(R.drawable.bell_off) + } + } + //treba proveriti preference + else-> { + if(SharedPreferencesHelper.getValue("notifications",this)==null){ + SharedPreferencesHelper.addValue("notifications","false",this@ChatActivity) + } + else if (SharedPreferencesHelper.getValue("notifications",this)=="true") { + binding.btnNotifications.setImageResource(R.drawable.bell_on) + } + else{ + binding.btnNotifications.setImageResource(R.drawable.bell_off) + } + } + } } fun launchNotificationPermissionPrompt(){ @@ -109,44 +120,54 @@ class ChatActivity : AppCompatActivity(), SwipeRefreshLayout.OnRefreshListener { } fun launchInfoDialog(){ - val alertDialog: AlertDialog = AlertDialog.Builder(this@ChatActivity).create() - alertDialog.setTitle("Obaveštenje") - alertDialog.setMessage("Potrebno je restartovati aplikaciju da bi se sačuvale promene.") - alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK" + var builder= MaterialAlertDialogBuilder(this) + builder.background = AppCompatResources.getDrawable(this,R.drawable.rounded_alert_background) + builder.setTitle("Obaveštenje") + builder.setMessage("Potrebno je restartovati aplikaciju da bi se sačuvale promene.") + builder.setPositiveButton("OK", ) { dialog, _ -> dialog.dismiss() } - alertDialog.show() + builder.show() } fun setListeners(){ - findViewById<ImageButton>(R.id.addNewMessage).setOnClickListener { - val intent: Intent = Intent(this@ChatActivity,ChatActivityConversation::class.java) - intent.putExtra("receiverId","") - startActivity(intent) - } findViewById<ImageButton>(R.id.btnBack).setOnClickListener { finish() } findViewById<ImageButton>(R.id.btnNotifications).setOnClickListener { when { - ContextCompat.checkSelfPermission(this,Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED -> { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + //treba proveriti permisije + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU-> { + if(ContextCompat.checkSelfPermission(this,Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) { revokeSelfPermissionOnKill(Manifest.permission.POST_NOTIFICATIONS) + launchInfoDialog() + } + else{ + launchNotificationPermissionPrompt() } - launchInfoDialog() } - else -> { - launchNotificationPermissionPrompt() + //treba proveriti preference + else-> { + if (SharedPreferencesHelper.getValue("notifications",this)=="true") { + SharedPreferencesHelper.addValue("notifications","false",this@ChatActivity) + binding.btnNotifications.setImageResource(R.drawable.bell_off) + } + else{ + SharedPreferencesHelper.addValue("notifications","true",this@ChatActivity) + binding.btnNotifications.setImageResource(R.drawable.bell_on) + } } + } } } fun requestForChats(){ - var dbHelper= DBHelper.getInstance(this@ChatActivity) - items=dbHelper.getContacts() - adapterVar= items?.let { ChatPreviewsAdapter(it,this@ChatActivity) } - setRecyclerView(setParams = false) + MainScope().launch{ + var dbHelper= DBHelper.getInstance(this@ChatActivity) + items=dbHelper.getContacts() + setRecyclerView() + } } fun requestNewMessages(){ @@ -164,7 +185,8 @@ class ChatActivity : AppCompatActivity(), SwipeRefreshLayout.OnRefreshListener { cal.time=message.timestamp dbHelper.addMessage( Message(message.senderId+message.timestamp,message.senderId, - JWT(SharedPreferencesHelper.getValue("jwt",this@ChatActivity)!!).claims["id"]?.asString()!!,message.messagge,message.timestamp,cal),false) + JWT(SharedPreferencesHelper.getValue("jwt",this@ChatActivity)!!).claims["id"]?.asString()!!,message.messagge,message.timestamp,cal),false) + } } requestForChats() diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ChatActivityConversation.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ChatActivityConversation.kt index 985735f..723980b 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ChatActivityConversation.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ChatActivityConversation.kt @@ -1,9 +1,9 @@ package com.example.brzodolokacije.Activities +import android.content.Intent import android.graphics.Bitmap import android.os.Bundle import android.util.Log -import android.view.View import android.widget.EditText import android.widget.ImageButton import android.widget.Toast @@ -11,6 +11,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.auth0.android.jwt.JWT +import com.bumptech.glide.Glide import com.exam.DBHelper import com.example.brzodolokacije.Adapters.ChatMessagesAdapter import com.example.brzodolokacije.Models.Message @@ -21,6 +22,7 @@ import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper import com.example.brzodolokacije.chat.SignalRListener import com.example.brzodolokacije.databinding.ActivityChatConversationBinding +import com.google.gson.Gson import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import retrofit2.Call @@ -39,6 +41,7 @@ class ChatActivityConversation : AppCompatActivity() { var webSocketConnection:SignalRListener?=null var items:MutableList<Message>?=mutableListOf() var userImage:Bitmap?=null + var userImageId:String?=null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -46,13 +49,19 @@ class ChatActivityConversation : AppCompatActivity() { setContentView(binding.root) userId=intent.extras?.get("userId").toString() receiverUsername=intent.extras?.get("username").toString() - userImage=intent.extras?.get("pfp") as Bitmap? + if(intent.extras?.get("pfp") is Bitmap){ + userImage=intent.extras?.get("pfp") as Bitmap? + } + else{ + userImageId=intent.extras?.get("pfp") as String? + } dbConnection=DBHelper.getInstance(this@ChatActivityConversation) setHeader() setRecyclerView() requestMessages() webSocketConnection=SignalRListener.getInstance(this@ChatActivityConversation) - (webSocketConnection!!.activity as ChatActivity).setClickedActivity(this@ChatActivityConversation) + if(webSocketConnection!!.activity is ChatActivity) + (webSocketConnection!!.activity as ChatActivity).setClickedActivity(this@ChatActivityConversation) setListeners() } @@ -62,58 +71,6 @@ class ChatActivityConversation : AppCompatActivity() { var messageContent=findViewById<EditText>(R.id.etNewMessage).text.trim().toString() val Api= RetrofitHelper.getInstance() if(!messageContent.isNullOrEmpty()){ - if(userId.isNullOrEmpty() || userId.equals("null")){ - //zahtev sa username=om - receiverUsername=findViewById<EditText>(R.id.etReceiverUsername).text.toString() - val request=Api.getProfile("Bearer "+token, - receiverUsername!! - ) - request.enqueue(object : retrofit2.Callback<UserReceive?> { - override fun onResponse(call: Call<UserReceive?>, response: Response<UserReceive?>) { - if(response.isSuccessful()){ - //zahtev da se posalje poruka - var user:UserReceive=response.body()!! - userId=user._id - setHeader() - var message= MessageSend(userId!!,messageContent) - val request2=Api.sendMessage("Bearer "+token, - message - ) - request2.enqueue(object : retrofit2.Callback<Message?> { - override fun onResponse(call: Call<Message?>, response: Response<Message?>) { - if(response.isSuccessful()){ - //zahtev da se posalje poruka - var responseMessage=response.body() - var cal: Calendar = Calendar.getInstance() - cal.time=responseMessage?.timestamp - responseMessage?.usableTimeStamp=cal - dbConnection?.addMessage(responseMessage!!,username=user.username) - requestMessages() - binding.etNewMessage.text?.clear() - - } - else{ - Toast.makeText(this@ChatActivityConversation,"Pogresno korisnicko ime1.",Toast.LENGTH_LONG).show() - } - } - - override fun onFailure(call: Call<Message?>, t: Throwable) { - Toast.makeText(this@ChatActivityConversation,"Pogresno korisnicko ime2.",Toast.LENGTH_LONG).show() - } - }) - } - else{ - Log.d("main",response.message()) - //Toast.makeText(this@ChatActivityConversation,"Pogresno korisnicko ime3.",Toast.LENGTH_LONG).show() - } - } - - override fun onFailure(call: Call<UserReceive?>, t: Throwable) { - Toast.makeText(this@ChatActivityConversation,"fail.",Toast.LENGTH_LONG).show() - } - }) - } - else{ //zahtev da se posalje poruka var message= MessageSend(userId!!,messageContent) val request2=Api.sendMessage("Bearer "+token, @@ -140,35 +97,40 @@ class ChatActivityConversation : AppCompatActivity() { Toast.makeText(this@ChatActivityConversation,"Pogresno korisnicko ime.",Toast.LENGTH_LONG).show() } }) - } - } } + binding.llHeader.setOnClickListener { + val intent: Intent = Intent(this@ChatActivityConversation,ActivityUserProfile::class.java) + var b= Bundle() + intent.putExtra("user", Gson().toJson( + UserReceive(userId!!,"",receiverUsername!!,"",Date(),null,0, listOf(),0,listOf(),0,listOf(),0,null) + )) + this.startActivity(intent) + } } private fun setHeader(){ if(userId.isNullOrEmpty() || userId.equals("null")){ - binding.cvParentUsername.visibility= View.VISIBLE - binding.cvParentUsername.forceLayout() - binding.llHeader.visibility= View.GONE - binding.llHeader.invalidate() - binding.llHeader.forceLayout() + binding.tvFragmentTitle.text="Nije nađen korisnik" + binding.tvFragmentTitle.invalidate() } else{ - binding.llHeader.visibility= View.VISIBLE - binding.llHeader.invalidate() - binding.llHeader.forceLayout() binding.tvFragmentTitle.text=receiverUsername binding.tvFragmentTitle.invalidate() - binding.cvParentUsername.visibility= View.GONE - binding.cvParentUsername.forceLayout() } binding.btnBack.setOnClickListener { finish() } - if(userImage!=null) + if(userImage!=null){ binding.ivUserImage.setImageBitmap(userImage) + } + else if(userImageId!=null){ + Glide.with(this) + .load(RetrofitHelper.baseUrl + "/api/post/image/compress/" + userImageId!!) + .circleCrop() + .into(binding.ivUserImage) + } } fun setRecyclerView(setParams:Boolean=true){ MainScope().launch { diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/MapsActivity.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/MapsActivity.kt index 238c7e8..82fd7a4 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/MapsActivity.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/MapsActivity.kt @@ -1,11 +1,8 @@ package com.example.brzodolokacije.Activities import android.Manifest -import android.app.AlertDialog import android.content.Context -import android.content.DialogInterface import android.content.pm.PackageManager -import android.graphics.Color import android.location.Location import android.location.LocationManager import android.os.Build @@ -21,17 +18,18 @@ import android.view.View import android.widget.* import android.widget.AdapterView.OnItemClickListener import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.content.res.AppCompatResources import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.core.widget.addTextChangedListener import com.example.brzodolokacije.Models.LocationType -import com.example.brzodolokacije.Models.PostPreview import com.example.brzodolokacije.R import com.example.brzodolokacije.Services.GeocoderHelper import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper import com.google.android.gms.location.* import com.google.android.material.button.MaterialButton +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.floatingactionbutton.FloatingActionButton import org.osmdroid.config.Configuration import org.osmdroid.tileprovider.tilesource.TileSourceFactory @@ -39,7 +37,6 @@ import org.osmdroid.util.GeoPoint import org.osmdroid.views.MapView import org.osmdroid.views.Projection import org.osmdroid.views.overlay.ItemizedIconOverlay -import org.osmdroid.views.overlay.Marker import org.osmdroid.views.overlay.Overlay import org.osmdroid.views.overlay.OverlayItem import org.osmdroid.views.overlay.ScaleBarOverlay @@ -50,8 +47,6 @@ import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay import retrofit2.Call import retrofit2.Response -import java.util.* -import kotlin.collections.ArrayList class MapsActivity : AppCompatActivity() { @@ -126,18 +121,26 @@ class MapsActivity : AppCompatActivity() { } fun addLocation(){ var editText=EditText(this) - var dialog=AlertDialog.Builder(this).setTitle("Naziv").setMessage("Unesite naziv") - .setView(editText) - dialog.setPositiveButton("Dodaj") { dialog, which -> + var builder=MaterialAlertDialogBuilder(this) + builder.background = AppCompatResources.getDrawable(this,R.drawable.rounded_alert_background) + builder.setView(editText) + builder.setTitle("Unesite naziv lokacije") + if(searchBar.text!=null && searchBar.text.toString().trim()!="") + editText.setText(searchBar.text.toString()) + builder.setPositiveButton("Dodaj") { dialog, which -> uploadLocation(editText.text.toString()) } - dialog.setNegativeButton("Prekini") { dialog, which -> + builder.setNegativeButton("Prekini") { dialog, which -> } - dialog.show() + builder.show() } fun uploadLocation(locationName:String){ + if(locationName.isNullOrEmpty() ||locationName.toString().trim()=="") { + Toast.makeText(this@MapsActivity,"Morate uneti naziv lokacije",Toast.LENGTH_SHORT).show() + return + } val api =RetrofitHelper.getInstance() var geocoder=GeocoderHelper.getInstance() var loc1=geocoder!!.getFromLocation(locLatitude!!,locLongitude!!,1) @@ -399,16 +402,16 @@ class MapsActivity : AppCompatActivity() { //Log.d("Main",geocoder!!.getFromLocationName("Paris",1)[0].countryName) var locString=searchBar.text.toString().trim() if(locString==null || locString=="") - Toast.makeText(this,"Unesite naziv lokacije", Toast.LENGTH_LONG) + Toast.makeText(this@MapsActivity,"Unesite naziv lokacije", Toast.LENGTH_LONG) else{ var temp=geocoder!!.getFromLocationName(locString,1) if(temp.size<=0) { - Toast.makeText(this,"Nepostojeca lokacija",Toast.LENGTH_LONG) + Toast.makeText(this@MapsActivity,"Nepostojeca lokacija",Toast.LENGTH_LONG) return } var result=temp[0] if(result==null) - Toast.makeText(this,"Nepostojeca lokacija", Toast.LENGTH_LONG) + Toast.makeText(this@MapsActivity,"Nepostojeca lokacija", Toast.LENGTH_LONG) else{ //Move to spot val searchPoint = GeoPoint(result.latitude,result.longitude) diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/NavigationActivity.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/NavigationActivity.kt index 23cbca6..01c6993 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/NavigationActivity.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/NavigationActivity.kt @@ -1,18 +1,19 @@ package com.example.brzodolokacije.Activities import android.content.Intent -import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.View import android.widget.Button import android.widget.ImageButton -import android.widget.Toast -import androidx.appcompat.app.AppCompatDelegate +import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import com.example.brzodolokacije.Fragments.* import com.example.brzodolokacije.R import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomsheet.BottomSheetDialog +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.launch +import net.yslibrary.android.keyboardvisibilityevent.KeyboardVisibilityEvent class NavigationActivity : AppCompatActivity() { @@ -33,6 +34,7 @@ class NavigationActivity : AppCompatActivity() { val profileFragment=FragmentProfile() bottomNav=findViewById<View>(R.id.bottomNavigationView) as BottomNavigationView setCurrentFragment(fragmentHomePage) + KeyboardEvents() bottomNav.setOnNavigationItemSelectedListener { when(it.itemId){ R.id.navHomePage->setCurrentFragment(fragmentHomePage) @@ -61,34 +63,25 @@ class NavigationActivity : AppCompatActivity() { bottomSheetDialog2.setContentView(R.layout.bottom_sheet_add_new_post) bottomSheetDialog2.show() - var close=bottomSheetDialog2.findViewById<View>(R.id.btnBottomSheetAddNewPostClose) as ImageButton - var openAddPost=bottomSheetDialog2.findViewById<View>(R.id.btnBottomSheetAddNewPostOpenAddPost) as ImageButton - var capturePost=bottomSheetDialog2.findViewById<View>(R.id.btnBottomSheetAddNewPostOpenCapturePost) as ImageButton + + var openAddPost=bottomSheetDialog2.findViewById<View>(R.id.btnBottomSheetAddNewPostOpenAddPost) as Button + var capturePost=bottomSheetDialog2.findViewById<View>(R.id.btnBottomSheetAddNewPostOpenCapturePost) as Button openAddPost.setOnClickListener{ - Toast.makeText( - applicationContext, "Open select from gallery ", Toast.LENGTH_LONG - ).show(); val intent = Intent (this, ActivityAddPost::class.java) startActivity(intent) } capturePost.setOnClickListener{ - Toast.makeText( - applicationContext, "Open capture ", Toast.LENGTH_LONG - ).show(); + val intent = Intent (this, ActivityCapturePost::class.java) startActivity(intent) } - close.setOnClickListener { - bottomSheetDialog2.dismiss() - } + } private fun showBottomSheetAddNew(){ - Toast.makeText( - applicationContext, "Open add new ", Toast.LENGTH_LONG - ).show(); + var bottomSheetDialog:BottomSheetDialog bottomSheetDialog=BottomSheetDialog(this) bottomSheetDialog.setContentView(R.layout.bottom_sheet_add_new) @@ -103,17 +96,34 @@ class NavigationActivity : AppCompatActivity() { } newLocation.setOnClickListener{ - Toast.makeText( - applicationContext, "Open capture ", Toast.LENGTH_LONG - ).show(); + val intent = Intent (this, MapsActivity::class.java) startActivity(intent) } - close.setOnClickListener { - bottomSheetDialog.dismiss() + + } + + fun KeyboardEvents(){ + KeyboardVisibilityEvent.setEventListener( + this + ) { isOpen -> + if (isOpen) { + bottomNav.visibility = View.GONE + bottomNav.forceLayout() + + } else { + MainScope().launch { + bottomNav.visibility = View.VISIBLE + bottomNav.forceLayout() + } + } } } + fun changeToProfile(){ + setCurrentFragment(FragmentProfile()) + bottomNav.menu.findItem(R.id.navProfile).isChecked = true + } }
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ChatMessagesAdapter.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ChatMessagesAdapter.kt index 403b736..ec436bd 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ChatMessagesAdapter.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ChatMessagesAdapter.kt @@ -51,7 +51,11 @@ class ChatMessagesAdapter (val items : MutableList<Message>, val activity:Activi fun bind(item : Message){ bindingOther?.apply { tvMessage?.text=item.messagge - tvTimestamp.text=item.usableTimeStamp.get(Calendar.HOUR_OF_DAY).toString() + ":" + item.usableTimeStamp.get(Calendar.MINUTE).toString() + var hour=item.usableTimeStamp.get(Calendar.HOUR_OF_DAY) + var hourStr=if(hour<10) "0"+hour.toString() else hour.toString() + var minute=item.usableTimeStamp.get(Calendar.MINUTE) + var minuteStr=if(minute<10) "0"+minute.toString() else minute.toString() + tvTimestamp.text= hourStr + ":" + minuteStr if(layoutPosition==0 || isDifferentDays(items[layoutPosition].usableTimeStamp,items[layoutPosition-1].usableTimeStamp)){ tvDate.text=item.usableTimeStamp.get(Calendar.DAY_OF_MONTH).toString()+"/"+ @@ -69,7 +73,11 @@ class ChatMessagesAdapter (val items : MutableList<Message>, val activity:Activi fun bind(item : Message){ binding?.apply { tvMessage.text=item.messagge - tvTimestamp.text=item.usableTimeStamp.get(Calendar.HOUR_OF_DAY).toString() + ":" + item.usableTimeStamp.get(Calendar.MINUTE).toString() + var hour=item.usableTimeStamp.get(Calendar.HOUR_OF_DAY) + var hourStr=if(hour<10) "0"+hour.toString() else hour.toString() + var minute=item.usableTimeStamp.get(Calendar.MINUTE) + var minuteStr=if(minute<10) "0"+minute.toString() else minute.toString() + tvTimestamp.text= hourStr + ":" + minuteStr if(layoutPosition==0 || isDifferentDays(items[layoutPosition].usableTimeStamp,items[layoutPosition-1].usableTimeStamp)){ tvDate.text=item.usableTimeStamp.get(Calendar.DAY_OF_MONTH).toString()+"/"+ diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ChatPreviewsAdapter.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ChatPreviewsAdapter.kt index be564f4..1ed6542 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ChatPreviewsAdapter.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ChatPreviewsAdapter.kt @@ -42,16 +42,6 @@ class ChatPreviewsAdapter (val items : MutableList<ChatPreview>,val activity:Cha override fun onBindViewHolder(holder: ViewHolder, position: Int){ //sets components of particular item holder.bind(items[position]) - holder.itemView.setOnClickListener { - val intent: Intent = Intent(activity, ChatActivityConversation::class.java) - intent.putExtra("userId",items[position].userId) - intent.putExtra("username",holder.itemView.tvUsername.text) - intent.putExtra("pfp",holder.itemView.ivUserImage.drawable.toBitmap(200,200)) - db.readContact(items[position].userId) - items[position].read=true - holder.itemView.tvUsername.typeface= Typeface.DEFAULT - activity.startActivity(intent) - } } override fun getItemCount() = items.size inner class ViewHolder(itemView : ChatPreviewBinding) : RecyclerView.ViewHolder(itemView.root){ @@ -70,7 +60,7 @@ class ChatPreviewsAdapter (val items : MutableList<ChatPreview>,val activity:Cha tvUsername.text=user.username if(user.pfp!=null) { Glide.with(activity) - .load(RetrofitHelper.baseUrl + "/api/post/image/" + user.pfp!!._id) + .load(RetrofitHelper.baseUrl + "/api/post/image/compress/" + user.pfp!!._id) .circleCrop() .into(ivUserImage) } @@ -90,10 +80,14 @@ class ChatPreviewsAdapter (val items : MutableList<ChatPreview>,val activity:Cha var lastMessage=db.getLastMessage(item.userId) tvUsername.text=item.username if(lastMessage!=null){ - tvLastMessage.text=lastMessage.messagge - if(layoutPosition==0 || isDifferentDays(lastMessage.usableTimeStamp,Calendar.getInstance())){ - tvLastMessageDate.text=lastMessage.usableTimeStamp.get(Calendar.HOUR_OF_DAY).toString() + ":" + lastMessage.usableTimeStamp.get( - Calendar.MINUTE).toString() + //var msg=lastMessage.messagge.dropLast(if(lastMessage.messagge.length>20) lastMessage.messagge.length-20 else 0) + tvLastMessage.text=lastMessage.messagge//msg+if(lastMessage.messagge.length>20) "..." else "" + if(!isDifferentDays(lastMessage.usableTimeStamp,Calendar.getInstance())){ + var hour=lastMessage.usableTimeStamp.get(Calendar.HOUR_OF_DAY) + var hourStr=if(hour<10) "0"+hour.toString() else hour.toString() + var minute=lastMessage.usableTimeStamp.get(Calendar.MINUTE) + var minuteStr=if(minute<10) "0"+minute.toString() else minute.toString() + tvLastMessageDate.text= hourStr + ":" + minuteStr } else{ tvLastMessageDate.text=lastMessage.usableTimeStamp.get(Calendar.DAY_OF_MONTH).toString()+"/"+ @@ -102,6 +96,16 @@ class ChatPreviewsAdapter (val items : MutableList<ChatPreview>,val activity:Cha } } + itemView.setOnClickListener { + val intent: Intent = Intent(activity, ChatActivityConversation::class.java) + intent.putExtra("userId",items[position].userId) + intent.putExtra("username",itemView.tvUsername.text) + intent.putExtra("pfp",itemView.ivUserImage.drawable.toBitmap(200,200)) + db.readContact(items[position].userId) + items[position].read=true + setRead() + activity.startActivity(intent) + } } } fun isDifferentDays(c1:Calendar,c2:Calendar):Boolean{ @@ -123,5 +127,16 @@ class ChatPreviewsAdapter (val items : MutableList<ChatPreview>,val activity:Cha itemView.readIndicator.background= ContextCompat.getDrawable(activity,R.color.dark_blue_transparent) itemView.readIndicator.invalidate() } + + fun setRead(){ + itemView.tvUsername.typeface= Typeface.DEFAULT + itemView.tvUsername.invalidate() + itemView.tvLastMessage.typeface= Typeface.DEFAULT + itemView.tvLastMessage.invalidate() + itemView.tvLastMessageDate.typeface= Typeface.DEFAULT + itemView.tvLastMessageDate.invalidate() + itemView.readIndicator.background= ContextCompat.getDrawable(activity,R.color.white) + itemView.readIndicator.invalidate() + } } }
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/CommentsAdapter.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/CommentsAdapter.kt index 8f737a3..fc77d76 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/CommentsAdapter.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/CommentsAdapter.kt @@ -2,6 +2,8 @@ package com.example.brzodolokacije.Adapters import android.app.Activity import android.content.Context +import android.content.Intent +import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View @@ -9,22 +11,28 @@ import android.view.ViewGroup import android.view.inputmethod.InputMethodManager import android.widget.EditText import android.widget.Toast +import androidx.core.content.ContextCompat import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.example.brzodolokacije.Activities.ActivitySinglePost +import com.example.brzodolokacije.Activities.ActivityUserProfile +import com.example.brzodolokacije.Fragments.FragmentSinglePostComments import com.example.brzodolokacije.Interfaces.IBackendApi import com.example.brzodolokacije.Models.CommentReceive import com.example.brzodolokacije.Models.CommentSend import com.example.brzodolokacije.Models.UserReceive +import com.example.brzodolokacije.R import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper import com.example.brzodolokacije.databinding.SingleCommentBinding +import com.google.gson.Gson import kotlinx.android.synthetic.main.single_comment.view.* import retrofit2.Call import retrofit2.Response +import java.util.* -class CommentsAdapter (val items : MutableList<CommentSend>,val activity: Activity) +class CommentsAdapter (val items : MutableList<CommentSend>,val activity: Activity, val fragment:FragmentSinglePostComments) : RecyclerView.Adapter<CommentsAdapter.ViewHolder>(){ //constructer has one argument - list of objects that need to be displayed //it is bound to xml of single item @@ -52,6 +60,8 @@ class CommentsAdapter (val items : MutableList<CommentSend>,val activity: Activi inner class ViewHolder(itemView : SingleCommentBinding) : RecyclerView.ViewHolder(itemView.root){ fun bind(item : CommentSend){ binding.apply { + var color = ContextCompat.getColor(activity, R.color.purple_500) + etReplyCount.setTextColor(color) tvCommentAuthor.text=item.username tvCommentText.text=item.comment Log.d("info",tvCommentText.text.toString()+binding.toString()) @@ -80,7 +90,7 @@ class CommentsAdapter (val items : MutableList<CommentSend>,val activity: Activi else{ showKeyboard(etReply) btnPostReply.setOnClickListener{ - if(etReply.text.isNotEmpty()){ + if(etReply.text!!.isNotEmpty()){ val postId=(activity as ActivitySinglePost).post._id Log.d("main",binding.toString()) val comment= CommentReceive(etReply.text.toString(),item._id) @@ -92,17 +102,47 @@ class CommentsAdapter (val items : MutableList<CommentSend>,val activity: Activi } } } + ivPfp.setOnClickListener { + val intent: Intent = Intent(activity, ActivityUserProfile::class.java) + var b= Bundle() + intent.putExtra("user", Gson().toJson( + UserReceive(item.userId,"",item.username,"", + Date(),null,0, listOf(),0,listOf(),0,listOf(),0,null) + )) + activity.startActivity(intent) + } var rv: RecyclerView = rvReplies rv.setHasFixedSize(true) rv.layoutManager=LinearLayoutManager(activity,LinearLayoutManager.VERTICAL,false) - if(item.replies!=null) - rv.adapter=CommentsAdapter(item.replies as MutableList<CommentSend>,activity) - else - rv.adapter=CommentsAdapter(mutableListOf(),activity) + etReplyCount.setOnClickListener { + if(llReplies.visibility==View.VISIBLE) + llReplies.visibility=View.GONE + else + llReplies.visibility=View.VISIBLE + llReplies.forceLayout() + } + if(item.replies!=null){ + setReplyCount(layoutPosition) + rv.adapter=CommentsAdapter(item.replies as MutableList<CommentSend>,activity,fragment) + } + else { + rv.adapter = CommentsAdapter(mutableListOf(), activity, fragment) + } } } + fun setReplyCount(position: Int){ + + if(items[position].replies==null) + items[position].replies= mutableListOf() + if(items[position].replies!!.count()==1) + itemView.etReplyCount.text=items[position].replies!!.count().toString() + " odgovor" + else + itemView.etReplyCount.text=items[position].replies!!.count().toString() + " odgovora" + itemView.clReplyCount.visibility=View.VISIBLE + itemView.clReplyCount.invalidate() + } fun showKeyboard(item:EditText){ var imm:InputMethodManager=activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.showSoftInput(item,InputMethodManager.SHOW_IMPLICIT) @@ -121,9 +161,10 @@ class CommentsAdapter (val items : MutableList<CommentSend>,val activity: Activi if(response.isSuccessful){ var newComment=response.body()!! requestGetComments(newComment) - itemView.etReply.text.clear() + itemView.etReply.text!!.clear() hideKeyboard(itemView.etReply) itemView.etReply.clearFocus() + setReplyCount(bindingAdapterPosition) }else{ if(response.errorBody()!=null) Log.d("main1",response.message().toString()) @@ -143,7 +184,7 @@ class CommentsAdapter (val items : MutableList<CommentSend>,val activity: Activi var adapter:CommentsAdapter=rv.adapter as CommentsAdapter adapter.items.add(0,newComment) rv.adapter=adapter - //(activity as ActivitySinglePost).addedComment() + fragment.addedComment() } private fun requestProfilePic(item:CommentSend){ diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/FollowersAdapter.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/FollowersAdapter.kt index 5381ebc..ff798cc 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/FollowersAdapter.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/FollowersAdapter.kt @@ -1,18 +1,20 @@ package com.example.brzodolokacije.Adapters import android.app.Activity -import android.util.Log +import android.content.Intent +import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.ImageView import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide -import com.example.brzodolokacije.Models.PostPreview -import com.example.brzodolokacije.Models.User +import com.example.brzodolokacije.Activities.ActivityUserProfile import com.example.brzodolokacije.Models.UserReceive import com.example.brzodolokacije.R import com.example.brzodolokacije.Services.RetrofitHelper +import com.google.gson.Gson class FollowersAdapter (var followers:MutableList<UserReceive>, val activity: Activity): RecyclerView.Adapter<FollowersAdapter.FollowerViewHolder>() { @@ -34,9 +36,22 @@ class FollowersAdapter (var followers:MutableList<UserReceive>, val activity: Ac private val name: TextView =view.findViewById(R.id.tvFollowerItemName) private val username:TextView=view.findViewById(R.id.tvFollowerItemUsername) + private val pfp: ImageView =view.findViewById(R.id.tvFragmentProfileProfilePicture) fun bindView(follower: UserReceive){ name.text=follower.name username.text="@"+follower.username + if(follower.pfp!=null) { + Glide.with(activity) + .load(RetrofitHelper.baseUrl + "/api/post/image/compress/" + follower.pfp!!._id) + .circleCrop() + .into(pfp) + } + itemView.setOnClickListener { + val intent: Intent = Intent(activity, ActivityUserProfile::class.java) + var b= Bundle() + intent.putExtra("user", Gson().toJson(follower)) + activity.startActivity(intent) + } } } }
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/MonthViewsAdapter.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/MonthViewsAdapter.kt new file mode 100644 index 0000000..240deb0 --- /dev/null +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/MonthViewsAdapter.kt @@ -0,0 +1,63 @@ +package com.example.brzodolokacije.Adapters + +import android.app.Activity +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.example.brzodolokacije.Models.MonthlyViews +import com.example.brzodolokacije.databinding.SingleDateViewBinding + +class MonthViewsAdapter (val activity: Activity, val items : MutableList<MonthlyViews>) + : RecyclerView.Adapter<MonthViewsAdapter.ViewHolder>() { + + + private lateinit var binding: SingleDateViewBinding + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val inflater = LayoutInflater.from(parent.context) + binding = SingleDateViewBinding.inflate(inflater, parent, false) + return ViewHolder(binding) + } + + + + + override fun getItemCount() = items.size + inner class ViewHolder(itemView: SingleDateViewBinding) : RecyclerView.ViewHolder(itemView.root) { + fun bind(item: MonthlyViews) { + binding.apply { + tvMonth.text=numberToMonthName(item.month) + tvMonthViews.text=item.views.toString() + + } + } + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + return holder.bind(items[position]) + + } + fun numberToMonthName(number:Int):String{ + var text="" + when (number) { + 1 -> text="Januar" + 2 -> text="Februar" + 3 -> text="Mart" + 4 -> text="April" + 5 -> text="Maj" + 6 -> text="Jun" + 7 -> text="Jul" + 8 -> text="Avgust" + 9 -> text="Septembar" + 10 -> text="Oktobar" + 11 -> text="Novembar" + 12 -> text="Decembar" + else -> { + text = "nedefinisan" + } + } + + return text + + } + +} diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/MyPostsAdapter.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/MyPostsAdapter.kt index e557e02..7ea97f6 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/MyPostsAdapter.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/MyPostsAdapter.kt @@ -2,12 +2,10 @@ package com.example.brzodolokacije.Adapters import android.app.Activity import android.content.Intent -import android.graphics.BitmapFactory -import android.os.AsyncTask import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup -import android.widget.Toast import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.example.brzodolokacije.Activities.ActivitySinglePost @@ -16,12 +14,9 @@ import com.example.brzodolokacije.Models.LocationType import com.example.brzodolokacije.Models.PostPreview import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper +import com.example.brzodolokacije.databinding.PostItemHomePageBinding +import com.example.brzodolokacije.databinding.PostItemUserPostBinding import com.example.brzodolokacije.databinding.PostPreviewBinding -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch -import okhttp3.ResponseBody -import retrofit2.Call -import retrofit2.Response class MyPostsAdapter (val activity:Activity,val items : MutableList<PostPreview>) @@ -29,14 +24,12 @@ class MyPostsAdapter (val activity:Activity,val items : MutableList<PostPreview> private lateinit var token: String private lateinit var imageApi: IBackendApi - //constructer has one argument - list of objects that need to be displayed - //it is bound to xml of single item - private lateinit var binding: PostPreviewBinding + private lateinit var binding: PostItemUserPostBinding override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val inflater = LayoutInflater.from(parent.context) imageApi= RetrofitHelper.getInstance() token= SharedPreferencesHelper.getValue("jwt", activity).toString() - binding = PostPreviewBinding.inflate(inflater, parent, false) + binding = PostItemUserPostBinding.inflate(inflater, parent, false) return ViewHolder(binding) } @@ -44,17 +37,19 @@ class MyPostsAdapter (val activity:Activity,val items : MutableList<PostPreview> override fun getItemCount() = items.size - inner class ViewHolder(itemView: PostPreviewBinding) : RecyclerView.ViewHolder(itemView.root) { + inner class ViewHolder(itemView: PostItemUserPostBinding) : RecyclerView.ViewHolder(itemView.root) { fun bind(item: PostPreview) { binding.apply { - tvTitle.text = item.location.name - tvLocationParent.text = item.location.country - tvPostPreviewRating.text=item.ratings.toString() + piupLocation.text = item.location.name + piupLocationDetail.text = item.location.country + piuprating.text=item.ratings.toString() + if(item.images.size>1) + ivMultipleImagesIcon.visibility= View.VISIBLE // tvLocationType.text = "TODO" if(item.images.isNotEmpty()) { Glide.with(activity) .load(RetrofitHelper.baseUrl + "/api/post/image/compress/" + item.images[0]._id) - .into(locationImage) + .into(piupbackground) } } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/OpenedPostImageAdapter.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/OpenedPostImageAdapter.kt new file mode 100644 index 0000000..2a73072 --- /dev/null +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/OpenedPostImageAdapter.kt @@ -0,0 +1,75 @@ +package com.example.brzodolokacije.Adapters + +import android.app.Activity +import android.net.Uri +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView +import com.example.brzodolokacije.Models.PostImage +import com.example.brzodolokacije.Services.RetrofitHelper +import com.example.brzodolokacije.databinding.OpenedPostImageBinding +import com.github.piasy.biv.BigImageViewer +import com.github.piasy.biv.loader.ImageLoader +import com.github.piasy.biv.loader.glide.GlideImageLoader +import com.github.piasy.biv.view.BigImageView +import java.io.File + +class OpenedPostImageAdapter(val items:List<PostImage>?,val activity:Activity): RecyclerView.Adapter<OpenedPostImageAdapter.ViewHolder>() { + lateinit var binding:OpenedPostImageBinding + + inner class ViewHolder(itemView: OpenedPostImageBinding) : RecyclerView.ViewHolder(itemView.root) { + fun bind(item:PostImage){ + binding.apply { + ivOpenedImage.setImageLoaderCallback(object : ImageLoader.Callback{ + override fun onCacheHit(imageType: Int, image: File?) { + ivOpenedImage.ssiv.orientation = SubsamplingScaleImageView.ORIENTATION_USE_EXIF + } + + override fun onCacheMiss(imageType: Int, image: File?) { + } + + override fun onStart() { + } + + override fun onProgress(progress: Int) { + } + + override fun onFinish() { + ivOpenedImage.ssiv.orientation = SubsamplingScaleImageView.ORIENTATION_USE_EXIF + } + + override fun onSuccess(image: File?) { + } + + override fun onFail(error: Exception?) { + } + + }) + ivOpenedImage.setInitScaleType(BigImageView.INIT_SCALE_TYPE_CENTER_CROP) + ivOpenedImage.showImage(Uri.parse(RetrofitHelper.baseUrl + "/api/post/image/compress/" + item._id)) + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + BigImageViewer.initialize(GlideImageLoader.with(activity)) + val inflater = LayoutInflater.from(parent.context) + binding= OpenedPostImageBinding.inflate(inflater,parent,false) + return ViewHolder(binding) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(items!![position]) + } + + override fun getItemCount(): Int { + if(items==null){ + return 0 + } + else{ + return items.size + } + } + +}
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/PostImageAdapter.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/PostImageAdapter.kt index 74bfd92..f3a8345 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/PostImageAdapter.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/PostImageAdapter.kt @@ -1,17 +1,16 @@ package com.example.brzodolokacije.Adapters import android.app.Activity -import android.graphics.BitmapFactory -import android.media.Image +import android.content.Intent import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide -import com.example.brzodolokacije.Models.Post +import com.example.brzodolokacije.Activities.ActivityOpenedImages +import com.example.brzodolokacije.Activities.ActivitySinglePost import com.example.brzodolokacije.Models.PostImage import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.databinding.PostImageBinding -import com.example.brzodolokacije.databinding.PostPreviewBinding class PostImageAdapter(val activity: Activity, val items : MutableList<PostImage>) : RecyclerView.Adapter<PostImageAdapter.ViewHolder>(){ @@ -37,6 +36,11 @@ class PostImageAdapter(val activity: Activity, val items : MutableList<PostImage .into(locationImage) } } + itemView.setOnClickListener { + val intent: Intent = Intent(activity, ActivityOpenedImages::class.java) + intent.putExtra("post",(activity as ActivitySinglePost).post) + activity.startActivity(intent) + } } } }
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ShowPostsAdapter.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ShowPostsAdapter.kt index 8605246..ed05191 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ShowPostsAdapter.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ShowPostsAdapter.kt @@ -3,7 +3,9 @@ package com.example.brzodolokacije.Adapters import android.app.Activity import android.content.Intent import android.os.Bundle +import android.util.Log import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.paging.PagingDataAdapter @@ -16,6 +18,8 @@ import com.example.brzodolokacije.Models.PostPreview import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper import com.example.brzodolokacije.databinding.PostPreviewBinding +import kotlinx.android.synthetic.main.post_preview.view.* +import java.text.SimpleDateFormat class ShowPostsAdapter (val activity:Activity,val items : MutableList<PostPreview>?=null) @@ -51,7 +55,7 @@ class ShowPostsAdapter (val activity:Activity,val items : MutableList<PostPrevie //sets components of particular item holder.bind(getItem(position)!!) holder.itemView.setOnClickListener { - Toast.makeText(activity,getItem(position)!!._id,Toast.LENGTH_LONG).show() + val intent:Intent = Intent(activity,ActivitySinglePost::class.java) var b=Bundle() //getItem(position)!!.location.type=LocationType.ADA @@ -65,9 +69,16 @@ class ShowPostsAdapter (val activity:Activity,val items : MutableList<PostPrevie inner class ViewHolder(itemView: PostPreviewBinding) : RecyclerView.ViewHolder(itemView.root) { fun bind(item: PostPreview) { - binding.apply { + itemView.apply { + tvPostPreviewDate.text= SimpleDateFormat("dd/MM/yyyy").format(item.createdAt) tvTitle.text = item.location.name - tvLocationParent.text = item.location.country + if(item.location.city!=null) + tvLocationParent.text = item.location.city + else + tvLocationParent.text = item.location.country + tvPostPreviewRating.text=item.ratings.toString() + if(item.images.size>1) + ivMultipleImagesIcon.visibility= View.VISIBLE //tvLocationType.text = "TODO" if(item.images.isNotEmpty()) { Glide.with(activity) diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ShowPostsGridViewAdapter.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ShowPostsGridViewAdapter.kt new file mode 100644 index 0000000..f837afd --- /dev/null +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ShowPostsGridViewAdapter.kt @@ -0,0 +1,69 @@ +package com.example.brzodolokacije.Adapters + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import androidx.paging.PagingDataAdapter +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import com.example.brzodolokacije.Activities.ActivitySinglePost +import com.example.brzodolokacije.Models.LocationType +import com.example.brzodolokacije.Models.PostPreview +import com.example.brzodolokacije.R +import com.example.brzodolokacije.Services.RetrofitHelper + +class ShowPostsGridViewAdapter(val activity: Activity,var postPreview:MutableList<PostPreview>?=null): + PagingDataAdapter<PostPreview,ShowPostsGridViewAdapter.PostViewHolder1>(REPO_COMPARATOR) { + + companion object{ + private val REPO_COMPARATOR=object: DiffUtil.ItemCallback<PostPreview>(){ + override fun areContentsTheSame(oldItem: PostPreview, newItem: PostPreview): Boolean { + return oldItem._id==newItem._id + } + + override fun areItemsTheSame(oldItem: PostPreview, newItem: PostPreview): Boolean { + return oldItem._id==newItem._id + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostViewHolder1 { + val view= + LayoutInflater.from(parent.context).inflate(R.layout.post_item_grid_view,parent,false) + return PostViewHolder1(view) + } + override fun onBindViewHolder(holder: ShowPostsGridViewAdapter.PostViewHolder1, position: Int) { + holder.itemView.setOnClickListener { + val intent: Intent = Intent(activity, ActivitySinglePost::class.java) + var b= Bundle() + getItem(position)!!.location.type= LocationType.ADA + b.putParcelable("selectedPost", getItem(position)!!) + intent.putExtras(b) + activity.startActivity(intent) + } + return holder.bindView(getItem(position)!! ) + } + inner class PostViewHolder1(view: View): RecyclerView.ViewHolder(view){ + private val background:com.google.android.material.imageview.ShapeableImageView=view.findViewById( + R.id.postItemGridViewImage) + private val multipleImageIcon: ImageView =view.findViewById(R.id.ivPostItemMultipleImagesIcon) + + fun bindView(postPreview: PostPreview){ + if(postPreview.images.isNotEmpty()) { + Glide.with(activity) + .load(RetrofitHelper.baseUrl + "/api/post/image/compress/" + postPreview.images[0]._id) + .into(background) + } + if(postPreview.images.size>1) + multipleImageIcon.visibility= View.VISIBLE + + } + } + + +}
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ShowPostsHomePageAdapter.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ShowPostsHomePageAdapter.kt index 5b6d0f2..5569fd4 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ShowPostsHomePageAdapter.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Adapters/ShowPostsHomePageAdapter.kt @@ -7,6 +7,7 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.ImageView import android.widget.TextView import androidx.core.net.toUri import androidx.recyclerview.widget.RecyclerView @@ -49,6 +50,7 @@ inner class PostViewHolder(view: View):RecyclerView.ViewHolder(view){ private val locationName:TextView=view.findViewById(R.id.tvPIHPLocationName) private val locationDetail:TextView=view.findViewById(R.id.tvPIHPLocationDetail) private val rating:TextView=view.findViewById(R.id.tvPIHPRecension) + private val multipleImageIcon:ImageView=view.findViewById(R.id.ivMultipleImagesIcon) fun bindView(postPreview:PostPreview){ //background.setImageURI(postPreview.images[0]._id.to) @@ -59,7 +61,12 @@ inner class PostViewHolder(view: View):RecyclerView.ViewHolder(view){ } locationName.text=postPreview.location.name rating.text=postPreview.ratings.toString() - locationDetail.text="Srbija, Kragujevac" + if(postPreview.images.size>1) + multipleImageIcon.visibility=View.VISIBLE + if(postPreview.location.city!=null) + locationDetail.text=postPreview.location.city + else + locationDetail.text=postPreview.location.country } } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/FragmentProfileStatistics.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/FragmentProfileStatistics.kt new file mode 100644 index 0000000..1f0ff56 --- /dev/null +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/FragmentProfileStatistics.kt @@ -0,0 +1,98 @@ +package com.example.brzodolokacije + +import android.os.Bundle +import android.util.Log +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import android.widget.Toast +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.example.brzodolokacije.Adapters.MonthViewsAdapter +import com.example.brzodolokacije.Adapters.MyPostsAdapter +import com.example.brzodolokacije.Models.MonthlyViews +import com.example.brzodolokacije.Models.Statistics +import com.example.brzodolokacije.Models.UserReceive +import com.example.brzodolokacije.Services.RetrofitHelper +import com.example.brzodolokacije.Services.SharedPreferencesHelper +import retrofit2.Call +import retrofit2.Response + + +class FragmentProfileStatistics : Fragment() { + + private var stats:Statistics?=null + private var username:String?=null + private lateinit var totalViews:TextView + private lateinit var numberOfRatings:TextView + private lateinit var averageRatings:TextView + private lateinit var numberOfFavourite:TextView + private lateinit var rcMonths:RecyclerView + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + var view=inflater.inflate(R.layout.fragment_profile_statistics, container, false) + username=this.requireArguments().getString("username") + totalViews=view.findViewById(R.id.tvProfileStatisticsViews) + numberOfRatings=view.findViewById(R.id.tvProfileStatisticsRatingNumber) + averageRatings=view.findViewById(R.id.tvProfileStatisticsAverageRating) + numberOfFavourite=view.findViewById(R.id.tvProfileStatisticsFavouriteNumber) + rcMonths=view.findViewById(R.id.rvFragmentProfileStatisticsMonths) + + + + loadStats() + + return view + } + + + fun loadStats(){ + val authApi= RetrofitHelper.getInstance() + val token= SharedPreferencesHelper.getValue("jwt", requireActivity()) + val request=authApi.getUserStatsFromUsername("Bearer "+token,username!!) + + request.enqueue(object : retrofit2.Callback<Statistics?> { + override fun onResponse(call: Call<Statistics?>, response: Response<Statistics?>) { + if(response.isSuccessful()){ + stats=response.body() + loadText() + loadMonths() + + + } + } + override fun onFailure(call: Call<Statistics?>, t: Throwable) { + Toast.makeText( + activity, t.toString(), Toast.LENGTH_LONG + ).show(); + } + }) + + } + fun loadText(){ + totalViews.text=stats!!.totalViews.toString() + numberOfRatings.text=stats!!.numberOfRatingsOnPosts.toString() + averageRatings.text=stats!!.averagePostRatingOnPosts.toString() + numberOfFavourite.text=stats!!.numberOfFavouritePosts.toString() + } + private fun loadMonths(){ + rcMonths.apply { + layoutManager= GridLayoutManager(requireContext(),2) + adapter= MonthViewsAdapter(requireActivity(), + stats!!.monthlyViews as MutableList<MonthlyViews> + ) + + } + } + + +}
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentAddNew.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentAddNew.kt index 8eaa469..a5c3e88 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentAddNew.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentAddNew.kt @@ -41,9 +41,7 @@ class FragmentAddNew : Fragment() { addNewPost.setOnClickListener{ - Toast.makeText( - activity, "Add new post", Toast.LENGTH_LONG - ).show(); + val intent = Intent (getActivity(), ActivityAddPost::class.java) getActivity()?.startActivity(intent) diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentBrowse.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentBrowse.kt index a0d6146..bbfd583 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentBrowse.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentBrowse.kt @@ -209,8 +209,10 @@ class FragmentBrowse : Fragment(R.layout.fragment_browse) { for(post in postList){ Log.d("main",post.toString()) val startMarker = Marker(map) + startMarker.setPosition(GeoPoint(post.location.latitude,post.location.longitude)) startMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM) + startMarker.icon=ContextCompat.getDrawable(requireContext(), R.drawable.ic_baseline_location_on_24) startMarker.setOnMarkerClickListener(object:OnMarkerClickListener{ override fun onMarkerClick( marker: Marker?, @@ -335,7 +337,7 @@ class FragmentBrowse : Fragment(R.layout.fragment_browse) { .lastLocation // Set latitude map!!.controller.animateTo(GeoPoint(location1!!.latitude,location1!!.longitude)) - Toast.makeText(requireContext()," "+location1!!.latitude,Toast.LENGTH_LONG) + } } @@ -345,7 +347,7 @@ class FragmentBrowse : Fragment(R.layout.fragment_browse) { Looper.myLooper()); } else { map!!.controller.animateTo(GeoPoint(location!!.latitude,location!!.longitude)) - Toast.makeText(requireContext()," "+location.latitude,Toast.LENGTH_LONG) + } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentFollowers.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentFollowers.kt index 767c192..2a92e97 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentFollowers.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentFollowers.kt @@ -39,9 +39,7 @@ class FragmentFollowers : Fragment() { val bundle = this.arguments if (bundle != null) { userId= bundle.getString("userId").toString() - Toast.makeText( - activity, bundle.getString("userId"), Toast.LENGTH_LONG - ).show(); + } getFollowers() diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentFollowing.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentFollowing.kt index fe52723..a31fb47 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentFollowing.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentFollowing.kt @@ -34,9 +34,7 @@ class FragmentFollowing : Fragment() { val bundle = this.arguments if (bundle != null) { userId= bundle.getString("userId").toString() - Toast.makeText( - activity, bundle.getString("userId"), Toast.LENGTH_LONG - ).show(); + } getFollowing() diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentHome.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentHome.kt index fd5aa33..d0a9818 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentHome.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentHome.kt @@ -45,7 +45,7 @@ class FragmentHome : Fragment(R.layout.fragment_home) { val rootView = inflater?.inflate(R.layout.fragment_home, container, false) recyclerView = rootView?.findViewById(R.id.rvMain) // set recyclerView attributes - recyclerView?.setHasFixedSize(true) +// recyclerView?.setHasFixedSize(true) recyclerView?.layoutManager = layoutManagerVar recyclerView?.adapter = adapterVar return rootView diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentHomePage.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentHomePage.kt index a26aaba..66bc8e5 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentHomePage.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentHomePage.kt @@ -7,31 +7,26 @@ import android.view.KeyEvent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.* +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.AutoCompleteTextView +import android.widget.ImageView import androidx.core.view.isVisible import androidx.core.widget.addTextChangedListener import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentTransaction -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView +import com.auth0.android.jwt.JWT +import com.bumptech.glide.Glide import com.example.brzodolokacije.Activities.ChatActivity import com.example.brzodolokacije.Activities.NavigationActivity -import com.example.brzodolokacije.Adapters.ShowPostsHomePageAdapter -import com.example.brzodolokacije.Interfaces.IBackendApi import com.example.brzodolokacije.Models.Location -import com.example.brzodolokacije.Models.LocationType -import com.example.brzodolokacije.Models.PostPreview -import com.example.brzodolokacije.Models.SearchParams +import com.example.brzodolokacije.Models.UserReceive import com.example.brzodolokacije.R import com.example.brzodolokacije.Services.RetrofitHelper -import com.example.brzodolokacije.Services.RetrofitHelper.baseUrl import com.example.brzodolokacije.Services.SharedPreferencesHelper import com.google.android.material.button.MaterialButton import retrofit2.Call -import retrofit2.Callback import retrofit2.Response -import retrofit2.Retrofit -import retrofit2.converter.gson.GsonConverterFactory class FragmentHomePage : Fragment() { @@ -40,6 +35,7 @@ class FragmentHomePage : Fragment() { private lateinit var btnBack:ImageView private lateinit var searchBar:AutoCompleteTextView private lateinit var searchButton: MaterialButton + private lateinit var pfp:ImageView var responseLocations:MutableList<com.example.brzodolokacije.Models.Location>?=null /* override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -56,6 +52,7 @@ class FragmentHomePage : Fragment() { btnChat=view.findViewById(R.id.ivFragmentHomePageChat) searchBar=view.findViewById(R.id.etFragmentHomePageSearch) searchButton=view.findViewById(R.id.mbFragmentHomePageSearchButton) + pfp=view.findViewById(R.id.ivFragmentHomePageProfile) setBtnBackInvisible() setUpSpinner() var fm: FragmentTransaction =childFragmentManager.beginTransaction() @@ -88,16 +85,46 @@ class FragmentHomePage : Fragment() { false }) + pfp.setOnClickListener { + (activity as NavigationActivity).changeToProfile() + } + reqProfile() + return view } + fun reqProfile(){ + var api=RetrofitHelper.getInstance() + var token=SharedPreferencesHelper.getValue("jwt",requireActivity()) + val request2=api?.getProfileFromId("Bearer "+token, + JWT(token!!).claims["id"]!!.asString()!! + ) + request2?.enqueue(object : retrofit2.Callback<UserReceive?> { + override fun onResponse(call: Call<UserReceive?>, response: Response<UserReceive?>) { + if(response.isSuccessful()){ + //zahtev da se posalje poruka + var user=response.body()!! + if(user.pfp!=null) { + Glide.with(activity!!) + .load(RetrofitHelper.baseUrl + "/api/post/image/compress/" + user.pfp!!._id) + .circleCrop() + .into(pfp) + } + } + } - fun searchText(){ - if(searchBar.text==null || searchBar.text.toString().trim()=="") - return + override fun onFailure(call: Call<UserReceive?>, t: Throwable) { + } + }) + } + + fun searchText(){ var act=requireActivity() as NavigationActivity - act.searchQuery=searchBar.text.toString() + if(searchBar.text==null || searchBar.text.toString().trim()=="") + act.searchQuery="-1" + else + act.searchQuery=searchBar.text.toString() act.searchId="" act.bottomNav.selectedItemId=R.id.navAllPosts } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentHomePageMainScroll.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentHomePageMainScroll.kt index 82c78a1..3e42c2c 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentHomePageMainScroll.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentHomePageMainScroll.kt @@ -8,11 +8,12 @@ import android.widget.Button import android.widget.ImageButton import android.widget.LinearLayout import android.widget.Toast -import androidx.core.view.isVisible import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentTransaction import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener +import com.example.brzodolokacije.Activities.NavigationActivity import com.example.brzodolokacije.Adapters.ShowPostsHomePageAdapter import com.example.brzodolokacije.Interfaces.IBackendApi import com.example.brzodolokacije.Models.LocationType @@ -20,15 +21,15 @@ import com.example.brzodolokacije.Models.PostPreview import com.example.brzodolokacije.R import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper -import kotlinx.android.synthetic.main.fragment_home_page_main_scroll.* import retrofit2.Call import retrofit2.Callback import retrofit2.Response import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory -class FragmentHomePageMainScroll : Fragment() { +class FragmentHomePageMainScroll : Fragment(),OnRefreshListener { + private lateinit var swipeRefreshLayout: SwipeRefreshLayout private lateinit var posts : MutableList<PostPreview> private lateinit var mostViewedPosts : MutableList<PostPreview> private lateinit var newestPosts : MutableList<PostPreview> @@ -79,107 +80,50 @@ private lateinit var change:Button location_waterfall=view.findViewById(R.id.btnFragmentHomePagelocation_waterfall) //pokupi sve objave iz baze' - getAllPosts() + //getAllPosts() var bundle=Bundle() var fragment=FragmentShowPostsByLocation() location_spa.setOnClickListener { - filter=LocationType.BANJA - filterString=filter.toString() - bundle.putString("data",filterString) - fragment.arguments=bundle + tagSearch("Banja") + - val parentFrag: FragmentHomePage = this@FragmentHomePageMainScroll.getParentFragment() as FragmentHomePage - parentFrag.changeScrollVIewToLocationView() - parentFrag.setBtnBackVisible() } location_waterfall.setOnClickListener { - filter=LocationType.VODOPAD - filterString=filter.toString() - bundle.putString("data",filterString) - fragment.arguments=bundle - - val parentFrag: FragmentHomePage = this@FragmentHomePageMainScroll.getParentFragment() as FragmentHomePage - parentFrag.changeScrollVIewToLocationView() - parentFrag.setBtnBackVisible() + tagSearch("Vodopad") } location_mountain.setOnClickListener { - filter=LocationType.PLANINA - filterString=filter.toString() - bundle.putString("data",filterString) - fragment.arguments=bundle - - val parentFrag: FragmentHomePage = this@FragmentHomePageMainScroll.getParentFragment() as FragmentHomePage - parentFrag.changeScrollVIewToLocationView() - parentFrag.setBtnBackVisible() + tagSearch("Planina") } location_landmark.setOnClickListener { - filter=LocationType.LOKALITET - filterString=filter.toString() - bundle.putString("data",filterString) - fragment.arguments=bundle - - val parentFrag: FragmentHomePage = this@FragmentHomePageMainScroll.getParentFragment() as FragmentHomePage - parentFrag.changeScrollVIewToLocationView() - parentFrag.setBtnBackVisible() + tagSearch("Lokalitet") } location_city.setOnClickListener { - filter=LocationType.GRAD - filterString=filter.toString() - bundle.putString("data",filterString) - fragment.arguments=bundle - - val parentFrag: FragmentHomePage = this@FragmentHomePageMainScroll.getParentFragment() as FragmentHomePage - parentFrag.changeScrollVIewToLocationView() - parentFrag.setBtnBackVisible() + tagSearch("Grad") } location_lake.setOnClickListener { - filter=LocationType.JEZERO - filterString=filter.toString() - bundle.putString("data",filterString) - fragment.arguments=bundle - val parentFrag: FragmentHomePage = this@FragmentHomePageMainScroll.getParentFragment() as FragmentHomePage - parentFrag.changeScrollVIewToLocationView() - parentFrag.setBtnBackVisible() + tagSearch("Jezero") } location_attraction.setOnClickListener { - filter=LocationType.ATRAKCIJA - filterString=filter.toString() - bundle.putString("data",filterString) - fragment.arguments=bundle - val parentFrag: FragmentHomePage = this@FragmentHomePageMainScroll.getParentFragment() as FragmentHomePage - parentFrag.changeScrollVIewToLocationView() - parentFrag.setBtnBackVisible() + tagSearch("Atrakcija") } location_amusement_park.setOnClickListener { - filter=LocationType.ZABAVNI_PARK - filterString=filter.toString() - bundle.putString("data",filterString) - fragment.arguments=bundle - val parentFrag: FragmentHomePage = this@FragmentHomePageMainScroll.getParentFragment() as FragmentHomePage - parentFrag.changeScrollVIewToLocationView() - parentFrag.setBtnBackVisible() + tagSearch("Zabavni park") } location_beach.setOnClickListener { - filter=LocationType.PLAZA - filterString=filter.toString() - bundle.putString("data",filterString) - fragment.arguments=bundle - val parentFrag: FragmentHomePage = this@FragmentHomePageMainScroll.getParentFragment() as FragmentHomePage - parentFrag.changeScrollVIewToLocationView() - parentFrag.setBtnBackVisible() + tagSearch("Plaza") } /* ll1.isVisible=true @@ -190,13 +134,30 @@ private lateinit var change:Button } */ + swipeRefreshLayout = view.findViewById<View>(R.id.swipeContainer) as SwipeRefreshLayout + swipeRefreshLayout.setOnRefreshListener(this) + swipeRefreshLayout.setColorSchemeResources( + R.color.purple_200, + R.color.teal_200, + R.color.dark_blue_transparent, + R.color.purple_700 + ) + swipeRefreshLayout.post(kotlinx.coroutines.Runnable { + swipeRefreshLayout.isRefreshing=true + }) return view } + override fun onRefresh() { + getAllPosts() + } + + override fun onResume() { + super.onResume() + getAllPosts() + } + private fun getAllPosts(){ - Toast.makeText( - activity," get all", Toast.LENGTH_LONG - ).show(); val api = Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .baseUrl(RetrofitHelper.baseUrl) @@ -269,9 +230,7 @@ private lateinit var change:Button // Toast.makeText( // activity, "get all r ", Toast.LENGTH_LONG // ).show(); - Toast.makeText( - activity," get all newest", Toast.LENGTH_LONG - ).show(); + val api = RetrofitHelper.getInstance() val token= SharedPreferencesHelper.getValue("jwt", requireActivity()) val data=api.get10Newest("Bearer "+token) @@ -289,6 +248,7 @@ private lateinit var change:Button layoutManager= LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL,false) adapter= ShowPostsHomePageAdapter(newestposts,requireActivity()) } + swipeRefreshLayout.isRefreshing=false } override fun onFailure(call: Call<MutableList<PostPreview>>, t: Throwable) { @@ -301,9 +261,6 @@ private lateinit var change:Button // Toast.makeText( // activity, "get all br ", Toast.LENGTH_LONG // ).show(); - Toast.makeText( - activity," get all best", Toast.LENGTH_LONG - ).show(); val api = RetrofitHelper.getInstance() val token= SharedPreferencesHelper.getValue("jwt", requireActivity()) val data=api.get10Best("Bearer "+token) @@ -329,5 +286,11 @@ private lateinit var change:Button } + private fun tagSearch(tag:String){ + var act = requireActivity() as NavigationActivity + act.searchQuery = tag + act.searchId = "" + act.bottomNav.selectedItemId = R.id.navAllPosts + } }
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentLogin.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentLogin.kt index 01b3f1d..35309c4 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentLogin.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentLogin.kt @@ -3,6 +3,7 @@ package com.example.brzodolokacije.Fragments import android.content.Intent import android.graphics.Color import android.os.Bundle +import android.view.KeyEvent import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View @@ -49,6 +50,16 @@ class FragmentLogin : Fragment() { forgottenPassword = view.findViewById<View>(R.id.tvFragmentLoginForgottenPassword) as TextView login=view.findViewById<View>(R.id.btnFragmentLoginLogin) as Button + password.setOnKeyListener(View.OnKeyListener{v, keyCode, event -> + if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_UP){ + //Start your action + login.performClick() + //End action + return@OnKeyListener true + } + false + }) + //osluskivanje unosa login.setOnClickListener{ @@ -89,9 +100,6 @@ class FragmentLogin : Fragment() { override fun onResponse(call: Call<String?>, response: Response<String?>) { if(response.isSuccessful()){ val token=response.body().toString() - Toast.makeText( - activity, token, Toast.LENGTH_LONG - ).show(); SharedPreferencesHelper.addValue("jwt",token,activity!!) val intent= Intent(activity!!, NavigationActivity::class.java) startActivity(intent) diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentMyProfileInfo.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentMyProfileInfo.kt index d6e345b..4192f8d 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentMyProfileInfo.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentMyProfileInfo.kt @@ -1,24 +1,32 @@ package com.example.brzodolokacije.Fragments + import android.content.Intent +import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button -import androidx.core.content.ContextCompat.startActivity import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentTransaction import com.exam.DBHelper +import com.example.brzodolokacije.Activities.ActivityChangePassword import com.example.brzodolokacije.Activities.ActivityChangeUserData -import com.example.brzodolokacije.Activities.ActivityForgottenPassword import com.example.brzodolokacije.Activities.ActivityLoginRegister +import com.example.brzodolokacije.FragmentProfileStatistics import com.example.brzodolokacije.R +import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper class FragmentMyProfileInfo : Fragment() { private lateinit var logout:Button private lateinit var changeAccount:Button + private lateinit var statistics:Button + private lateinit var changePassword:Button + private lateinit var favouritePosts:Button + private lateinit var inviteFriends:Button override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -29,7 +37,10 @@ class FragmentMyProfileInfo : Fragment() { logout=view.findViewById<View>(R.id.buttonLogOut) as Button changeAccount=view.findViewById(R.id.changeAccountData) - + statistics=view.findViewById<View>(R.id.getAccoutStatistics) as Button + changePassword=view.findViewById(R.id.ChangePassword) + favouritePosts=view.findViewById(R.id.getMyFavorite) + inviteFriends=view.findViewById(R.id.inviteFriends) logout.setOnClickListener{ logOut() } @@ -39,6 +50,56 @@ class FragmentMyProfileInfo : Fragment() { getActivity()?.startActivity(intent) } + inviteFriends.setOnClickListener { + val uri: Uri = + Uri.parse(RetrofitHelper.baseUrl+"/api/app/download") // missing 'http://' will cause crashed + + val intent = Intent(Intent.ACTION_VIEW, uri) + startActivity(intent) + } + favouritePosts.setOnClickListener { + + val manager: androidx.fragment.app.FragmentManager? = fragmentManager + val transaction: FragmentTransaction = manager!!.beginTransaction() + + var fragment:FragmentUserPosts=FragmentUserPosts() + val bundle = Bundle() + var parentFragment:FragmentProfile=parentFragment as FragmentProfile + var username=parentFragment.usernameStringSend + bundle.putString("username", username) + fragment.arguments=bundle + + + + transaction.replace(R.id.flFragmentProfileFragmentContainer,fragment ) + transaction.commit() + + } + statistics.setOnClickListener { + + val manager: androidx.fragment.app.FragmentManager? = fragmentManager + val transaction: FragmentTransaction = manager!!.beginTransaction() + + var fragment:FragmentProfileStatistics=FragmentProfileStatistics() + val bundle = Bundle() + var parentFragment:FragmentProfile=parentFragment as FragmentProfile + var username=parentFragment.usernameStringSend + bundle.putString("username", username) + fragment.arguments=bundle + + + + transaction.replace(R.id.flFragmentProfileFragmentContainer,fragment ) + transaction.commit() + + } + + + changePassword.setOnClickListener { + val intent = Intent (getActivity(), ActivityChangePassword::class.java) + getActivity()?.startActivity(intent) + } + return view } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentProfile.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentProfile.kt index 6fe4678..9759002 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentProfile.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentProfile.kt @@ -15,6 +15,8 @@ import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentTransaction +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener import com.bumptech.glide.Glide import com.example.brzodolokacije.Activities.ActivityShowFollowersAndFollowing import com.example.brzodolokacije.Models.UserReceive @@ -41,7 +43,9 @@ private const val ARG_PARAM2 = "param2" * Use the [FragmentProfile.newInstance] factory method to * create an instance of this fragment. */ -class FragmentProfile : Fragment(com.example.brzodolokacije.R.layout.fragment_profile) { +class FragmentProfile : Fragment(com.example.brzodolokacije.R.layout.fragment_profile),OnRefreshListener { + private lateinit var swipeRefreshLayout: SwipeRefreshLayout + // TODO: Rename and change types of parameters private lateinit var username: TextView private lateinit var name: TextView @@ -60,6 +64,7 @@ class FragmentProfile : Fragment(com.example.brzodolokacije.R.layout.fragment_pr private lateinit var profilePicturePlus: MaterialButton private lateinit var showFollowers: TextView private lateinit var showFollowing: TextView + public var usernameStringSend:String?=null override fun onCreateView( @@ -131,8 +136,37 @@ class FragmentProfile : Fragment(com.example.brzodolokacije.R.layout.fragment_pr intent.putExtras(bundle) startActivity(intent) } - getProfileInfo() - openMyPosts() + swipeRefreshLayout = view.findViewById<View>(R.id.ProfileSwipeRefresh) as SwipeRefreshLayout + swipeRefreshLayout?.setOnRefreshListener(this@FragmentProfile) + swipeRefreshLayout?.setColorSchemeResources( + R.color.purple_200, + R.color.teal_200, + R.color.dark_blue_transparent, + R.color.purple_700 + ) + swipeRefreshLayout?.post(kotlinx.coroutines.Runnable { + swipeRefreshLayout?.isRefreshing=true + }) + + + followersNumber.setOnClickListener{ + val bundle = Bundle() + bundle.putString("userId","error") + bundle.putString("show","followers") + bundle.putString("showMy","yes") + val intent = Intent(activity, ActivityShowFollowersAndFollowing::class.java) + intent.putExtras(bundle) + startActivity(intent) + } + followingNumber.setOnClickListener { + val bundle = Bundle() + bundle.putString("userId","error") + bundle.putString("show","following") + bundle.putString("showMy","yes") + val intent = Intent(activity,ActivityShowFollowersAndFollowing::class.java) + intent.putExtras(bundle) + startActivity(intent) + } return view } fun openMyPosts(){ @@ -142,6 +176,16 @@ class FragmentProfile : Fragment(com.example.brzodolokacije.R.layout.fragment_pr fm.commit() } + override fun onRefresh() { + onResume() + } + + override fun onResume(){ + super.onResume() + getProfileInfo() + openMyPosts() + } + private fun addProfilePicture(){ val intent= Intent(Intent.ACTION_PICK) intent.action = Intent.ACTION_GET_CONTENT @@ -193,7 +237,9 @@ class FragmentProfile : Fragment(com.example.brzodolokacije.R.layout.fragment_pr override fun onResponse(call: Call<UserReceive?>, response: Response<UserReceive?>) { if(response.isSuccessful()){ setUserInfo(response.body()!!) + swipeRefreshLayout.isRefreshing=false }else{ + swipeRefreshLayout.isRefreshing=false if(response.errorBody()!=null) Toast.makeText(activity, response.errorBody()!!.string(), Toast.LENGTH_LONG).show(); } @@ -202,12 +248,14 @@ class FragmentProfile : Fragment(com.example.brzodolokacije.R.layout.fragment_pr Toast.makeText( activity, t.toString(), Toast.LENGTH_LONG ).show(); + swipeRefreshLayout.isRefreshing=false } }) } private fun setUserInfo(user:UserReceive){ name.setText(user.name) username.setText("@"+user.username) + usernameStringSend=user.username postsCount.setText(user.postcount.toString()) Log.d("follno",user.followersCount.toString()) Log.d("follno","helllllllllllllllllllllppppppppppppppppppppppppppppppp") diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentRegister.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentRegister.kt index e166d38..ac08d9c 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentRegister.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentRegister.kt @@ -2,6 +2,7 @@ package com.example.brzodolokacije.Fragments import android.graphics.Color import android.os.Bundle +import android.view.KeyEvent import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View @@ -42,6 +43,16 @@ class FragmentRegister : Fragment() { name = view.findViewById<View>(R.id.etFragmentRegisterName) as EditText register=view.findViewById<View>(R.id.btnFragmentRegisterRegister) as Button + password.setOnKeyListener(View.OnKeyListener{v, keyCode, event -> + if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_UP){ + //Start your action + register.performClick() + //End action + return@OnKeyListener true + } + false + }) + //osluskivanje unosa register.setOnClickListener{ diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentShowPosts.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentShowPosts.kt index 76fa4e0..a26ea43 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentShowPosts.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentShowPosts.kt @@ -1,6 +1,8 @@ package com.example.brzodolokacije.Fragments -import android.content.Intent + +import android.graphics.Color + import android.os.Bundle import android.util.Log import android.view.KeyEvent @@ -8,20 +10,21 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.* -import androidx.core.content.ContextCompat import androidx.core.widget.addTextChangedListener import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.paging.PagingData import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout -import com.example.brzodolokacije.Activities.ActivityAddPost -import com.example.brzodolokacije.Activities.ChatActivity import com.example.brzodolokacije.Activities.NavigationActivity import com.example.brzodolokacije.Adapters.ShowPostsAdapter +import com.example.brzodolokacije.Adapters.ShowPostsGridViewAdapter + import com.example.brzodolokacije.Models.Location +import com.example.brzodolokacije.Models.PostPreview import com.example.brzodolokacije.Models.SearchParams import com.example.brzodolokacije.R import com.example.brzodolokacije.Services.RetrofitHelper @@ -31,34 +34,45 @@ import com.example.brzodolokacije.paging.SearchPostsViewModel import com.example.brzodolokacije.paging.SearchPostsViewModelFactory import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.button.MaterialButton -import kotlinx.android.synthetic.main.fragment_show_posts.* +import kotlinx.android.synthetic.main.activity_splash_page.* +import kotlinx.android.synthetic.main.bottom_sheet_sort.* import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch -import org.osmdroid.util.GeoPoint -import org.osmdroid.views.overlay.ItemizedIconOverlay -import org.osmdroid.views.overlay.OverlayItem import retrofit2.Call import retrofit2.Response - class FragmentShowPosts : Fragment(), SwipeRefreshLayout.OnRefreshListener { + private var dataChanged:Boolean=false + private var flowData: PagingData<PostPreview>?=null private lateinit var binding: FragmentShowPostsBinding private var linearManagerVar: RecyclerView.LayoutManager? = null private var adapterVar: ShowPostsAdapter? = null + private var gridViewAdapter:ShowPostsGridViewAdapter?=null private var recyclerView: RecyclerView?=null - private var gridManagerVar: RecyclerView.LayoutManager?=null + // private var gridManagerVar: RecyclerView.LayoutManager?=null private var swipeRefreshLayout:SwipeRefreshLayout?=null private lateinit var searchButton: MaterialButton private lateinit var searchPostsViewModel:SearchPostsViewModel - private var searchParams:SearchParams?= SearchParams("Kragujevac",1,1) + private lateinit var btnFilter:ImageButton private lateinit var btnSort:ImageButton private lateinit var searchBar: AutoCompleteTextView var responseLocations:MutableList<com.example.brzodolokacije.Models.Location>?=null var selectedLocation:com.example.brzodolokacije.Models.Location?=null + + private lateinit var filter:Button + private lateinit var sort:Button + + private var filterBool:Boolean=false + private var ratingFrom:Int=-1 + private var ratingTo:Int=-1 + private var viewsFrom:Int=-1 + private var viewsTo:Int=-1 + private var searchParams:SearchParams?= SearchParams("-1",filterBool,1,1,ratingFrom,ratingTo,viewsFrom,viewsTo) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setUpViewModel() @@ -66,15 +80,21 @@ class FragmentShowPosts : Fragment(), SwipeRefreshLayout.OnRefreshListener { //instantiate adapter and linearLayout adapterVar=ShowPostsAdapter(requireActivity()) linearManagerVar= LinearLayoutManager(activity) - gridManagerVar=GridLayoutManager(activity,2) + //gridManagerVar=GridLayoutManager(activity,2) + + } fun searchText(){ - if(searchBar.text==null || searchBar.text.toString().trim()=="") - return var act=requireActivity() as NavigationActivity - act.searchQuery=searchBar.text.toString() + if(searchBar.text==null || searchBar.text.toString().trim()=="") + act.searchQuery="-1" + else{ + act.searchQuery=searchBar.text.toString() + } + + act.searchId="" - searchParams=SearchParams(searchBar.text.toString(),1,1) + searchParams=SearchParams(act.searchQuery,filterBool,1,1,ratingFrom,ratingTo,viewsFrom,viewsTo) requestToBack(searchParams!!) } fun onTextEnter(){ @@ -124,7 +144,7 @@ class FragmentShowPosts : Fragment(), SwipeRefreshLayout.OnRefreshListener { var act=requireActivity() as NavigationActivity act.searchQuery=selectedLocation!!.name act.searchId=selectedLocation!!._id - searchParams=SearchParams(selectedLocation!!._id,1,1)//to do sort type + searchParams=SearchParams(selectedLocation!!._id,filterBool,1,1,ratingFrom,ratingTo,viewsFrom,viewsTo)//to do sort type requestToBack(searchParams!!) }) @@ -138,8 +158,16 @@ class FragmentShowPosts : Fragment(), SwipeRefreshLayout.OnRefreshListener { fun setUpListeners(rootView: View?){ rootView?.findViewById<ImageButton>(R.id.btnGridLayout)?.setOnClickListener() { - if(recyclerView?.layoutManager!=gridManagerVar){ - recyclerView?.layoutManager=gridManagerVar + /*if(recyclerView?.layoutManager!=gridManagerVar){ + recyclerView?.layoutManager=gridManagerVar*/ + recyclerView?.apply { + layoutManager= GridLayoutManager(activity,2) + if(gridViewAdapter==null) + gridViewAdapter= ShowPostsGridViewAdapter(requireActivity()) + recyclerView?.adapter=gridViewAdapter + if(dataChanged) + gridViewAdapter?.submitData(lifecycle,flowData!!) + dataChanged=false } Log.d("main","klik") } @@ -148,19 +176,27 @@ class FragmentShowPosts : Fragment(), SwipeRefreshLayout.OnRefreshListener { if(recyclerView?.layoutManager!=linearManagerVar){ recyclerView?.layoutManager=linearManagerVar } + recyclerView?.adapter=adapterVar + if(dataChanged) + adapterVar?.submitData(lifecycle,flowData!!) + dataChanged=false Log.d("main","klik") } - rootView?.findViewById<ImageButton>(R.id.btnChat)?.setOnClickListener() { - val intent: Intent = Intent(activity, ChatActivity::class.java) - requireActivity().startActivity(intent) - } + } fun requestToBack(searchParams: SearchParams){ lifecycleScope.launch{ searchPostsViewModel.fetchPosts(searchParams).distinctUntilChanged().collectLatest { - adapterVar?.submitData(lifecycle,it) + if(recyclerView?.adapter == gridViewAdapter){ + gridViewAdapter?.submitData(lifecycle,it) + } + else{ + adapterVar?.submitData(lifecycle,it) + } + dataChanged=true + flowData=it swipeRefreshLayout?.isRefreshing=false } } @@ -172,11 +208,171 @@ class FragmentShowPosts : Fragment(), SwipeRefreshLayout.OnRefreshListener { ): View? { val rootView = inflater?.inflate(R.layout.fragment_show_posts, container, false) recyclerView = rootView?.findViewById(R.id.rvMain) + + // set recyclerView attributes - recyclerView?.setHasFixedSize(true) +// recyclerView?.setHasFixedSize(true) //recyclerView?.layoutManager = linearManagerVar recyclerView?.layoutManager = linearManagerVar recyclerView?.adapter = adapterVar + + + //filter dialog + var bottomSheetDialogFilter: BottomSheetDialog + bottomSheetDialogFilter = BottomSheetDialog(requireContext()) + bottomSheetDialogFilter.setContentView(R.layout.bottom_sheet_filter) + + //sort dialog + var bottomSheetDialogSort: BottomSheetDialog + bottomSheetDialogSort = BottomSheetDialog(requireContext()) + bottomSheetDialogSort.setContentView(R.layout.bottom_sheet_sort) + + var ratingFromInput=bottomSheetDialogFilter.findViewById<View>(R.id.filterRatingFrom) as EditText + var ratingToInput=bottomSheetDialogFilter.findViewById<View>(R.id.filterRatingTo) as EditText + var viewsFromInput=bottomSheetDialogFilter.findViewById<View>(R.id.filterViewsFrom) as EditText + var viewsToInput=bottomSheetDialogFilter.findViewById<View>(R.id.filterViewsTo) as EditText + + + btnFilter= rootView!!.findViewById(R.id.btnSortType) + btnSort=rootView!!.findViewById(R.id.btnSortDirection) + + btnFilter.setOnClickListener{ + bottomSheetDialogFilter.show() + + var filter = bottomSheetDialogFilter.findViewById<View>(R.id.btnBSFFilter) as Button + var radioGroupF = bottomSheetDialogFilter.findViewById<View>(R.id.radioGroupFilter) as RadioGroup + + filter.setOnClickListener { + + var selectedRadioButtonIdF: Int = radioGroupF.checkedRadioButtonId + if (selectedRadioButtonIdF != -1) { + var selectedRadioButtonF = + bottomSheetDialogFilter.findViewById<View>(selectedRadioButtonIdF) as RadioButton + val string: String = selectedRadioButtonF.text.toString().trim() + + if (string.equals("Prethodna nedelja")) { + searchParams!!.filterdate= 5 + } else if (string.equals("Prethodni mesec")) { + searchParams!!.filterdate=4 + } else if (string.equals("Prethodna tri meseca")) { + searchParams!!.filterdate=3 + } else if (string.equals("Prethodna godina")) { + searchParams!!.filterdate=2 + } else { + searchParams!!.filterdate=1 + } + } + if(ratingFromInput.text.toString().isNotEmpty()) { + if (ratingFromInput.text.toString().trim().toInt() >= 0) { + filterBool = true + ratingFrom = ratingFromInput.text.toString().toInt() + } else { + Toast.makeText( + activity, + "Vrednost rejtinga ne može biti negativna", + Toast.LENGTH_LONG + ).show(); + var fromrating = + bottomSheetDialogFilter.findViewById<View>(R.id.ratingFromtxt) as TextView + fromrating.setTextColor(Color.RED) + } + } + else{ + ratingFrom=-1 + } + if(ratingToInput.text.toString().isNotEmpty()) { + if (ratingToInput.text.toString().trim().toInt() >= 0) { + filterBool = true + ratingTo = ratingToInput.text.toString().toInt() + } else { + Toast.makeText( + activity, + "Vrednost rejtinga ne može biti negativna", + Toast.LENGTH_LONG + ).show(); + var torating = + bottomSheetDialogFilter.findViewById<View>(R.id.ratingTotxt) as TextView + torating.setTextColor(Color.RED) + } + }else{ + ratingTo=-1 + } + + if(viewsFromInput.text.toString().isNotEmpty()) { + if (viewsFromInput.text.toString().trim().toInt() >= 0) { + filterBool = true + viewsFrom = viewsFromInput.text.toString().toInt() + } else { + Toast.makeText( + activity, + "Vrednost broja pregleda ne može biti negativna", + Toast.LENGTH_LONG + ).show(); + var fromviews = + bottomSheetDialogFilter.findViewById<View>(R.id.viewsFromtxt) as TextView + fromviews.setTextColor(Color.RED) + } + } + else{ + viewsFrom=-1 + } + if(viewsToInput.text.toString().isNotEmpty()) { + if (viewsToInput.text.toString().trim().toInt() >= 0) { + filterBool = true + viewsTo = viewsToInput.text.toString().trim().toInt() + } else { + Toast.makeText( + activity, + "Vrednost broja pregleda ne može biti negativna", + Toast.LENGTH_LONG + ).show(); + var toviews = + bottomSheetDialogFilter.findViewById<View>(R.id.viewsTotxt) as TextView + toviews.setTextColor(Color.RED) + } + }else{ + viewsTo=-1 + } + searchParams!!.filter=filterBool + searchParams!!.ratingFrom=ratingFrom + searchParams!!.ratingTo=ratingTo + searchParams!!.viewsFrom=viewsFrom + searchParams!!.viewsTo=viewsTo + searchText() + bottomSheetDialogFilter.dismiss() + } + + + } + btnSort.setOnClickListener{ + Log.d("main","fgdsfdssdfd") + bottomSheetDialogSort.show() + var sort = bottomSheetDialogSort.findViewById<View>(R.id.btnSortPosts) as Button + var radioGroup = bottomSheetDialogSort.findViewById<View>(R.id.radioGroup)as RadioGroup + + sort.setOnClickListener { + val selectedRadioButtonId: Int = radioGroup.checkedRadioButtonId + if (selectedRadioButtonId != -1) { + var selectedRadioButton = + bottomSheetDialogSort.findViewById<View>(selectedRadioButtonId) as RadioButton + val string: String = selectedRadioButton.text.toString().trim() + if (string.equals("Najnovije")) { + searchParams!!.sorttype = 3 + } else if (string.equals("Najstarije")) { + searchParams!!.sorttype=4 + } else if (string.equals("Najbolje ocenjeno")) { + searchParams!!.sorttype=2 + } else if (string.equals("Najviše pregleda")) { + searchParams!!.sorttype=1 + } else { + searchParams!!.sorttype=1 + } + } + + } + bottomSheetDialogSort.dismiss() + } + setUpListeners(rootView) swipeRefreshLayout = rootView?.findViewById<View>(R.id.swipeContainer) as SwipeRefreshLayout swipeRefreshLayout?.setOnRefreshListener(this) @@ -190,17 +386,14 @@ class FragmentShowPosts : Fragment(), SwipeRefreshLayout.OnRefreshListener { swipeRefreshLayout?.isRefreshing=true requestToBack(searchParams!!) }) +////////////////////////////////////////////////////////////////// - btnFilter=rootView.findViewById(R.id.btnSortType) - btnSort=rootView.findViewById(R.id.btnSortDirection) - btnFilter.setOnClickListener{ - showBottomSheetFilter() - } - btnSort.setOnClickListener{ - showBottomSheetSort() - } + + + ///////////////////////////////////////////////////////////////////////////// + searchBar=rootView.findViewById(R.id.etFragmentShowPostsSearch) as AutoCompleteTextView searchButton=rootView.findViewById<View>(R.id.mbFragmentHomePageSearch) as MaterialButton setUpSpinner() @@ -240,42 +433,18 @@ class FragmentShowPosts : Fragment(), SwipeRefreshLayout.OnRefreshListener { Log.d("TEST","USAO") if(act.searchId!=null && act.searchId.trim()!="") { - searchBar.setText(act.searchQuery,TextView.BufferType.EDITABLE) - searchParams= SearchParams(act.searchId,1,1) + if(act.searchQuery!="-1") + searchBar.setText(act.searchQuery,TextView.BufferType.EDITABLE) + searchParams= SearchParams(act.searchId,filterBool,1,1,ratingFrom,ratingTo,viewsFrom,viewsTo) requestToBack(searchParams!!) }else if(act.searchQuery!=null && act.searchQuery.trim()!="") { searchBar.setText(act.searchQuery,TextView.BufferType.EDITABLE) - searchParams= SearchParams(act.searchQuery,1,1) + searchParams= SearchParams(act.searchQuery,filterBool,1,1,ratingFrom,ratingTo,viewsFrom,viewsTo) requestToBack(searchParams!!) } } - private fun showBottomSheetFilter() { - var bottomSheetDialog: BottomSheetDialog - bottomSheetDialog = BottomSheetDialog(requireContext()) - bottomSheetDialog.setContentView(R.layout.bottom_sheet_filter) - bottomSheetDialog.show() - - var dateFrom=bottomSheetDialog.findViewById<View>(R.id.dateFromBSF)as EditText - var dateTo=bottomSheetDialog.findViewById<View>(R.id.dateToBSF) as EditText - var location=bottomSheetDialog.findViewById<View>(R.id.locationBSF) as EditText - var filter = bottomSheetDialog.findViewById<View>(R.id.btnBSFFilter) as Button - - - filter.setOnClickListener { - //povezati sa back-om - - - } - } - private fun showBottomSheetSort() { - var bottomSheetDialogSort: BottomSheetDialog - bottomSheetDialogSort = BottomSheetDialog(requireContext()) - bottomSheetDialogSort.setContentView(R.layout.bottom_sheet_sort) - bottomSheetDialogSort.show() - - } }
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentShowPostsByLocation.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentShowPostsByLocation.kt index f9accc8..6823f42 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentShowPostsByLocation.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentShowPostsByLocation.kt @@ -59,9 +59,7 @@ class FragmentShowPostsByLocation : Fragment() { data.enqueue(object : Callback<MutableList<PostPreview>> { override fun onResponse(call: Call<MutableList<PostPreview>>, response: Response<MutableList<PostPreview>>) { if (response.body() == null) { - Toast.makeText( - activity, "get all null", Toast.LENGTH_LONG - ).show(); + return } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentSinglePostComments.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentSinglePostComments.kt index 45fbcba..1032ee3 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentSinglePostComments.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentSinglePostComments.kt @@ -3,7 +3,6 @@ package com.example.brzodolokacije.Fragments import android.content.Context import android.os.Bundle import android.util.Log -import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -12,19 +11,17 @@ import android.widget.EditText import android.widget.ImageView import android.widget.TextView import android.widget.Toast +import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.example.brzodolokacije.Adapters.CommentsAdapter -import com.example.brzodolokacije.Adapters.PostImageAdapter import com.example.brzodolokacije.Models.CommentReceive import com.example.brzodolokacije.Models.CommentSend import com.example.brzodolokacije.Models.PostPreview import com.example.brzodolokacije.R import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper -import com.google.android.material.internal.ViewUtils.hideKeyboard import com.google.gson.Gson -import org.w3c.dom.Text import retrofit2.Call import retrofit2.Response @@ -131,15 +128,17 @@ class FragmentSinglePostComments : Fragment() { }) } else{ + newComment.replies= mutableListOf() (adapterComments as CommentsAdapter).items.add(0,newComment) recyclerViewComments?.adapter=adapterComments addedComment() + } } fun buildRecyclerViewComments(){ recyclerViewComments=commentsContainer - adapterComments=CommentsAdapter(comments as MutableList<CommentSend>,requireActivity()) + adapterComments=CommentsAdapter(comments as MutableList<CommentSend>,requireActivity(),this@FragmentSinglePostComments) layoutManagerComments= LinearLayoutManager(requireActivity(),LinearLayoutManager.VERTICAL,false) recyclerViewComments!!.setHasFixedSize(false) recyclerViewComments!!.layoutManager=layoutManagerComments diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentSinglePostDescription.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentSinglePostDescription.kt index 877fbc4..6e37052 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentSinglePostDescription.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentSinglePostDescription.kt @@ -1,21 +1,24 @@ package com.example.brzodolokacije.Fragments +import android.content.Intent import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ImageButton +import android.widget.Button import android.widget.ImageView import android.widget.TextView -import android.widget.Toast +import androidx.core.view.isGone +import androidx.core.view.isVisible import androidx.fragment.app.Fragment +import com.example.brzodolokacije.Activities.ActivitySinglePost +import com.example.brzodolokacije.Activities.NavigationActivity import com.example.brzodolokacije.Models.* import com.example.brzodolokacije.R import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper import com.google.gson.Gson -import org.w3c.dom.Text import retrofit2.Call import retrofit2.Response @@ -30,6 +33,13 @@ class FragmentSinglePostDescription : Fragment() { private lateinit var star5:ImageView private var starNumber:Number=0 private lateinit var post:PostPreview + private lateinit var parentact:ActivitySinglePost + private lateinit var ocenitext:TextView + private lateinit var userid:String + private lateinit var del:TextView + private lateinit var delbtn:Button + private lateinit var delbtnY:Button + private lateinit var delbtnN:Button override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -37,7 +47,7 @@ class FragmentSinglePostDescription : Fragment() { ): View? { var view=inflater.inflate(R.layout.fragment_single_post_description, container, false) - + parentact = activity as ActivitySinglePost //uzmi post prosledjen iz single post @@ -45,10 +55,18 @@ class FragmentSinglePostDescription : Fragment() { var jsonPostObject = args!!.getString("post") post= Gson().fromJson(jsonPostObject, PostPreview::class.java) + //setuj opis descriptionContainer=view.findViewById(R.id.tvDescription) descriptionContainer.text=post.description.toString() + + del=view.findViewById(R.id.tvObrisi) + delbtn=view.findViewById(R.id.btnObrisi) + delbtnY=view.findViewById(R.id.btnObrisiY) + delbtnN=view.findViewById(R.id.btnObrisiN) + userid="" + ocenitext=view.findViewById(R.id.title) //setuj zvezdice star1=view.findViewById(R.id.rateStar1) star2=view.findViewById(R.id.rateStar2) @@ -57,15 +75,17 @@ class FragmentSinglePostDescription : Fragment() { star5=view.findViewById(R.id.rateStar5) setRatingListeners() + val alreadyrated= RatingReceive(starNumber.toInt(),post._id) requestAddRating(alreadyrated) - + toggleStarRatings() return view } fun setRatingListeners() { val emptyStar = R.drawable.ic_round_star_outline_24 val fullStar = R.drawable.ic_baseline_star_rate_24 + val offStar = R.drawable.ic_baseline_star_24 star1.setOnClickListener { //Toast.makeText(this,"kliknuta prva zvezdica",Toast.LENGTH_SHORT).show() @@ -77,7 +97,7 @@ class FragmentSinglePostDescription : Fragment() { starNumber=1 rate(starNumber) } - star1.setOnClickListener { + star2.setOnClickListener { //Toast.makeText(this,"kliknuta druga zvezdica",Toast.LENGTH_SHORT).show() star1.setImageResource(fullStar) star2.setImageResource(fullStar) @@ -87,7 +107,7 @@ class FragmentSinglePostDescription : Fragment() { starNumber=2 rate(starNumber) } - star1.setOnClickListener { + star3.setOnClickListener { //Toast.makeText(this,"kliknuta treca zvezdica",Toast.LENGTH_SHORT).show() star1.setImageResource(fullStar) star2.setImageResource(fullStar) @@ -97,8 +117,8 @@ class FragmentSinglePostDescription : Fragment() { starNumber=3 rate(starNumber) } - star1.setOnClickListener { - Toast.makeText(requireActivity(),"kliknuta cetvrta zvezdica",Toast.LENGTH_SHORT).show() + star4.setOnClickListener { + //Toast.makeText(requireActivity(),"kliknuta cetvrta zvezdica",Toast.LENGTH_SHORT).show() star1.setImageResource(fullStar) star2.setImageResource(fullStar) star3.setImageResource(fullStar) @@ -107,7 +127,7 @@ class FragmentSinglePostDescription : Fragment() { starNumber=4 rate(starNumber) } - star1.setOnClickListener { + star5.setOnClickListener { //Toast.makeText(this,"kliknuta peta zvezdica",Toast.LENGTH_SHORT).show() star1.setImageResource(fullStar) star2.setImageResource(fullStar) @@ -140,19 +160,54 @@ class FragmentSinglePostDescription : Fragment() { "--------------", data.ratings.toString() + " " + data.ratingscount.toString() ) - when (data.myrating) { - 1 -> star1.performClick() - 2 -> star1.performClick() - 3 -> star3.performClick() - 4 -> star4.performClick() - 5 -> star5.performClick() - else -> { - val emptyStar = R.drawable.empty_star - star1.setImageResource(emptyStar) - star2.setImageResource(emptyStar) - star3.setImageResource(emptyStar) - star4.setImageResource(emptyStar) - star5.setImageResource(emptyStar) + parentact.updateratings(data.ratingscount,data.ratings) + if(rating.rating==0) { + val emptyStar = R.drawable.empty_star + val fullStar = R.drawable.ic_baseline_star_rate_24 + + when (data.myrating) { + 1 -> { + star1.setImageResource(fullStar) + star2.setImageResource(emptyStar) + star3.setImageResource(emptyStar) + star4.setImageResource(emptyStar) + star5.setImageResource(emptyStar) + } + 2 -> { + star1.setImageResource(fullStar) + star2.setImageResource(fullStar) + star3.setImageResource(emptyStar) + star4.setImageResource(emptyStar) + star5.setImageResource(emptyStar) + } + 3 -> { + star1.setImageResource(fullStar) + star2.setImageResource(fullStar) + star3.setImageResource(fullStar) + star4.setImageResource(emptyStar) + star5.setImageResource(emptyStar) + } + 4 -> { + star1.setImageResource(fullStar) + star2.setImageResource(fullStar) + star3.setImageResource(fullStar) + star4.setImageResource(fullStar) + star5.setImageResource(emptyStar) + } + 5 -> { + star1.setImageResource(fullStar) + star2.setImageResource(fullStar) + star3.setImageResource(fullStar) + star4.setImageResource(fullStar) + star5.setImageResource(fullStar) + } + else -> { + star1.setImageResource(emptyStar) + star2.setImageResource(emptyStar) + star3.setImageResource(emptyStar) + star4.setImageResource(emptyStar) + star5.setImageResource(emptyStar) + } } } /*Toast.makeText( @@ -171,4 +226,97 @@ class FragmentSinglePostDescription : Fragment() { } }) } + fun toggleStarRatings(){ + var token= SharedPreferencesHelper.getValue("jwt", requireActivity()).toString() + val api= RetrofitHelper.getInstance() + val request= api.getUserId("Bearer " + token) + request.enqueue(object : retrofit2.Callback<String> { + override fun onResponse(call: Call<String>, + response: Response<String> + ) { + if (response.body() == null) { + return + } + userid=response.body().toString() + Log.d("UID TEST",userid) + if(post.ownerId==userid){ + //val offStar = R.drawable.ic_baseline_star_24 + ocenitext.text="Vlasnik posta ne moze ocenjivati sebe" + /*star1.setImageResource(offStar) + star2.setImageResource(offStar) + star3.setImageResource(offStar) + star4.setImageResource(offStar) + star5.setImageResource(offStar)*/ + star1.isEnabled=false + star2.isEnabled=false + star3.isEnabled=false + star4.isEnabled=false + star5.isEnabled=false + + ocenitext.isVisible=false + ocenitext.isGone=true + star1.isVisible=false + star1.isGone=true + star2.isVisible=false + star2.isGone=true + star3.isVisible=false + star3.isGone=true + star4.isVisible=false + star4.isGone=true + star5.isVisible=false + star5.isGone=true + + delbtn.isGone=false + delbtn.setOnClickListener{ + del.isGone=false + delbtnY.isGone=false + delbtnN.isGone=false + delbtn.isGone=true + delbtnY.setOnClickListener { + deletePostreq() + } + delbtnN.setOnClickListener { + del.isGone=true + delbtnY.isGone=true + delbtnN.isGone=true + delbtn.isGone=false + } + } + + + } + } + + override fun onFailure(call: Call<String>, t: Throwable) { + + } + }) + + + } + + fun deletePostreq(){ + var token= SharedPreferencesHelper.getValue("jwt", requireActivity()).toString() + val api= RetrofitHelper.getInstance() + val request= api.DeletePost("Bearer " + token,post._id) + request.enqueue(object : retrofit2.Callback<String> { + override fun onResponse( + call: Call<String>, + response: Response<String> + ) { + if(response.isSuccessful){ + SharedPreferencesHelper.addValue("jwt",token,activity!!) + val intent= Intent(activity!!, NavigationActivity::class.java) + startActivity(intent) + activity!!.finish() + } + + } + + override fun onFailure(call: Call<String>, t: Throwable) { + + } + }) + } + }
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserFollowers.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserFollowers.kt index 376517c..f2c817a 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserFollowers.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserFollowers.kt @@ -1,30 +1,37 @@ package com.example.brzodolokacije.Fragments import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher import android.util.Log -import androidx.fragment.app.Fragment +import android.view.KeyEvent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.AutoCompleteTextView +import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.example.brzodolokacije.Adapters.FollowersAdapter -import com.example.brzodolokacije.Adapters.ShowPostsHomePageAdapter -import com.example.brzodolokacije.Models.PostPreview import com.example.brzodolokacije.Models.UserReceive import com.example.brzodolokacije.R import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper +import com.google.android.material.button.MaterialButton import retrofit2.Call import retrofit2.Callback import retrofit2.Response + class FragmentUserFollowers : Fragment() { private lateinit var followers:MutableList<UserReceive> + private lateinit var searchedFollowers:MutableList<UserReceive> private lateinit var rvFollowers:RecyclerView private lateinit var userId:String private lateinit var showMy:String + private lateinit var searchBar:AutoCompleteTextView + private lateinit var searchButton:MaterialButton override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -37,6 +44,8 @@ class FragmentUserFollowers : Fragment() { userId = bundle!!.getString("userId").toString() showMy = bundle!!.getString("showMy").toString().trim() rvFollowers=view.findViewById(R.id.rvFragmentUserFollowers) + searchBar=view.findViewById(R.id.FragmentFollowersSearchBar) + searchButton=view.findViewById(R.id.FragmentFollowersSearchBButton) if(showMy=="yes"){ getFollowersWithoutId() @@ -44,9 +53,63 @@ class FragmentUserFollowers : Fragment() { else if(showMy=="no") { getFollowers() } + searchButton.setOnClickListener { + searchText() + } + searchBar.setOnKeyListener(View.OnKeyListener { v1, keyCode, event -> // If the event is a key-down event on the "enter" button + if (event.action === KeyEvent.ACTION_DOWN && + keyCode == KeyEvent.KEYCODE_ENTER + ) { + // Perform action on key press + searchText() + return@OnKeyListener true + } + false + }) + + searchBar.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + searchText() + if(count==0) + if(showMy=="yes"){ + getFollowersWithoutId() + } + else if(showMy=="no") { + getFollowers() + } + } + + override fun afterTextChanged(s: Editable) { + } + }) return view } + fun searchText(){ + if(searchBar.text==null || searchBar.text.isNullOrEmpty() || searchBar.text.toString().trim()=="") + return + if(!this::followers.isInitialized) + return + var text=searchBar.text.toString().trim() + searchedFollowers= mutableListOf() + for(user in followers){ + if(user.username.contains(text)) + searchedFollowers.add(user) + } + rvFollowers.apply { + layoutManager= LinearLayoutManager(activity, LinearLayoutManager.VERTICAL,false) + adapter= FollowersAdapter(searchedFollowers,requireActivity()) + + } + + + + + } + fun getFollowers(){ val api = RetrofitHelper.getInstance() @@ -64,7 +127,7 @@ class FragmentUserFollowers : Fragment() { } followers = response.body()!!.toMutableList<UserReceive>() rvFollowers.apply { - layoutManager= LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL,false) + layoutManager= LinearLayoutManager(activity, LinearLayoutManager.VERTICAL,false) adapter= FollowersAdapter(followers,requireActivity()) } @@ -89,7 +152,7 @@ class FragmentUserFollowers : Fragment() { Log.d("MyFollowers","Successsssssssssssssssssssssssssssss") followers = response.body()!!.toMutableList<UserReceive>() rvFollowers.apply { - layoutManager= LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL,false) + layoutManager= LinearLayoutManager(activity, LinearLayoutManager.VERTICAL,false) adapter= FollowersAdapter(followers,requireActivity()) } } @@ -98,4 +161,13 @@ class FragmentUserFollowers : Fragment() { } }) } + override fun onResume() { + super.onResume() + if(showMy=="yes"){ + getFollowersWithoutId() + } + else if(showMy=="no") { + getFollowers() + } + } }
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserFollowing.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserFollowing.kt index 9a78b6e..0508c13 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserFollowing.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserFollowing.kt @@ -1,11 +1,15 @@ package com.example.brzodolokacije.Fragments import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher import android.util.Log +import android.view.KeyEvent import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.AutoCompleteTextView import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.example.brzodolokacije.Adapters.FollowersAdapter @@ -13,6 +17,7 @@ import com.example.brzodolokacije.Models.UserReceive import com.example.brzodolokacije.R import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper +import com.google.android.material.button.MaterialButton import retrofit2.Call import retrofit2.Callback import retrofit2.Response @@ -21,9 +26,12 @@ import retrofit2.Response class FragmentUserFollowing : Fragment() { private lateinit var following:MutableList<UserReceive> + private lateinit var searchedFollowing:MutableList<UserReceive> private lateinit var rvFollowing: RecyclerView private lateinit var userId:String private lateinit var showMy:String + private lateinit var searchBar: AutoCompleteTextView + private lateinit var searchButton: MaterialButton override fun onCreateView( @@ -36,15 +44,68 @@ class FragmentUserFollowing : Fragment() { userId = bundle!!.getString("userId").toString() showMy = bundle!!.getString("showMy").toString().trim() rvFollowing=view.findViewById(R.id.rvFragmentUserFollowing) - + searchBar=view.findViewById(R.id.FragmentFollowingSearchBar) + searchButton=view.findViewById(R.id.FragmentFollowingSearchBButton) if(showMy=="yes"){ getFollowingWithoutId() } else if(showMy=="no") { getFollowing() } + searchButton.setOnClickListener { + searchText() + } + searchBar.setOnKeyListener(View.OnKeyListener { v1, keyCode, event -> // If the event is a key-down event on the "enter" button + if (event.action === KeyEvent.ACTION_DOWN && + keyCode == KeyEvent.KEYCODE_ENTER + ) { + // Perform action on key press + searchText() + return@OnKeyListener true + } + false + }) + searchBar.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + searchText() + if(count==0) + if(showMy=="yes"){ + getFollowingWithoutId() + } + else if(showMy=="no") { + getFollowing() + } + } + + override fun afterTextChanged(s: Editable) { + } + }) return view } + fun searchText(){ + if(searchBar.text==null || searchBar.text.isNullOrEmpty() || searchBar.text.toString().trim()=="") + return + var text=searchBar.text.toString().trim() + if(!this::following.isInitialized) + return + searchedFollowing= mutableListOf() + for(user in following){ + if(user.username.contains(text)) + searchedFollowing.add(user) + } + rvFollowing.apply { + layoutManager= LinearLayoutManager(activity, LinearLayoutManager.VERTICAL,false) + adapter= FollowersAdapter(searchedFollowing,requireActivity()) + + } + + + + + } fun getFollowing(){ val api = RetrofitHelper.getInstance() @@ -58,7 +119,7 @@ class FragmentUserFollowing : Fragment() { Log.d("Following","Successsssssssssssssssssssssssssssss") following = response.body()!!.toMutableList<UserReceive>() rvFollowing.apply { - layoutManager= LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL,false) + layoutManager= LinearLayoutManager(activity, LinearLayoutManager.VERTICAL,false) adapter= FollowersAdapter(following,requireActivity()) } } @@ -80,7 +141,7 @@ class FragmentUserFollowing : Fragment() { Log.d("MyFollowings","Successsssssssssssssssssssssssssssss") following = response.body()!!.toMutableList<UserReceive>() rvFollowing.apply { - layoutManager= LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL,false) + layoutManager= LinearLayoutManager(activity, LinearLayoutManager.VERTICAL,false) adapter= FollowersAdapter(following,requireActivity()) } } @@ -90,4 +151,14 @@ class FragmentUserFollowing : Fragment() { }) } + override fun onResume() { + super.onResume() + if(showMy=="yes"){ + getFollowingWithoutId() + } + else if(showMy=="no") { + getFollowing() + } + } + }
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserPosts.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserPosts.kt index d6971c4..e132ec4 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserPosts.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserPosts.kt @@ -46,6 +46,7 @@ class FragmentUserPosts : Fragment() { private lateinit var posts : MutableList<PostPreview> private lateinit var rvPosts: RecyclerView private lateinit var addNewPost:TextView + var favourite=0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -64,6 +65,8 @@ class FragmentUserPosts : Fragment() { if(jwtString!=null) { var jwt: JWT = JWT(jwtString!!) var userId=jwt.getClaim("id").asString() + if(favourite==1) + bundle.putString("favourite","true") bundle.putString("id", userId) val userMapFragment = UserPostsMapFragment() userMapFragment.setArguments(bundle) @@ -77,9 +80,35 @@ class FragmentUserPosts : Fragment() { } rvPosts=view.findViewById(R.id.rvFragmentUserPostsPosts) as RecyclerView - getPosts() + if(this.arguments==null) + getPosts() + else + getFavouritePosts() return view } + fun getFavouritePosts(){ + val api = RetrofitHelper.getInstance() + val token= SharedPreferencesHelper.getValue("jwt", requireActivity()) + val data=api.getMyFavouritePosts("Bearer "+token) + + data.enqueue(object : Callback<MutableList<PostPreview>> { + override fun onResponse( + call: Call<MutableList<PostPreview>>, + response: Response<MutableList<PostPreview>> + ) { + if (response.body() == null) { + return + } + posts = response.body()!!.toMutableList<PostPreview>() + loadPosts() + favourite=1 + } + override fun onFailure(call: Call<MutableList<PostPreview>>, t: Throwable) { + + } + }) + + } fun getPosts(){ val api = RetrofitHelper.getInstance() diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Interfaces/IBackendApi.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Interfaces/IBackendApi.kt index 19b1bb5..c7d238c 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Interfaces/IBackendApi.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Interfaces/IBackendApi.kt @@ -1,10 +1,7 @@ package com.example.brzodolokacije.Interfaces import com.example.brzodolokacije.Models.* -import com.example.brzodolokacije.Models.Auth.JustMail -import com.example.brzodolokacije.Models.Auth.Login -import com.example.brzodolokacije.Models.Auth.Register -import com.example.brzodolokacije.Models.Auth.ResetPass +import com.example.brzodolokacije.Models.Auth.* import okhttp3.MultipartBody import okhttp3.RequestBody import okhttp3.ResponseBody @@ -57,13 +54,20 @@ interface IBackendApi { @GET("/api/user/posts") fun getMyPosts(@Header("Authorization") authHeader:String):Call<MutableList<PostPreview>> + @GET("/api/post/userFavouritePosts") + fun getMyFavouritePosts(@Header("Authorization") authHeader:String):Call<MutableList<PostPreview>> @GET("/api/post/locations/{id}/posts") suspend fun getPagedPosts(@Header("Authorization") authHeader: String, @Path("id") locationId:String, + @Query("filter") filter:Boolean, @Query("page") page:Int, @Query("sorttype") sorttype:Int, - @Query("filterdate") filterdate:Int + @Query("filterdate") filterdate:Int, + @Query("ratingFrom") ratingFrom:Int, + @Query("ratingTo") ratingTo:Int, + @Query("viewsFrom") viewsFrom:Int, + @Query("viewsTo") viewsTo:Int ):PagedPosts @POST("/api/message/add") fun sendMessage(@Header("Authorization") authHeader:String,@Body message:MessageSend):Call<Message> @@ -121,4 +125,13 @@ interface IBackendApi { @GET("/api/user/{newName}/changeMyName") fun changeMyName(@Header("Authorization") authHeader:String,@Path("newName") newName:String):Call<Boolean> + + @POST("/api/user/changePass") + fun changePass(@Header("Authorization") authHeader:String,@Body changePass:ChangePass):Call<Int> + @GET("/api/user/{username}/profile/stats") + fun getUserStatsFromUsername(@Header("Authorization") authHeader:String,@Path("username") username:String):Call<Statistics> + @GET("/api/auth/jwttoid") + fun getUserId(@Header("Authorization") authHeader:String):Call<String> + @DELETE("api/Post/posts/delete/{id}") + fun DeletePost(@Header("Authorization") authHeader:String,@Path("id") id:String):Call<String> }
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/MainActivity.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/MainActivity.kt index acce7b3..b996b12 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/MainActivity.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/MainActivity.kt @@ -9,7 +9,6 @@ import com.example.brzodolokacije.Activities.ActivityLoginRegister import com.example.brzodolokacije.Activities.NavigationActivity import com.example.brzodolokacije.Services.RetrofitHelper import com.example.brzodolokacije.Services.SharedPreferencesHelper -import com.example.brzodolokacije.chat.Notifications import retrofit2.Call import retrofit2.Response @@ -23,7 +22,6 @@ class MainActivity : AppCompatActivity() { val intent:Intent if(checkLoggedIn()) { - Notifications.makeChannel(this) intent = Intent(this, NavigationActivity::class.java) } else @@ -57,13 +55,14 @@ class MainActivity : AppCompatActivity() { override fun onResponse(call: Call<String?>, response: Response<String?>) { if(response.isSuccessful()){ val newToken=response.body().toString() - Toast.makeText( - applicationContext, token, Toast.LENGTH_LONG - ).show(); + SharedPreferencesHelper.addValue("jwt",newToken,this@MainActivity) }else{ if(response.errorBody()!=null) Toast.makeText(applicationContext, response.errorBody()!!.string(), Toast.LENGTH_LONG).show(); + intent= Intent(this@MainActivity, ActivityLoginRegister::class.java) + SharedPreferencesHelper.removeValue("jwt",this@MainActivity) + startActivity(intent) } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/Auth/ChangePass.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/Auth/ChangePass.kt new file mode 100644 index 0000000..46957df --- /dev/null +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/Auth/ChangePass.kt @@ -0,0 +1,6 @@ +package com.example.brzodolokacije.Models.Auth + +data class ChangePass( + var currentPass:String, + var newPass:String +) diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/Post.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/Post.kt index 8f07bca..3df1621 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/Post.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/Post.kt @@ -3,6 +3,7 @@ package com.example.brzodolokacije.Models import android.os.Parcelable import kotlinx.android.parcel.Parcelize import okhttp3.MultipartBody +import retrofit2.http.Query import java.time.LocalDateTime import java.util.* @@ -91,6 +92,29 @@ data class PagedPosts( data class SearchParams( var locationId: String, + var filter:Boolean, var sorttype:Int, - var filterdate:Int -)
\ No newline at end of file + var filterdate:Int, + var ratingFrom:Int, + var ratingTo:Int, + var viewsFrom:Int, + var viewsTo:Int, +) +/* +data class FilterSort( + //var posts: MutableList<PostPreview>, + var sort:Boolean, + var filter:Boolean, + + //var filterDateFrom:Date, + //var filterDateTo:Date, + var filterRatingFrom:Int, + var filterRatingTo:Int, + var filterViewsFrom:Int, + var filterViewsTo:Int, + + var sortLatest:Boolean, + var sortOldest:Boolean, + var sortBest:Boolean, + var sortMostViews:Boolean + )*/
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/Statistics.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/Statistics.kt new file mode 100644 index 0000000..4466e05 --- /dev/null +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/Statistics.kt @@ -0,0 +1,18 @@ +package com.example.brzodolokacije.Models + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize +data class Statistics( + var totalViews:Int, + var numberOfPosts:Int, + var numberOfRatingsOnPosts:Int, + var averagePostRatingOnPosts:Double, + var monthlyViews:List<MonthlyViews>, + var numberOfFavouritePosts:Int +) +@Parcelize +data class MonthlyViews( + var month:Int, + var views:Int +):Parcelable + diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/User.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/User.kt index 6e282a9..072be55 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/User.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/User.kt @@ -34,5 +34,6 @@ data class UserReceive( var following:List<String>, var followingCount:Int, var postIds:List<Int>, - var postNumber:Int + var postNumber:Int, + var favourites:List<String>? )
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Services/LinePagerIndicatorDecoration.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Services/LinePagerIndicatorDecoration.kt new file mode 100644 index 0000000..31f03ab --- /dev/null +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Services/LinePagerIndicatorDecoration.kt @@ -0,0 +1,111 @@ +import android.content.res.Resources +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Rect +import android.view.View +import androidx.annotation.ColorInt +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.RecyclerView.ItemDecoration + + +class LinePagerIndicatorDecoration( + radius: Int, + padding: Int, + indicatorHeight: Int, + @ColorInt colorInactive: Int, + @ColorInt colorActive: Int +) : + ItemDecoration() { + private val indicatorHeight: Int + private val indicatorItemPadding: Int + private val radius: Int + private val inactivePaint: Paint = Paint() + private val activePaint: Paint = Paint() + + init { + val strokeWidth: Float = Resources.getSystem().getDisplayMetrics().density * 1 + this.radius = radius + inactivePaint.setStrokeCap(Paint.Cap.ROUND) + inactivePaint.setStrokeWidth(strokeWidth) + inactivePaint.setStyle(Paint.Style.STROKE) + inactivePaint.setAntiAlias(true) + inactivePaint.setColor(colorInactive) + activePaint.setStrokeCap(Paint.Cap.ROUND) + activePaint.setStrokeWidth(strokeWidth) + activePaint.setStyle(Paint.Style.FILL) + activePaint.setAntiAlias(true) + activePaint.setColor(colorActive) + indicatorItemPadding = padding + this.indicatorHeight = indicatorHeight + } + + override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { + super.onDrawOver(c, parent, state) + val adapter = parent.adapter ?: return + val itemCount = adapter.itemCount + + // center horizontally, calculate width and subtract half from center + val totalLength = (radius * 2 * itemCount).toFloat() + val paddingBetweenItems = (Math.max(0, itemCount - 1) * indicatorItemPadding).toFloat() + val indicatorTotalWidth = totalLength + paddingBetweenItems + val indicatorStartX = (parent.width - indicatorTotalWidth) / 2f + + // center vertically in the allotted space + val indicatorPosY = parent.height - indicatorHeight / 2f + drawInactiveDots(c, indicatorStartX, indicatorPosY, itemCount) + val activePosition: Int + activePosition = if (parent.layoutManager is GridLayoutManager) { + (parent.layoutManager as GridLayoutManager?)!!.findFirstVisibleItemPosition() + } else if (parent.layoutManager is LinearLayoutManager) { + (parent.layoutManager as LinearLayoutManager?)!!.findFirstVisibleItemPosition() + } else { + // not supported layout manager + return + } + if (activePosition == RecyclerView.NO_POSITION) { + return + } + + // find offset of active page if the user is scrolling + val activeChild = parent.layoutManager!!.findViewByPosition(activePosition) + ?: return + drawActiveDot(c, indicatorStartX, indicatorPosY, activePosition) + } + + private fun drawInactiveDots( + c: Canvas, + indicatorStartX: Float, + indicatorPosY: Float, + itemCount: Int + ) { + // width of item indicator including padding + val itemWidth = (radius * 2 + indicatorItemPadding).toFloat() + var start = indicatorStartX + radius + for (i in 0 until itemCount) { + c.drawCircle(start, indicatorPosY, radius.toFloat(), inactivePaint) + start += itemWidth + } + } + + private fun drawActiveDot( + c: Canvas, indicatorStartX: Float, indicatorPosY: Float, + highlightPosition: Int + ) { + // width of item indicator including padding + val itemWidth = (radius * 2 + indicatorItemPadding).toFloat() + val highlightStart = indicatorStartX + radius + itemWidth * highlightPosition + c.drawCircle(highlightStart, indicatorPosY, radius.toFloat(), activePaint) + } + + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + super.getItemOffsets(outRect, view, parent, state) + outRect.bottom = indicatorHeight + } +}
\ No newline at end of file diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/UserPostsMapFragment.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/UserPostsMapFragment.kt index 882a1ae..665a48e 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/UserPostsMapFragment.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/UserPostsMapFragment.kt @@ -10,6 +10,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView +import androidx.core.content.ContextCompat import com.example.brzodolokacije.Activities.ActivitySinglePost import com.example.brzodolokacije.Fragments.FragmentProfile import com.example.brzodolokacije.Models.PostPreview @@ -40,13 +41,16 @@ class UserPostsMapFragment : Fragment() { map=view.findViewById(R.id.FragmentUserPostsMapMapView) as MapView backButton=view.findViewById(R.id.btnFragmentUserPostsBack) as ImageView map!!.setTileSource(TileSourceFactory.MAPNIK); + if(this.requireArguments().getString("other")!=null) + backButton!!.visibility=View.INVISIBLE + id=this.requireArguments().getString("id");//https://stackoverflow.com/questions/17436298/how-to-pass-a-variable-from-activity-to-fragment-and-pass-it-back setUpMap() backButton!!.setOnClickListener{ //SUBJECT TO CHANGE val fragmentProfile = FragmentProfile() fragmentManager?.beginTransaction() - ?.replace(com.example.brzodolokacije.R.id.flNavigationFragment,fragmentProfile) + ?.replace(R.id.flNavigationFragment,fragmentProfile) ?.commit() //How to call fragment // val bundle = Bundle() @@ -70,7 +74,12 @@ class UserPostsMapFragment : Fragment() { var jwtString= SharedPreferencesHelper.getValue("jwt",requireActivity()) if(id==null) return - var data=api.getUsersPosts("Bearer "+jwtString,id!!) + var data:Call<MutableList<PostPreview>> + if(this.requireArguments().getString("favourite")==null) + data=api.getUsersPosts("Bearer "+jwtString,id!!) + else + data=api.getMyFavouritePosts("Bearer "+jwtString) + data.enqueue(object : retrofit2.Callback<MutableList<PostPreview>> { override fun onResponse(call: Call<MutableList<PostPreview>>, response: Response<MutableList<PostPreview>>) { @@ -83,6 +92,7 @@ class UserPostsMapFragment : Fragment() { val startMarker = Marker(map) startMarker.setPosition(GeoPoint(post.location.latitude,post.location.longitude)) startMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM) + startMarker.icon= ContextCompat.getDrawable(requireContext(), R.drawable.ic_baseline_location_on_24) if(flag){ flag=false map!!.controller.animateTo(GeoPoint(post.location.latitude,post.location.longitude)) diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/chat/DBHelper.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/chat/DBHelper.kt index 041eebb..ee7e924 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/chat/DBHelper.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/chat/DBHelper.kt @@ -175,7 +175,6 @@ class DBHelper : ) Log.d("main",cal.time.toString()) - readContact(userId) return msg } return null @@ -216,20 +215,23 @@ class DBHelper : return null } - fun getContacts(): MutableList<ChatPreview>? { + suspend fun getContacts(): MutableList<ChatPreview>? { + var mapChats:Map<Long,ChatPreview> + mapChats= mutableMapOf() onCreate(db) var sql="SELECT * FROM "+ CONTACTS_TABLE_NAME var cursor=db?.rawQuery(sql,null) if(cursor?.count!! >0){ - var contactList:MutableList<ChatPreview> =mutableListOf() var userIdIndex=cursor.getColumnIndexOrThrow("userId") var readIndex=cursor.getColumnIndexOrThrow("read") var usernameIndex=cursor.getColumnIndexOrThrow("username") while(cursor.moveToNext()){ - contactList.add(ChatPreview(cursor.getString(userIdIndex),cursor.getInt(readIndex)==1,cursor.getString(usernameIndex))) + var chat=ChatPreview(cursor.getString(userIdIndex),cursor.getInt(readIndex)==1,cursor.getString(usernameIndex)) + var lastMessage=getLastMessage(chat.userId)?.usableTimeStamp!!.timeInMillis + mapChats[lastMessage]=chat } - Log.d("main",contactList.size.toString()) - return contactList + var sorted=mapChats.toSortedMap(kotlin.Comparator { o1, o2 -> (o2-o1).toInt() }) + return ArrayList<ChatPreview>(sorted.values).toMutableList() } return null } @@ -242,10 +244,12 @@ class DBHelper : } fun readContact(userId: String){ + onCreate(db) var sql="UPDATE "+ CONTACTS_TABLE_NAME+" SET read=1 WHERE userId='"+userId+"'" db?.execSQL(sql) } fun unreadContact(userId: String){ + onCreate(db) var sql="UPDATE "+ CONTACTS_TABLE_NAME+" SET read=0 WHERE userId='"+userId+"'" db?.execSQL(sql) } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/chat/SignalRListener.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/chat/SignalRListener.kt index 627d7c0..49d76c9 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/chat/SignalRListener.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/chat/SignalRListener.kt @@ -2,16 +2,20 @@ package com.example.brzodolokacije.chat import android.Manifest import android.app.Activity +import android.app.PendingIntent +import android.content.Intent import android.content.pm.PackageManager import android.graphics.Color import android.util.Log import android.widget.Toast import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat +import androidx.core.app.TaskStackBuilder import androidx.core.content.ContextCompat import com.auth0.android.jwt.JWT import com.exam.DBHelper import com.example.brzodolokacije.Activities.ChatActivity +import com.example.brzodolokacije.Activities.ChatActivityConversation import com.example.brzodolokacije.Models.Message import com.example.brzodolokacije.Models.MessageReceive import com.example.brzodolokacije.Models.UserReceive @@ -82,35 +86,42 @@ class SignalRListener private constructor(val activity: Activity){ if(activity.clickedChat?.userId==message.senderId){ activity.clickedChat?.requestMessages() } - activity.requestNewMessages() + activity.onRefresh() } - when { - ContextCompat.checkSelfPermission(activity, - Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED -> { - //poslati notifikaciju - var api=RetrofitHelper.getInstance() - var token=SharedPreferencesHelper.getValue("jwt",activity) - val request2=api?.getProfileFromId("Bearer "+token, - message.senderId - ) - request2?.enqueue(object : retrofit2.Callback<UserReceive?> { - override fun onResponse(call: Call<UserReceive?>, response: Response<UserReceive?>) { - if(response.isSuccessful()){ - var user=response.body()!! - createNotification(message,user,activity) - } - } - - override fun onFailure(call: Call<UserReceive?>, t: Throwable) { - //TODO("Not yet implemented") + if(ContextCompat.checkSelfPermission(activity, + Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED || SharedPreferencesHelper.getValue("notifications",activity)=="true"){ + //poslati notifikaciju + var api=RetrofitHelper.getInstance() + var token=SharedPreferencesHelper.getValue("jwt",activity) + val request2=api?.getProfileFromId("Bearer "+token, + message.senderId + ) + request2?.enqueue(object : retrofit2.Callback<UserReceive?> { + override fun onResponse(call: Call<UserReceive?>, response: Response<UserReceive?>) { + if(response.isSuccessful()){ + var user=response.body()!! + createNotification(message,user,activity) } - }) } - } + override fun onFailure(call: Call<UserReceive?>, t: Throwable) { + //TODO("Not yet implemented") + } + }) + } } fun createNotification(message: MessageReceive,user: UserReceive,activity: Activity){ + val resultIntent = Intent(activity, ChatActivityConversation::class.java) + resultIntent.putExtra("userId",user._id) + resultIntent.putExtra("username",user.username) + resultIntent.putExtra("pfp",user.pfp?._id) + val resultPendingIntent: PendingIntent? = TaskStackBuilder.create(activity).run { + addNextIntentWithParentStack(resultIntent) + getPendingIntent(0, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + } + val notificationBuilder = NotificationCompat.Builder(activity, Notifications.CHANNEL_ID) .setSmallIcon(R.drawable.ic_round_chat_24) .setAutoCancel(true) @@ -120,6 +131,7 @@ class SignalRListener private constructor(val activity: Activity){ .setContentTitle(user.username) .setContentText(message.messagge) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + .setContentIntent(resultPendingIntent) val notificationManager = NotificationManagerCompat.from(activity) val notification = notificationBuilder.build() notificationManager.notify(NotificationID.iD, notification) diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/paging/SearchPostsPagingSource.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/paging/SearchPostsPagingSource.kt index cee39ce..6a8fec2 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/paging/SearchPostsPagingSource.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/paging/SearchPostsPagingSource.kt @@ -21,8 +21,9 @@ class SearchPostsPagingSource( val page=params.key?:0 val token=SharedPreferencesHelper.getValue("jwt", activity) return try{ - val response=backend.getPagedPosts("Bearer "+token,searchParams.locationId, - page,searchParams.sorttype,searchParams.filterdate + val response=backend.getPagedPosts("Bearer "+token,searchParams.locationId,searchParams.filter, + page,searchParams.sorttype,searchParams.filterdate,searchParams.ratingFrom,searchParams.ratingTo, + searchParams.viewsFrom,searchParams.viewsTo ) Log.d("main","stranicenje: "+page.toString()) LoadResult.Page( |