Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…into dev
  • Loading branch information
ST10195824 committed Nov 2, 2024
2 parents dc5b790 + f6070de commit cbfa454
Show file tree
Hide file tree
Showing 22 changed files with 480 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ dependencies {
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.picasso:picasso:2.71828")
implementation ("com.google.android.material:material:1.10.0")
implementation ("com.google.firebase:firebase-messaging:23.1.1")


// Use Firebase BOM for managing Firebase dependencies
implementation(platform("com.google.firebase:firebase-bom:31.5.0"))
Expand Down Expand Up @@ -105,4 +107,7 @@ dependencies {
androidTestImplementation("androidx.test.ext:junit:1.1.5") // AndroidX JUnit extensions
androidTestImplementation("androidx.test:runner:1.6.2") // AndroidX Test Runner

// For swipeable component
implementation("androidx.viewpager2:viewpager2:1.0.0")

}
18 changes: 17 additions & 1 deletion app/google-services.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"project_number": "859936099389",
"firebase_url": "https://purrsonal-trainer-default-rtdb.europe-west1.firebasedatabase.app",
"project_id": "purrsonal-trainer",
"storage_bucket": "purrsonal-trainer.appspot.com"
"storage_bucket": "purrsonal-trainer.firebasestorage.app"
},
"client": [
{
Expand All @@ -14,6 +14,22 @@
}
},
"oauth_client": [
{
"client_id": "859936099389-5lssh9i169lkn774prusu3oqgnhan4f1.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "za.co.varsitycollege.st10204902.purrsonaltrainer",
"certificate_hash": "8c37bb57cec58920d89eccfd108856895296ca43"
}
},
{
"client_id": "859936099389-npc8q7fpmhtti7m5nseg88i4blkdnikq.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "za.co.varsitycollege.st10204902.purrsonaltrainer",
"certificate_hash": "0893451db7400a8a9b573a0e9ba991cd60996b23"
}
},
{
"client_id": "859936099389-19fcm5qa1m50jqb04hot8jqbjl12oc9m.apps.googleusercontent.com",
"client_type": 3
Expand Down
19 changes: 19 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@

<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />



<application
android:allowBackup="true"
Expand Down Expand Up @@ -87,6 +94,18 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<service
android:name=".services.FirebaseMessagingService"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name=".services.NotificationService"
android:exported="false"
android:foregroundServiceType="location" />
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package za.co.varsitycollege.st10204902.purrsonaltrainer

import android.content.pm.PackageManager
import android.Manifest
import android.os.Build
import androidx.biometric.BiometricManager
import android.os.Bundle
import android.util.Log
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
Expand Down Expand Up @@ -45,6 +49,8 @@ class MainActivity : AppCompatActivity() {
private lateinit var catsApiService: CatsApiService
private lateinit var idToken: String



/**
* Called when the activity is first created.
* @param savedInstanceState If the activity is being re-created from a previous saved state, this is the state.
Expand Down Expand Up @@ -74,6 +80,8 @@ class MainActivity : AppCompatActivity() {
fetchCatFact()
loadNewCatImage()



// Initialize Firebase Auth
auth = FirebaseAuth.getInstance()
setupBiometricPrompt()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package za.co.varsitycollege.st10204902.purrsonaltrainer.adapters

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import za.co.varsitycollege.st10204902.purrsonaltrainer.R

class SwipableComponentAdapter(
private val itemList: List<Int>, // Assuming using drawable resource IDs
private val onItemPressed: (Int) -> Unit // Callback for when an avatar is selected
) : RecyclerView.Adapter<SwipableComponentAdapter.AvatarViewHolder>() {

inner class AvatarViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val avatarImageView: ImageView = itemView.findViewById(R.id.swipable_item_image)

fun bind(avatarResId: Int) {
avatarImageView.setImageResource(avatarResId)
itemView.setOnClickListener {
onItemPressed(avatarResId)
}
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AvatarViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_swipable_component, parent, false)
return AvatarViewHolder(view)
}

override fun onBindViewHolder(holder: AvatarViewHolder, position: Int) {
holder.bind(itemList[position])
}

override fun getItemCount(): Int = itemList.size
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package za.co.varsitycollege.st10204902.purrsonaltrainer.components

import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import androidx.viewpager2.widget.ViewPager2
import za.co.varsitycollege.st10204902.purrsonaltrainer.R
import za.co.varsitycollege.st10204902.purrsonaltrainer.adapters.SwipableComponentAdapter

class SwipeSelectorView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

private val viewPager: ViewPager2
private var adapter: SwipableComponentAdapter? = null

init {
// Inflate the layout
val view = LayoutInflater.from(context)
.inflate(R.layout.component_swipable_selector, this, true)
viewPager = view.findViewById(R.id.viewPager)
}

fun setItems(avatarList: List<Int>, onAvatarSelected: (Int) -> Unit) {
adapter = SwipableComponentAdapter(avatarList, onAvatarSelected)
viewPager.adapter = adapter
}

fun getCurrentItemPosition(): Int {
return viewPager.currentItem
}

fun setCurrentItemPosition(position: Int, smoothScroll: Boolean = true) {
viewPager.setCurrentItem(position, smoothScroll)
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
package za.co.varsitycollege.st10204902.purrsonaltrainer.screens.fragments

import android.Manifest
import android.content.ComponentName
import android.content.ContentValues.TAG
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.AnimationUtils
import android.widget.LinearLayout
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.widget.AppCompatImageButton
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.gms.tasks.OnCompleteListener
import com.google.firebase.messaging.FirebaseMessaging
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand All @@ -25,22 +39,63 @@ import za.co.varsitycollege.st10204902.purrsonaltrainer.backend.UserManager
import za.co.varsitycollege.st10204902.purrsonaltrainer.models.MonthWorkout
import za.co.varsitycollege.st10204902.purrsonaltrainer.screens.workout_activities.StartEmptyWorkoutActivity
import za.co.varsitycollege.st10204902.purrsonaltrainer.screens.workout_activities.StartWorkoutActivity
import za.co.varsitycollege.st10204902.purrsonaltrainer.services.NotificationService
import za.co.varsitycollege.st10204902.purrsonaltrainer.services.navigateTo
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

private const val LOCATION_PERMISSION_REQUEST_CODE = 1001

class HomeFragment : Fragment() {

private lateinit var routinesRecyclerView: RecyclerView
private lateinit var monthsAdapter: MonthsAdapter
private var monthWorkoutList: List<MonthWorkout> = listOf()
private lateinit var topSection: LinearLayout

private var exerciseDuration: Long = 0L
private val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
// Permission is granted; you can now show notifications
Toast.makeText(requireContext(), "Notification permission granted", Toast.LENGTH_SHORT).show()
} else {
// Permission is denied
Toast.makeText(requireContext(), "Notification permission denied", Toast.LENGTH_SHORT).show()
}
}
private val requiredPermissions = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.POST_NOTIFICATIONS, // Optional if you also want to request notification permission
Manifest.permission.FOREGROUND_SERVICE_LOCATION
)

fun checkAndRequestPermissions() {
val permissionsToRequest = requiredPermissions.filter {
ContextCompat.checkSelfPermission(requireContext(), it) != PackageManager.PERMISSION_GRANTED
}

if (permissionsToRequest.isNotEmpty()) {
ActivityCompat.requestPermissions(
requireActivity(),
permissionsToRequest.toTypedArray(),
LOCATION_PERMISSION_REQUEST_CODE
)
} else {
// Permissions are already granted, proceed with your functionality
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Request notification permission on Android 13+
checkAndRequestPermissions()
}



override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
Expand All @@ -49,9 +104,18 @@ class HomeFragment : Fragment() {
return inflater.inflate(R.layout.fragment_home, container, false)
}



override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
if (!task.isSuccessful) {
Log.w(TAG, "Fetching FCM registration token failed", task.exception)
return@OnCompleteListener
}
})

routinesRecyclerView = view.findViewById(R.id.routinesRecyclerView)
topSection = view.findViewById<LinearLayout>(R.id.topSection)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package za.co.varsitycollege.st10204902.purrsonaltrainer.screens.login_register

import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import za.co.varsitycollege.st10204902.purrsonaltrainer.backend.UserManager
import za.co.varsitycollege.st10204902.purrsonaltrainer.components.SwipeSelectorView
import za.co.varsitycollege.st10204902.purrsonaltrainer.databinding.ActivityProfileSetupBinding
import za.co.varsitycollege.st10204902.purrsonaltrainer.screens.HomeActivity
import za.co.varsitycollege.st10204902.purrsonaltrainer.services.CatAvatarList
import za.co.varsitycollege.st10204902.purrsonaltrainer.services.navigateTo

class ProfileSetupActivity : AppCompatActivity() {
private lateinit var binding: ActivityProfileSetupBinding
private lateinit var catSwipableView: SwipeSelectorView // custom component for choosing cats

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
Expand All @@ -19,8 +24,17 @@ class ProfileSetupActivity : AppCompatActivity() {
// Cat name entered by the user (for whoever needs this)
val catName = binding.profileSetupCatName.text

// CatAvatarSetup
val swipableSelector = binding.profileSetupCatSwipeSelector
swipableSelector.setItems(CatAvatarList) {}

// Navigation from next button
binding.profileSetupNext.setOnClickListener {
// Add the cat information to Firebase
UserManager.updateCatName(catName.toString())
UserManager.updateCatURI(swipableSelector.getCurrentItemPosition().toString())
Toast.makeText(this, swipableSelector.getCurrentItemPosition().toString(), Toast.LENGTH_SHORT).show()

navigateTo(this, HomeActivity::class.java, null)
}
}
Expand Down
Loading

0 comments on commit cbfa454

Please sign in to comment.