diff --git a/.gitignore b/.gitignore
index 8715c49..7e5b563 100755
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,4 @@
.externalNativeBuild
.cxx
/app/google-services.json
-/app/google-services.prod.json
-/app/google-services.dev.json
/keystore.properties
diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index 0325727..0000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-VITTY
\ No newline at end of file
diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml
deleted file mode 100644
index 4a53bee..0000000
--- a/.idea/AndroidProjectSystem.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index b86273d..fb7f4a8 100755
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
deleted file mode 100644
index b268ef3..0000000
--- a/.idea/deploymentTargetSelector.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/detekt.xml b/.idea/detekt.xml
deleted file mode 100644
index ee7289c..0000000
--- a/.idea/detekt.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/deviceManager.xml b/.idea/deviceManager.xml
deleted file mode 100644
index 91f9558..0000000
--- a/.idea/deviceManager.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 804c374..7b46144 100755
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -4,14 +4,14 @@
-
+
+
-
+
-
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 7061a0d..0000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
deleted file mode 100644
index fe63bb6..0000000
--- a/.idea/kotlinc.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/ktlint-plugin.xml b/.idea/ktlint-plugin.xml
deleted file mode 100644
index e8bd90c..0000000
--- a/.idea/ktlint-plugin.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
- DISTRACT_FREE
- DEFAULT
-
-
\ No newline at end of file
diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml
deleted file mode 100644
index f286756..0000000
--- a/.idea/material_theme_project_new.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/migrations.xml b/.idea/migrations.xml
deleted file mode 100644
index f8051a6..0000000
--- a/.idea/migrations.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 07a0a33..6d6971a 100755
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,3 +1,4 @@
+
@@ -66,8 +67,7 @@
-
-
+
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
deleted file mode 100644
index 16660f1..0000000
--- a/.idea/runConfigurations.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 35eb1dd..94a25f7 100755
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/README.md b/README.md
index c4186b6..4f77557 100755
--- a/README.md
+++ b/README.md
@@ -3,46 +3,35 @@
VITTY - VIT Timetable App
- An Android app for your VIT timetable with homescreen widgets, caching, friend & circle features, ghost mode, reminders, and in-app notifications for your classes
+ An Android app for your VIT timetable with homescreen widgets and in-app notifications for your classes
---
-
[](https://dsc.community.dev/vellore-institute-of-technology/)
[](https://discord.gg/498KVdSKWR)
-[](https://github.com/GDGVIT/vitty-app/blob/master/README.md)
-[](https://www.figma.com/file/3ILW1qy1qIjiJ5S78zyIqh/VITTY?node-id=1%3A4)
+[](https://github.com/GDGVIT/vitty-app/blob/master/README.md)
+ [](https://www.figma.com/file/3ILW1qy1qIjiJ5S78zyIqh/VITTY?node-id=1%3A4)
-## Features
-- [x] Easy access to your VIT timetable (cached & offline-ready)
-- [x] Home screen widgets (Today, Next Class)
-- [x] Notifications before classes with Exam/Holiday mode to disable them
-- [x] Navigation directions to class venues
-- [x] Friend system (send requests, view schedules)
-- [x] Ghost Mode – hide your timetable from friends
-- [x] Circles – group participants, view shared schedules
-- [x] Reminders – attach, edit, or delete course reminders
-- [x] Notes – markdown editor with undo/redo and local Room database
-- [x] QR code scan & generate for joining circles
-- [x] Community integration with rich friend profiles and actions
-- [x] Support & Feedback section in Settings
+## Features
+- [x] Easy access to timetable
+- [x] Home screen widgets
+- [x] Notifications for classes
+- [x] Exam/Holiday mode to turn off your class notifications
+- [x] Navigation directions to your classes
## Dependencies
+ - Android SDK
+ - Android Studio
-- Android SDK
-- Android Studio (latest stable)
-- Kotlin, Jetpack Compose
-- Room, LiveData, ViewModel
## Running
-- Clone the repository
-- Open it in Android Studio
-- Sync Gradle and run the app using the default `APP` configuration
+- Import the project in Android Studio
+- Run the project using the automatically added APP configuration
## Contributors
@@ -62,37 +51,9 @@
-
- Rudrank Basant
-
-
-
-
-
-
-
-
-
-
-
-
-
- Jothish Kamal
-
-
-
-
-
-
-
-
-
-
-
-
- Made with ❤️ by GDSC VIT
+ Made with :heart: by GDSC VIT
diff --git a/app/build.gradle b/app/build.gradle
index 20d3f6d..7a5acc9 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,41 +2,33 @@ plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
- id 'androidx.navigation.safeargs.kotlin'
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
- id 'org.jlleitschuh.gradle.ktlint' version '13.0.0'
- id 'org.jetbrains.kotlin.plugin.compose' version '2.2.0'
+ id 'org.jlleitschuh.gradle.ktlint' version '10.0.0'
}
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
-
-if (keystorePropertiesFile.exists()) {
- keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
-} else {
- throw new GradleException("Missing keystore.properties file!")
-}
+keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
- compileSdk 36
-
signingConfigs {
release {
- keyAlias keystoreProperties["keyAlias"]
- keyPassword keystoreProperties["keyPassword"]
- storeFile file(keystoreProperties["storeFile"])
- storePassword keystoreProperties["storePassword"]
+ keyAlias keystoreProperties['keyAlias']
+ keyPassword keystoreProperties['keyPassword']
+ storeFile file(keystoreProperties['storeFile'])
+ storePassword keystoreProperties['storePassword']
}
}
- // buildToolsVersion "30.0.3"
+ compileSdkVersion 33
+ buildToolsVersion "30.0.3"
defaultConfig {
- namespace "com.dscvit.vitty"
- minSdkVersion 26
- targetSdkVersion 36
- versionCode 44
- versionName "3.0.1"
+ applicationId "com.dscvit.vitty"
+ minSdkVersion 24
+ targetSdkVersion 33
+ versionCode 34
+ versionName "2.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
signingConfig signingConfigs.release
}
@@ -47,110 +39,67 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
- kotlin{
- jvmToolchain(21)
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
}
buildFeatures {
- viewBinding true
dataBinding true
- buildConfig true
- compose true
}
}
dependencies {
- // Compose BOM (Bill of Materials)
- implementation platform("androidx.compose:compose-bom:2025.07.00")
-
- // Core Compose dependencies
- implementation "androidx.compose.ui:ui"
- implementation "androidx.compose.material:material"
- implementation "androidx.compose.ui:ui-tooling-preview"
- implementation "androidx.activity:activity-compose"
-
- // For interoperability
- implementation "androidx.compose.ui:ui-viewbinding"
// Android Stuff
- implementation 'androidx.core:core-ktx:1.16.0'
- implementation 'androidx.appcompat:appcompat:1.7.1'
- implementation 'com.google.android.material:material:1.12.0'
- implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
+ implementation 'androidx.core:core-ktx:1.8.0'
+ implementation 'androidx.appcompat:appcompat:1.4.2'
+ implementation 'com.google.android.material:material:1.6.1'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
- implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.9.2'
- implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.2'
- implementation 'androidx.preference:preference-ktx:1.2.1'
- implementation 'androidx.navigation:navigation-fragment-ktx:2.9.2'
- implementation 'androidx.navigation:navigation-ui-ktx:2.9.2'
- implementation 'androidx.navigation:navigation-compose:2.9.2'
- implementation 'androidx.compose.material3:material3-android:1.3.2'
-
- implementation 'androidx.compose.runtime:runtime-livedata:1.8.3'
+ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.0'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.0'
+ implementation 'androidx.preference:preference-ktx:1.2.0'
+ implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
+ implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
testImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.test.ext:junit:1.2.1'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
// Firebase
- implementation platform('com.google.firebase:firebase-bom:33.16.0')
+ implementation platform('com.google.firebase:firebase-bom:27.1.0')
implementation 'com.google.firebase:firebase-analytics-ktx'
// Firebase Auth
implementation 'com.google.firebase:firebase-auth-ktx'
- implementation 'com.google.android.gms:play-services-auth:21.3.0'
+ implementation 'com.google.android.gms:play-services-auth:19.2.0'
- // FireStore
- implementation 'com.google.firebase:firebase-firestore:25.1.4'
+ // Firestore
+ implementation 'com.google.firebase:firebase-firestore:24.2.0'
// FCM
- implementation 'com.google.firebase:firebase-messaging:24.1.2'
+ implementation 'com.google.firebase:firebase-messaging:23.0.6'
// Remote Config
implementation 'com.google.firebase:firebase-config-ktx'
- debugImplementation 'androidx.compose.ui:ui-tooling:1.8.3'
// Crashlytics
releaseImplementation 'com.google.firebase:firebase-crashlytics-ktx'
// Retrofit
- implementation 'com.squareup.retrofit2:retrofit:3.0.0'
- implementation 'com.squareup.okhttp3:logging-interceptor:5.1.0'
- implementation 'com.squareup.retrofit2:converter-gson:3.0.0'
+ implementation 'com.squareup.retrofit2:retrofit:2.5.0'
+ implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0'
+ implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
// Loading Animations
implementation 'com.github.ybq:Android-SpinKit:1.4.0'
// Coil
- implementation "io.coil-kt:coil:2.7.0"
- implementation("io.coil-kt:coil-compose:2.7.0")
- // Timber for logs
- implementation 'com.jakewharton.timber:timber:5.0.1'
+ implementation "io.coil-kt:coil:1.4.0"
- // Room Database
- implementation "androidx.room:room-runtime:2.7.2"
- implementation "androidx.room:room-ktx:2.7.2"
- kapt "androidx.room:room-compiler:2.7.2"
-
- // ViewModel and LiveData
- implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.9.2"
- implementation "androidx.lifecycle:lifecycle-runtime-compose:2.9.2"
-
- implementation 'androidx.dynamicanimation:dynamicanimation-ktx:1.1.0'
-
- implementation project(':markdowntext')
-
- // QR Code generation
- implementation 'com.google.zxing:core:3.5.3'
- implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
-
- // Camera permissions for QR scanning
- implementation 'com.google.accompanist:accompanist-permissions:0.37.3'
-
- // Google Play In-App Updates
- implementation 'com.google.android.play:app-update:2.1.0'
- implementation 'com.google.android.play:app-update-ktx:2.1.0'
-
- // Google Play In-App Review
- implementation "com.google.android.play:review:2.0.2"
- implementation "com.google.android.play:review-ktx:2.0.2"
+ // Timber for logs
+ implementation 'com.jakewharton.timber:timber:4.7.1'
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9f8938b..a01a9fc 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,18 +1,11 @@
-
-
-
+
-
-
-
-
@@ -30,17 +23,10 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
- android:theme="@style/Theme.VITTY"
- android:usesCleartextTraffic="true">
-
+ android:theme="@style/Theme.VITTY">
-
@@ -105,7 +91,6 @@
-
-
=
hashMapOf(
- LATEST_VERSION to BuildConfig.VERSION_NAME,
+ LATEST_VERSION to BuildConfig.VERSION_CODE,
ONLINE_MODE to false
)
diff --git a/app/src/main/java/com/dscvit/vitty/activity/AddInfoActivity.kt b/app/src/main/java/com/dscvit/vitty/activity/AddInfoActivity.kt
deleted file mode 100644
index 2cffe56..0000000
--- a/app/src/main/java/com/dscvit/vitty/activity/AddInfoActivity.kt
+++ /dev/null
@@ -1,343 +0,0 @@
-package com.dscvit.vitty.activity
-
-import android.app.Activity
-import android.app.AlarmManager
-import android.app.PendingIntent
-import android.content.Context
-import android.content.Intent
-import android.content.SharedPreferences
-import android.os.Build
-import android.os.Bundle
-import android.os.PowerManager
-import android.provider.Settings
-import android.text.Editable
-import android.text.TextWatcher
-import android.view.View
-import android.widget.ArrayAdapter
-import android.widget.Toast
-import androidx.appcompat.app.AppCompatActivity
-import androidx.core.content.edit
-import androidx.databinding.DataBindingUtil
-import androidx.lifecycle.ViewModelProvider
-import com.dscvit.vitty.BuildConfig
-import com.dscvit.vitty.R
-import com.dscvit.vitty.databinding.ActivityAddInfoBinding
-import com.dscvit.vitty.receiver.AlarmReceiver
-import com.dscvit.vitty.ui.auth.AuthViewModel
-import com.dscvit.vitty.util.ArraySaverLoader
-import com.dscvit.vitty.util.Constants
-import com.dscvit.vitty.util.LogoutHelper
-import com.dscvit.vitty.util.NotificationHelper
-import com.dscvit.vitty.util.UtilFunctions
-import com.google.firebase.firestore.FirebaseFirestore
-import com.google.firebase.firestore.Source
-import timber.log.Timber
-import java.util.Date
-
-class AddInfoActivity : AppCompatActivity() {
- private lateinit var binding: ActivityAddInfoBinding
- private lateinit var authViewModel: AuthViewModel
- private lateinit var prefs: SharedPreferences
- private val db = FirebaseFirestore.getInstance()
- private val days =
- listOf("monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday")
- private var uid = ""
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- binding = DataBindingUtil.setContentView(this, R.layout.activity_add_info)
- authViewModel = ViewModelProvider(this)[AuthViewModel::class.java]
- prefs = getSharedPreferences(Constants.USER_INFO, Context.MODE_PRIVATE)
- uid = prefs.getString(Constants.UID, "").toString()
- setupToolbar()
- setGDSCVITChannel()
- setupCampusSpinner()
-
- binding.continueButton.setOnClickListener {
- setupContinueButton()
- }
-
- authViewModel.signInResponse.observe(this) {
- if (it != null) {
- prefs.edit().putString(Constants.COMMUNITY_TOKEN, it.token).apply()
- prefs.edit().putString(Constants.COMMUNITY_NAME, it.name).apply()
- prefs.edit().putString(Constants.COMMUNITY_PICTURE, it.picture).apply()
- } else {
- Toast.makeText(this, R.string.something_went_wrong, Toast.LENGTH_LONG).show()
- binding.loadingView.visibility = View.GONE
- }
- }
-
- authViewModel.user.observe(this) {
- Timber.d("User: $it")
- if (it != null) {
- val timetableDays = it.timetable?.data
- if (!timetableDays?.Monday.isNullOrEmpty() ||
- !timetableDays?.Tuesday.isNullOrEmpty() ||
- !timetableDays?.Wednesday.isNullOrEmpty() ||
- !timetableDays?.Thursday.isNullOrEmpty() ||
- !timetableDays?.Friday.isNullOrEmpty() ||
- !timetableDays?.Saturday.isNullOrEmpty() ||
- !timetableDays?.Sunday.isNullOrEmpty()
- ) {
- binding.loadingView.visibility = View.GONE
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- createNotificationChannels()
- } else {
- tellUpdated()
- }
- prefs.edit().putBoolean(Constants.COMMUNITY_TIMETABLE_AVAILABLE, true).apply()
- } else {
- val intent = Intent(this, InstructionsActivity::class.java)
- binding.loadingView.visibility = View.GONE
- startActivity(intent)
- finish()
- }
- } else {
- Toast.makeText(this, R.string.something_went_wrong, Toast.LENGTH_LONG).show()
- binding.loadingView.visibility = View.GONE
- }
- }
-
- binding.etUsername.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,
- ) {
- val username = s.toString().trim()
- authViewModel.checkUsername(username)
- }
-
- override fun afterTextChanged(s: Editable?) {
- }
- },
- )
-
- authViewModel.usernameValidity.observe(this) {
- Timber.d("Validity: $it")
- if (it != null) {
- binding.usernameValidity.visibility = View.VISIBLE
- binding.usernameValidity.text = it.detail
- if (it.detail == "Username is valid") {
- binding.usernameValidity.setTextColor(getColor(R.color.white))
- } else {
- binding.usernameValidity.setTextColor(getColor(R.color.red))
- }
- }
- }
- }
-
- private fun setupCampusSpinner() {
- val campusOptions = arrayOf("Select Campus", "Vellore", "Chennai", "Bhopal")
- val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, campusOptions)
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
- binding.spinnerCampus.adapter = adapter
- }
-
- private fun setupContinueButton() {
- binding.loadingView.visibility = View.VISIBLE
- val uuid = prefs.getString(Constants.UID, null)
- val username =
- binding.etUsername.text
- .toString()
- .trim()
- val regno =
- binding.etRegno.text
- .toString()
- .uppercase()
- .trim()
- val selectedCampus = binding.spinnerCampus.selectedItem.toString()
- val regexPattern = Regex("^[0-9]{2}[a-zA-Z]{3}[0-9]{4}$")
-
- if (username.isEmpty() || regno.isEmpty() || selectedCampus == "Select Campus") {
- Toast.makeText(this, getString(R.string.fill_all_fields), Toast.LENGTH_LONG).show()
- binding.loadingView.visibility = View.GONE
- } else if (!regexPattern.matches(regno)) {
- Toast.makeText(this, getString(R.string.invalid_regno), Toast.LENGTH_LONG).show()
- binding.loadingView.visibility = View.GONE
- } else {
- if (uuid != null) {
- prefs.edit().putString(Constants.COMMUNITY_USERNAME, username).apply()
- prefs.edit { putString(Constants.COMMUNITY_REGNO, regno) }
- prefs.edit { putString(Constants.COMMUNITY_CAMPUS, selectedCampus) }
- authViewModel.signInAndGetTimeTable(username, regno, uuid, selectedCampus.lowercase())
- } else {
- Toast
- .makeText(this, getString(R.string.something_went_wrong), Toast.LENGTH_LONG)
- .show()
- binding.loadingView.visibility = View.GONE
- }
- }
- }
-
- private fun setupToolbar() {
- binding.addInfoToolbar.setOnMenuItemClickListener { menuItem ->
- when (menuItem.itemId) {
- R.id.close -> {
- LogoutHelper.logout(this, this as Activity, prefs)
- true
- }
-
- else -> false
- }
- }
- }
-
- private fun createNotificationChannels() {
- binding.loadingView.visibility = View.VISIBLE
- setNotificationGroup()
- val notifChannels = ArraySaverLoader.loadArray(Constants.NOTIFICATION_CHANNELS, this)
- for (notifChannel in notifChannels) {
- if (notifChannel != null) {
- NotificationHelper.deleteNotificationChannel(this, notifChannel.toString())
- }
- }
- val newNotifChannels: ArrayList = ArrayList()
- for (day in days) {
- db
- .collection("users")
- .document(uid)
- .collection("timetable")
- .document(day)
- .collection("periods")
- .get(Source.SERVER)
- .addOnSuccessListener { result ->
- for (document in result) {
- var cn = document.getString("courseName")
- cn = if (cn.isNullOrEmpty()) "Default" else cn
- val cc = document.getString("courseCode")
- NotificationHelper.createNotificationChannel(
- this,
- cn,
- "Course Code: $cc",
- Constants.GROUP_ID,
- )
- newNotifChannels.add(cn)
- Timber.d(cn)
- }
- ArraySaverLoader.saveArray(
- newNotifChannels,
- Constants.NOTIFICATION_CHANNELS,
- this,
- )
-
- if (day == "sunday") {
- tellUpdated()
- }
- }.addOnFailureListener { e ->
- Timber.d("Error: $e")
- }
- }
- }
-
- private fun tellUpdated() {
- prefs.edit().putInt(Constants.TIMETABLE_AVAILABLE, 1).apply()
- prefs.edit().putInt(Constants.UPDATE, 0).apply()
- val updated =
- hashMapOf(
- "isTimetableAvailable" to true,
- "isUpdated" to false,
- )
- db
- .collection("users")
- .document(uid)
- .set(updated)
- .addOnSuccessListener {
- setAlarm()
- UtilFunctions.reloadWidgets(this)
- val pm: PowerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
- if (!pm.isIgnoringBatteryOptimizations(packageName)) {
- Toast
- .makeText(
- this,
- "Please turn off the Battery Optimization Settings for VITTY to receive notifications on time.",
- Toast.LENGTH_LONG,
- ).show()
- val pmIntent = Intent()
- pmIntent.action = Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
- startActivity(pmIntent)
- } else {
- val intent = Intent(this, HomeComposeActivity::class.java)
- startActivity(intent)
- finish()
- }
- }.addOnFailureListener { e ->
- Timber.d("Error: $e")
- }
- }
-
- private fun setGDSCVITChannel() {
- if (!prefs.getBoolean("gdscvitChannelCreated", false)) {
- NotificationHelper.createNotificationGroup(
- this,
- getString(R.string.gdscvit),
- Constants.GROUP_ID_2,
- )
- NotificationHelper.createNotificationChannel(
- this,
- getString(R.string.default_notification_channel_name),
- "Notifications from GDSC VIT",
- Constants.GROUP_ID_2,
- )
- prefs.edit {
- putBoolean("gdscvitChannelCreated", true)
- apply()
- }
- }
- }
-
- private fun setNotificationGroup() {
- if (!prefs.getBoolean("groupCreated", false)) {
- NotificationHelper.createNotificationGroup(
- this,
- getString(R.string.notif_group),
- Constants.GROUP_ID,
- )
- prefs.edit {
- putBoolean("groupCreated", true)
- apply()
- }
- }
- }
-
- private fun setAlarm() {
- if (!prefs.getBoolean(Constants.EXAM_MODE, false)) {
- if (prefs.getInt(Constants.VERSION_CODE, 0) != BuildConfig.VERSION_CODE) {
- val intent = Intent(this, AlarmReceiver::class.java)
-
- val pendingIntent =
- PendingIntent.getBroadcast(
- this,
- Constants.ALARM_INTENT,
- intent,
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
- )
- val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
-
- val date = Date().time
-
- alarmManager.setRepeating(
- AlarmManager.RTC_WAKEUP,
- date,
- (1000 * 60 * Constants.NOTIF_DELAY).toLong(),
- pendingIntent,
- )
-
- prefs.edit {
- putInt(Constants.VERSION_CODE, BuildConfig.VERSION_CODE)
- apply()
- }
- }
- }
- }
-}
diff --git a/app/src/main/java/com/dscvit/vitty/activity/AuthActivity.kt b/app/src/main/java/com/dscvit/vitty/activity/AuthActivity.kt
index a58db1c..c984561 100755
--- a/app/src/main/java/com/dscvit/vitty/activity/AuthActivity.kt
+++ b/app/src/main/java/com/dscvit/vitty/activity/AuthActivity.kt
@@ -1,31 +1,20 @@
package com.dscvit.vitty.activity
-import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
-import android.os.Build
import android.os.Bundle
import android.view.View
import android.widget.Toast
-import androidx.activity.result.ActivityResultLauncher
-import androidx.activity.result.contract.ActivityResultContracts
-import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
-import androidx.core.content.edit
import androidx.databinding.DataBindingUtil
-import androidx.lifecycle.ViewModelProvider
import androidx.viewpager2.widget.ViewPager2
import com.dscvit.vitty.R
import com.dscvit.vitty.adapter.IntroAdapter
import com.dscvit.vitty.databinding.ActivityAuthBinding
-import com.dscvit.vitty.ui.auth.AuthViewModel
-import com.dscvit.vitty.util.Constants
import com.dscvit.vitty.util.Constants.TOKEN
import com.dscvit.vitty.util.Constants.UID
import com.dscvit.vitty.util.Constants.USER_INFO
-import com.dscvit.vitty.util.NotificationPermissionHelper
-import com.dscvit.vitty.util.MaintenanceChecker
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInClient
@@ -35,9 +24,9 @@ import com.google.android.gms.tasks.Task
import com.google.android.material.tabs.TabLayoutMediator
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.GoogleAuthProvider
-import timber.log.Timber
class AuthActivity : AppCompatActivity() {
+
private lateinit var binding: ActivityAuthBinding
private val SIGNIN: Int = 1
@@ -45,130 +34,34 @@ class AuthActivity : AppCompatActivity() {
private lateinit var mGoogleSignInOptions: GoogleSignInOptions
private lateinit var firebaseAuth: FirebaseAuth
private lateinit var sharedPref: SharedPreferences
- private lateinit var authViewModel: AuthViewModel
private val pages = listOf("○", "○", "○")
private var loginClick = false
- private lateinit var notificationPermissionLauncher: ActivityResultLauncher
-
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_auth)
firebaseAuth = FirebaseAuth.getInstance()
sharedPref = getSharedPreferences(USER_INFO, Context.MODE_PRIVATE)
- authViewModel = ViewModelProvider(this)[AuthViewModel::class.java]
-
- setupNotificationPermissionLauncher()
- requestNotificationPermissionIfNeeded()
-
configureGoogleSignIn()
setupUI()
- setupBackPressedHandler()
- }
-
- private fun setupBackPressedHandler() {
- val callback = object : OnBackPressedCallback(true) {
- override fun handleOnBackPressed() {
- binding.apply {
- if (introPager.currentItem == 0 || loginClick) {
- finish()
- } else {
- introPager.currentItem--
- }
- }
- }
- }
- onBackPressedDispatcher.addCallback(this, callback)
- }
-
- private fun setupNotificationPermissionLauncher() {
- notificationPermissionLauncher =
- registerForActivityResult(
- ActivityResultContracts.RequestPermission(),
- ) { isGranted ->
- if (isGranted) {
- Timber.d("Notification permission granted")
- // Check and request exact alarm permission if needed
- if (!NotificationPermissionHelper.canScheduleExactAlarms(this)) {
- NotificationPermissionHelper.requestExactAlarmPermission(this)
- }
- } else {
- Timber.d("Notification permission denied")
- Toast
- .makeText(
- this,
- "Notification permission is required for reminders to work properly",
- Toast.LENGTH_LONG,
- ).show()
- }
- }
- }
-
- private fun requestNotificationPermissionIfNeeded() {
- // For Android 13+ (API 33+), request POST_NOTIFICATIONS permission
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- if (!NotificationPermissionHelper.hasNotificationPermission(this)) {
- Timber.d("Requesting POST_NOTIFICATIONS permission for Android 13+")
- notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
- } else {
- Timber.d("POST_NOTIFICATIONS permission already granted")
- checkAdditionalPermissions()
- }
- } else {
- // For Android 12 and below, notifications are enabled by default
- // but we still need to check other permissions
- Timber.d("Android version < 13, notifications enabled by default")
- checkAdditionalPermissions()
- }
- }
-
- private fun checkAdditionalPermissions() {
- // Check and request exact alarm permission if needed (Android 12+)
- if (!NotificationPermissionHelper.canScheduleExactAlarms(this)) {
- Timber.d("Requesting exact alarm permission")
- NotificationPermissionHelper.requestExactAlarmPermission(this)
- }
-
- // Note: Battery optimization can be checked later in the app flow
- // as it's more intrusive and not immediately necessary
}
override fun onStart() {
super.onStart()
- sharedPref = getSharedPreferences(USER_INFO, Context.MODE_PRIVATE)
- val isTimeTableAvailable =
- sharedPref.getBoolean(Constants.COMMUNITY_TIMETABLE_AVAILABLE, false)
- val token = sharedPref.getString(Constants.COMMUNITY_TOKEN, null)
- val username = sharedPref.getString(Constants.COMMUNITY_USERNAME, null)
- val regno = sharedPref.getString(Constants.COMMUNITY_REGNO, null)
val user = FirebaseAuth.getInstance().currentUser
- Timber.d("isTimeTableAvailable: $isTimeTableAvailable token: $token username: $username regno: $regno")
- if (isTimeTableAvailable) {
- val intent = Intent(this, HomeComposeActivity::class.java)
- startActivity(intent)
- finish()
- } else if (token != null && username != null) {
+ if (user != null) {
val intent = Intent(this, InstructionsActivity::class.java)
startActivity(intent)
finish()
- } else {
- Timber.d("here going to add info")
- if (user != null) {
- val intent = Intent(this, AddInfoActivity::class.java)
- startActivity(intent)
- finish()
- }
}
}
private fun configureGoogleSignIn() {
- mGoogleSignInOptions =
- GoogleSignInOptions
- .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
- .requestIdToken(getString(R.string.default_web_client_id))
- .requestEmail()
- .build()
+ mGoogleSignInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
+ .requestIdToken(getString(R.string.default_web_client_id))
+ .requestEmail()
+ .build()
mGoogleSignInClient = GoogleSignIn.getClient(this, mGoogleSignInOptions)
mGoogleSignInClient.signOut()
}
@@ -177,33 +70,30 @@ class AuthActivity : AppCompatActivity() {
val pagerAdapter = IntroAdapter(this)
binding.introPager.adapter = pagerAdapter
- val pageChangeCallback =
- object : ViewPager2.OnPageChangeCallback() {
- override fun onPageSelected(position: Int) {
- binding.apply {
- if (position == 0 || position == 1) {
- loginButton.visibility = View.INVISIBLE
- nextButton.visibility = View.VISIBLE
- } else {
- nextButton.visibility = View.INVISIBLE
- loginButton.visibility = View.VISIBLE
- }
+ val pageChangeCallback = object : ViewPager2.OnPageChangeCallback() {
+ override fun onPageSelected(position: Int) {
+ binding.apply {
+ if (position == 0 || position == 1) {
+ loginButton.visibility = View.INVISIBLE
+ nextButton.visibility = View.VISIBLE
+ } else {
+ nextButton.visibility = View.INVISIBLE
+ loginButton.visibility = View.VISIBLE
}
}
}
+ }
binding.introPager.registerOnPageChangeCallback(pageChangeCallback)
TabLayoutMediator(
- binding.introTabs,
- binding.introPager,
+ binding.introTabs, binding.introPager
) { tab, position -> tab.text = pages[position] }.attach()
binding.nextButton.setOnClickListener {
binding.apply {
- if (introPager.currentItem != pages.size - 1) {
+ if (introPager.currentItem != pages.size - 1)
introPager.currentItem++
- }
}
}
@@ -223,136 +113,59 @@ class AuthActivity : AppCompatActivity() {
}
private fun logoutFailed() {
- Timber.e("Google sign-in failed - showing error message to user")
Toast.makeText(this, getString(R.string.sign_in_fail), Toast.LENGTH_LONG).show()
binding.loadingView.visibility = View.GONE
binding.introPager.currentItem = 0
loginClick = false
}
- private fun saveInfo(
- token: String?,
- uid: String?,
- ) {
+ private fun saveInfo(token: String?, uid: String?) {
with(sharedPref.edit()) {
- putString("simethod", "Google")
+ putString("sign_in_method", "Google")
putString(TOKEN, token)
putString(UID, uid)
apply()
}
}
- override fun onActivityResult(
- requestCode: Int,
- resultCode: Int,
- data: Intent?,
- ) {
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
- Timber.d("Activity Result - requestCode: $requestCode, resultCode: $resultCode")
if (requestCode == SIGNIN) {
val task: Task = GoogleSignIn.getSignedInAccountFromIntent(data)
try {
val account = task.getResult(ApiException::class.java)
- Timber.d("Google sign-in account: $account")
if (account != null) {
- Timber.d("Google sign-in successful, proceeding with Firebase auth")
firebaseAuthWithGoogle(account)
- } else {
- Timber.e("Google sign-in account is null")
- logoutFailed()
}
} catch (e: ApiException) {
- Timber.e("Google sign-in failed with ApiException: ${e.message}, statusCode: ${e.statusCode}")
- logoutFailed()
- } catch (e: Exception) {
- Timber.e("Google sign-in failed with Exception: ${e.message}")
logoutFailed()
}
}
}
private fun firebaseAuthWithGoogle(acct: GoogleSignInAccount) {
- Timber.d("Starting Firebase authentication with Google account: ${acct.email}")
val credential = GoogleAuthProvider.getCredential(acct.idToken, null)
-
- firebaseAuth
- .signInWithCredential(credential)
- .addOnCompleteListener { authResult ->
- if (authResult.isSuccessful) {
- loginClick = true
- val uid = firebaseAuth.currentUser?.uid
- val email = firebaseAuth.currentUser?.email
- Timber.d("Firebase authentication successful - uid: $uid, email: $email")
- saveInfo(acct.idToken, uid)
-
- // Quick maintenance check for new login
- checkMaintenanceBeforeProceed()
- } else {
- Timber.e("Firebase authentication failed: ${authResult.exception?.message}")
- logoutFailed()
- }
- }.addOnFailureListener { exception ->
- Timber.e("Firebase authentication failed with exception: ${exception.message}")
- logoutFailed()
- }
- }
-
- private fun checkMaintenanceBeforeProceed() {
- MaintenanceChecker.checkMaintenanceStatusAsync(this) { isUnderMaintenance ->
- if (isUnderMaintenance) {
+ firebaseAuth.signInWithCredential(credential).addOnCompleteListener {
+ if (it.isSuccessful) {
+ loginClick = true
+ val uid = firebaseAuth.currentUser?.uid
+ saveInfo(acct.idToken, uid)
+ val intent = Intent(this, InstructionsActivity::class.java)
binding.loadingView.visibility = View.GONE
- val intent = Intent(this, MaintenanceActivity::class.java)
startActivity(intent)
finish()
} else {
- authViewModel.signInAndGetTimeTable("", "", firebaseAuth.currentUser?.uid ?: "", "")
- leadToNextPage()
+ logoutFailed()
}
}
}
- private fun leadToNextPage() {
- authViewModel.signInResponse.observe(this) {
- if (it != null) {
- Timber.d("here--$it")
- sharedPref.edit { putString(Constants.COMMUNITY_USERNAME, it.username) }
- sharedPref.edit { putString(Constants.COMMUNITY_TOKEN, it.token) }
- sharedPref.edit { putString(Constants.COMMUNITY_NAME, it.name) }
- sharedPref.edit { putString(Constants.COMMUNITY_PICTURE, it.picture) }
- sharedPref.edit { putString(Constants.COMMUNITY_CAMPUS, it.campus) }
+ override fun onBackPressed() {
+ binding.apply {
+ if (introPager.currentItem == 0 || loginClick) {
+ super.onBackPressed()
} else {
- val intent = Intent(this, AddInfoActivity::class.java)
- binding.loadingView.visibility = View.GONE
- startActivity(intent)
- finish()
- }
- }
-
- authViewModel.user.observe(this) {
- if (it != null) {
- val timetableDays = it.timetable?.data
- if (!timetableDays?.Monday.isNullOrEmpty() ||
- !timetableDays?.Tuesday.isNullOrEmpty() ||
- !timetableDays?.Wednesday.isNullOrEmpty() ||
- !timetableDays?.Thursday.isNullOrEmpty() ||
- !timetableDays?.Friday.isNullOrEmpty() ||
- !timetableDays?.Saturday.isNullOrEmpty() ||
- !timetableDays?.Sunday.isNullOrEmpty()
- ) {
- sharedPref
- .edit {
- putBoolean(Constants.COMMUNITY_TIMETABLE_AVAILABLE, true)
- }
- val intent = Intent(this, HomeComposeActivity::class.java)
- startActivity(intent)
- finish()
- binding.loadingView.visibility = View.GONE
- } else {
- val intent = Intent(this, InstructionsActivity::class.java)
- startActivity(intent)
- finish()
- binding.loadingView.visibility = View.GONE
- }
+ introPager.currentItem--
}
}
}
diff --git a/app/src/main/java/com/dscvit/vitty/activity/HomeActivity.kt b/app/src/main/java/com/dscvit/vitty/activity/HomeActivity.kt
index c8ba281..f529585 100644
--- a/app/src/main/java/com/dscvit/vitty/activity/HomeActivity.kt
+++ b/app/src/main/java/com/dscvit/vitty/activity/HomeActivity.kt
@@ -1,492 +1,28 @@
package com.dscvit.vitty.activity
-import android.animation.AnimatorSet
-import android.animation.ObjectAnimator
import android.os.Bundle
-import android.view.View
-import android.view.animation.AccelerateDecelerateInterpolator
-import android.view.animation.DecelerateInterpolator
-import android.view.animation.OvershootInterpolator
-import android.widget.ImageView
-import android.widget.LinearLayout
-import android.widget.TextView
-import androidx.core.view.isVisible
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.FragmentActivity
-import androidx.navigation.NavOptions
import androidx.navigation.findNavController
+import androidx.navigation.ui.setupWithNavController
import com.dscvit.vitty.R
import com.dscvit.vitty.databinding.ActivityHomeBinding
+import com.google.android.material.bottomnavigation.BottomNavigationView
class HomeActivity : FragmentActivity() {
+
private lateinit var binding: ActivityHomeBinding
- private var selectedBackground: View? = null
- private var currentSelectedId = -1
- private var isAnimating = false
- private var isNavigating = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_home)
- val navController = findNavController(R.id.nav_host_fragment_activity_main)
-
- fun createNavOptions(): NavOptions =
- NavOptions
- .Builder()
- .setEnterAnim(R.anim.crossfade_in)
- .setExitAnim(R.anim.crossfade_out)
- .setPopEnterAnim(R.anim.crossfade_in)
- .setPopExitAnim(R.anim.crossfade_out)
- .build()
-
- fun navigateIfNeeded(destinationId: Int) {
- if (navController.currentDestination?.id != destinationId && !isNavigating) {
- isNavigating = true
-
- android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
- navController.navigate(destinationId, null, createNavOptions())
-
- android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
- isNavigating = false
- }, 250)
- }, 50)
- }
- }
-
- fun findImageViewInLayout(layout: LinearLayout): ImageView? {
- for (i in 0 until layout.childCount) {
- val child = layout.getChildAt(i)
- if (child is ImageView) {
- return child
- }
- }
- return null
- }
-
- fun animateIconBounce(layout: LinearLayout) {
- val imageView = findImageViewInLayout(layout) ?: return
-
- val scaleX =
- ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 1.15f, 1f).apply {
- duration = 250
- interpolator = OvershootInterpolator(1.0f)
- }
- val scaleY =
- ObjectAnimator.ofFloat(imageView, "scaleY", 1f, 1.15f, 1f).apply {
- duration = 250
- interpolator = OvershootInterpolator(1.0f)
- }
-
- AnimatorSet().apply {
- playTogether(scaleX, scaleY)
- start()
- }
- }
-
- fun animateTextSlideIn(
- textView: TextView,
- delay: Long = 0,
- ) {
- textView.alpha = 0f
- textView.translationX = 10f
- textView.scaleX = 0.95f
- textView.visibility = View.VISIBLE
-
- val slideAnimator =
- ObjectAnimator.ofFloat(textView, "translationX", 10f, 0f).apply {
- duration = 200
- startDelay = delay
- interpolator = AccelerateDecelerateInterpolator()
- }
- val fadeAnimator =
- ObjectAnimator.ofFloat(textView, "alpha", 0f, 1f).apply {
- duration = 150
- startDelay = delay
- }
- val scaleAnimator =
- ObjectAnimator.ofFloat(textView, "scaleX", 0.95f, 1f).apply {
- duration = 200
- startDelay = delay
- interpolator = OvershootInterpolator(0.6f)
- }
-
- AnimatorSet().apply {
- playTogether(slideAnimator, fadeAnimator, scaleAnimator)
- start()
- }
- }
-
- fun animateTextSlideOut(
- textView: TextView,
- onComplete: () -> Unit = {},
- ) {
- if (textView.visibility != View.VISIBLE) {
- onComplete()
- return
- }
-
- val slideAnimator =
- ObjectAnimator.ofFloat(textView, "translationX", 0f, -10f).apply {
- duration = 100
- interpolator = AccelerateDecelerateInterpolator()
- }
- val fadeAnimator =
- ObjectAnimator.ofFloat(textView, "alpha", 1f, 0f).apply {
- duration = 100
- }
-
- AnimatorSet().apply {
- playTogether(slideAnimator, fadeAnimator)
- addListener(
- object : android.animation.AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: android.animation.Animator) {
- textView.visibility = View.GONE
- textView.translationX = 0f
- textView.alpha = 1f
- textView.scaleX = 1f
- onComplete()
- }
-
- override fun onAnimationCancel(animation: android.animation.Animator) {
- textView.visibility = View.GONE
- textView.translationX = 0f
- textView.alpha = 1f
- textView.scaleX = 1f
- onComplete()
- }
- },
- )
- start()
- }
- }
-
- fun animatePillMovement(
- fromView: View?,
- toView: View,
- onComplete: () -> Unit = {},
- ) {
- binding.navAcademics.setBackgroundResource(0)
- binding.navTimetable.setBackgroundResource(0)
- binding.navCommunity.setBackgroundResource(0)
-
- binding.navAcademics.elevation = 0f
- binding.navTimetable.elevation = 0f
- binding.navCommunity.elevation = 0f
-
- if (fromView == null) {
- toView.setBackgroundResource(R.drawable.bg_nav_item_selected)
- toView.alpha = 0f
- toView.scaleX = 0.95f
- toView.scaleY = 0.95f
-
- val fadeAnim =
- ObjectAnimator.ofFloat(toView, "alpha", 0f, 1f).apply {
- duration = 150
- }
- val scaleXAnim =
- ObjectAnimator.ofFloat(toView, "scaleX", 0.95f, 1f).apply {
- duration = 180
- interpolator = OvershootInterpolator(0.8f)
- }
- val scaleYAnim =
- ObjectAnimator.ofFloat(toView, "scaleY", 0.95f, 1f).apply {
- duration = 180
- interpolator = OvershootInterpolator(0.8f)
- }
- val elevationAnim =
- ObjectAnimator.ofFloat(toView, "elevation", 0f, 8f).apply {
- duration = 180
- interpolator = DecelerateInterpolator()
- }
-
- AnimatorSet().apply {
- playTogether(fadeAnim, scaleXAnim, scaleYAnim, elevationAnim)
- addListener(
- object : android.animation.AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: android.animation.Animator) {
- onComplete()
- }
-
- override fun onAnimationCancel(animation: android.animation.Animator) {
- onComplete()
- }
- },
- )
- start()
- }
- return
- }
-
- toView.setBackgroundResource(R.drawable.bg_nav_item_selected)
-
- val scaleX =
- ObjectAnimator.ofFloat(toView, "scaleX", 1f, 1.03f, 1f).apply {
- duration = 150
- interpolator = AccelerateDecelerateInterpolator()
- }
- val scaleY =
- ObjectAnimator.ofFloat(toView, "scaleY", 1f, 1.03f, 1f).apply {
- duration = 150
- interpolator = AccelerateDecelerateInterpolator()
- }
- val elevationAnim =
- ObjectAnimator.ofFloat(toView, "elevation", 0f, 8f).apply {
- duration = 150
- interpolator = DecelerateInterpolator()
- }
-
- AnimatorSet().apply {
- playTogether(scaleX, scaleY, elevationAnim)
- addListener(
- object : android.animation.AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: android.animation.Animator) {
- onComplete()
- }
-
- override fun onAnimationCancel(animation: android.animation.Animator) {
- onComplete()
- }
- },
- )
- start()
- }
- }
+ val navView: BottomNavigationView = binding.navView
- fun highlightSelectedTab(selectedId: Int) {
- if (currentSelectedId == selectedId) return
-
- if (isAnimating) {
- binding.textAcademics.clearAnimation()
- binding.textTimetable.clearAnimation()
- binding.textCommunity.clearAnimation()
- binding.navAcademics.clearAnimation()
- binding.navTimetable.clearAnimation()
- binding.navCommunity.clearAnimation()
- }
-
- isAnimating = true
-
- val (newSelectedView, newTextView) =
- when (selectedId) {
- R.id.navigation_academics -> Pair(binding.navAcademics, binding.textAcademics)
- R.id.navigation_schedule -> Pair(binding.navTimetable, binding.textTimetable)
- R.id.navigation_connect -> Pair(binding.navCommunity, binding.textCommunity)
- else -> {
- isAnimating = false
- return
- }
- }
-
- val allTextViews = listOf(binding.textAcademics, binding.textTimetable, binding.textCommunity)
- val visibleTextViews = allTextViews.filter { it.isVisible && it != newTextView }
-
- var completedOperations = 0
- val totalOperations = 1 + visibleTextViews.size
-
- fun onOperationComplete() {
- completedOperations++
- if (completedOperations >= totalOperations) {
- isAnimating = false
- }
- }
-
- animatePillMovement(selectedBackground, newSelectedView) {
- onOperationComplete()
- }
-
- animateTextSlideIn(newTextView, delay = 25)
-
- android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
- animateIconBounce(newSelectedView)
- }, 50)
-
- if (visibleTextViews.isEmpty()) {
- onOperationComplete()
- } else {
- visibleTextViews.forEach { textView ->
- animateTextSlideOut(textView) {
- onOperationComplete()
- }
- }
- }
-
- selectedBackground = newSelectedView
- currentSelectedId = selectedId
- }
-
- fun animateButtonPress(view: View) {
- val scaleDown =
- ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.95f).apply {
- duration = 60
- interpolator = AccelerateDecelerateInterpolator()
- }
- val scaleDownY =
- ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.95f).apply {
- duration = 60
- interpolator = AccelerateDecelerateInterpolator()
- }
- val elevationDown =
- ObjectAnimator.ofFloat(view, "elevation", view.elevation, view.elevation * 0.5f).apply {
- duration = 60
- }
- val scaleUp =
- ObjectAnimator.ofFloat(view, "scaleX", 0.95f, 1f).apply {
- duration = 100
- interpolator = OvershootInterpolator(1.2f)
- }
- val scaleUpY =
- ObjectAnimator.ofFloat(view, "scaleY", 0.95f, 1f).apply {
- duration = 100
- interpolator = OvershootInterpolator(1.2f)
- }
- val elevationUp =
- ObjectAnimator.ofFloat(view, "elevation", view.elevation * 0.5f, view.elevation).apply {
- duration = 100
- interpolator = OvershootInterpolator(0.6f)
- }
-
- AnimatorSet().apply {
- play(scaleDown).with(scaleDownY).with(elevationDown)
- play(scaleUp).after(scaleDown).with(scaleUpY).with(elevationUp)
- start()
- }
- }
-
- binding.navAcademics.setOnClickListener {
- if (isAnimating || isNavigating) return@setOnClickListener
- try {
- it.performHapticFeedback(android.view.HapticFeedbackConstants.VIRTUAL_KEY)
- } catch (e: Exception) {
- }
- animateButtonPress(it)
- navigateIfNeeded(R.id.navigation_academics)
- }
-
- binding.navTimetable.setOnClickListener {
- if (isAnimating || isNavigating) return@setOnClickListener
- try {
- it.performHapticFeedback(android.view.HapticFeedbackConstants.VIRTUAL_KEY)
- } catch (e: Exception) {
- }
- animateButtonPress(it)
- navigateIfNeeded(R.id.navigation_schedule)
- }
-
- binding.navCommunity.setOnClickListener {
- if (isAnimating || isNavigating) return@setOnClickListener
- try {
- it.performHapticFeedback(android.view.HapticFeedbackConstants.VIRTUAL_KEY)
- } catch (e: Exception) {
- }
- animateButtonPress(it)
- navigateIfNeeded(R.id.navigation_connect)
- }
-
- navController.addOnDestinationChangedListener { _, destination, _ ->
-
- android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
- when (destination.id) {
- R.id.allRequestFragment,
- R.id.friendFragment,
- R.id.searchFragment,
- R.id.navigation_requests,
- R.id.coursePageFragment,
- R.id.noteFragment,
- -> {
- hideBottomNavSafely()
- }
-
- R.id.navigation_academics -> {
- showBottomNavSafely()
- android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
- highlightSelectedTab(R.id.navigation_academics)
- }, 25)
- }
-
- R.id.navigation_schedule -> {
- showBottomNavSafely()
- android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
- highlightSelectedTab(R.id.navigation_schedule)
- }, 25)
- }
-
- R.id.navigation_connect -> {
- showBottomNavSafely()
- android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
- highlightSelectedTab(R.id.navigation_connect)
- }, 25)
- }
-
- else -> {
- hideBottomNavSafely()
- }
- }
- }, 50)
- }
- }
-
- private fun showBottomNavSafely() {
- if (binding.customBottomNav.visibility != View.VISIBLE) {
- binding.customBottomNav.visibility = View.VISIBLE
- binding.customBottomNav.translationY = 200f
- binding.customBottomNav.alpha = 0f
- binding.customBottomNav.scaleY = 0.9f
-
- val slideUp =
- ObjectAnimator.ofFloat(binding.customBottomNav, "translationY", 200f, 0f).apply {
- duration = 300
- interpolator = DecelerateInterpolator(1.0f)
- }
- val fadeIn =
- ObjectAnimator.ofFloat(binding.customBottomNav, "alpha", 0f, 1f).apply {
- duration = 250
- startDelay = 25
- }
- val scaleUp =
- ObjectAnimator.ofFloat(binding.customBottomNav, "scaleY", 0.9f, 1f).apply {
- duration = 280
- interpolator = OvershootInterpolator(0.4f)
- startDelay = 50
- }
+ val navController = findNavController(R.id.nav_host_fragment_activity_main)
- AnimatorSet().apply {
- playTogether(slideUp, fadeIn, scaleUp)
- start()
- }
- }
+ navView.setupWithNavController(navController)
}
- private fun hideBottomNavSafely() {
- if (binding.customBottomNav.visibility == View.VISIBLE) {
- val slideDown =
- ObjectAnimator.ofFloat(binding.customBottomNav, "translationY", 0f, 200f).apply {
- duration = 250
- interpolator = AccelerateDecelerateInterpolator()
- }
- val fadeOut =
- ObjectAnimator.ofFloat(binding.customBottomNav, "alpha", 1f, 0f).apply {
- duration = 200
- }
- val scaleDown =
- ObjectAnimator.ofFloat(binding.customBottomNav, "scaleY", 1f, 0.9f).apply {
- duration = 220
- interpolator = AccelerateDecelerateInterpolator()
- }
- AnimatorSet().apply {
- playTogether(slideDown, fadeOut, scaleDown)
- addListener(
- object : android.animation.AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: android.animation.Animator) {
- binding.customBottomNav.visibility = View.GONE
- binding.customBottomNav.translationY = 0f
- binding.customBottomNav.scaleY = 1f
- }
- },
- )
- start()
- }
- }
- }
}
diff --git a/app/src/main/java/com/dscvit/vitty/activity/HomeComposeActivity.kt b/app/src/main/java/com/dscvit/vitty/activity/HomeComposeActivity.kt
deleted file mode 100644
index d891ee7..0000000
--- a/app/src/main/java/com/dscvit/vitty/activity/HomeComposeActivity.kt
+++ /dev/null
@@ -1,247 +0,0 @@
-package com.dscvit.vitty.activity
-
-import android.content.SharedPreferences
-import android.os.Bundle
-import androidx.activity.result.ActivityResult
-import androidx.activity.result.contract.ActivityResultContracts
-import androidx.compose.ui.platform.ViewCompositionStrategy
-import androidx.core.content.edit
-import androidx.databinding.DataBindingUtil
-import androidx.fragment.app.FragmentActivity
-import com.dscvit.vitty.R
-import com.dscvit.vitty.databinding.ActivityHomeComposeBinding
-import com.dscvit.vitty.ui.main.MainComposeApp
-import com.dscvit.vitty.util.Constants
-import com.dscvit.vitty.util.Constants.PREF_LAST_REVIEW_REQUEST
-import com.google.android.material.snackbar.Snackbar
-import com.google.android.play.core.appupdate.AppUpdateInfo
-import com.google.android.play.core.appupdate.AppUpdateManager
-import com.google.android.play.core.appupdate.AppUpdateManagerFactory
-import com.google.android.play.core.appupdate.AppUpdateOptions
-import com.google.android.play.core.install.InstallStateUpdatedListener
-import com.google.android.play.core.install.model.AppUpdateType
-import com.google.android.play.core.install.model.InstallStatus
-import com.google.android.play.core.install.model.UpdateAvailability
-import com.google.android.play.core.review.ReviewInfo
-import com.google.android.play.core.review.ReviewManager
-import com.google.android.play.core.review.ReviewManagerFactory
-import timber.log.Timber
-import java.util.concurrent.TimeUnit
-
-class HomeComposeActivity : FragmentActivity() {
- private lateinit var binding: ActivityHomeComposeBinding
- private lateinit var prefs: SharedPreferences
- private lateinit var appUpdateManager: AppUpdateManager
- private lateinit var reviewManager: ReviewManager
-
- private var reviewInfo: ReviewInfo? = null
-
- companion object {
- private val REVIEW_INTERVAL_MILLIS = TimeUnit.DAYS.toMillis(30)
- private const val TAG = "HomeComposeActivity"
- }
-
- private val updateResultLauncher =
- registerForActivityResult(
- ActivityResultContracts.StartIntentSenderForResult(),
- ) { result: ActivityResult ->
- when (result.resultCode) {
- RESULT_OK -> {
- Timber.d("$TAG:Update flow completed successfully")
- }
- RESULT_CANCELED -> {
- Timber.d("$TAG:Update flow was cancelled by user")
- }
- else -> {
- Timber.d("$TAG:Update flow failed with result code: ${result.resultCode}")
- }
- }
- }
-
- private val installStateUpdatedListener: InstallStateUpdatedListener =
- InstallStateUpdatedListener { state ->
- when (state.installStatus()) {
- InstallStatus.DOWNLOADED -> {
- showUpdateDownloadedSnackbar()
- }
- InstallStatus.INSTALLED -> {
- appUpdateManager.unregisterListener(installStateUpdatedListener)
- }
- else -> {
- Timber.d("$TAG:Install status: ${state.installStatus()}")
- }
- }
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- binding = DataBindingUtil.setContentView(this, R.layout.activity_home_compose)
- prefs = getSharedPreferences(Constants.USER_INFO, 0)
- appUpdateManager = AppUpdateManagerFactory.create(this)
- reviewManager = ReviewManagerFactory.create(this)
-
- binding.composeView.apply {
- setViewCompositionStrategy(
- ViewCompositionStrategy.DisposeOnLifecycleDestroyed(this@HomeComposeActivity),
- )
- setContent { MainComposeApp() }
- }
-
- appUpdateManager.registerListener(installStateUpdatedListener)
-
- checkForAppUpdate()
- checkForReviewRequest()
- }
-
- override fun onResume() {
- super.onResume()
-
- appUpdateManager.appUpdateInfo
- .addOnSuccessListener { appUpdateInfo ->
- Timber.d(
- "$TAG:onResume - Update availability: ${appUpdateInfo.updateAvailability()}",
- )
- Timber.d("$TAG:onResume - Install status: ${appUpdateInfo.installStatus()}")
-
- if (appUpdateInfo.updateAvailability() ==
- UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS
- ) {
- Timber.d("$TAG:Resuming in-progress update")
- appUpdateManager.startUpdateFlowForResult(
- appUpdateInfo,
- updateResultLauncher,
- AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build(),
- )
- }
-
- if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
- showUpdateDownloadedSnackbar()
- }
- }.addOnFailureListener { exception ->
- Timber.e("$TAG:Failed to get app update info in onResume$exception")
- }
- }
-
- override fun onDestroy() {
- super.onDestroy()
-
- appUpdateManager.unregisterListener(installStateUpdatedListener)
- }
-
- private fun checkForAppUpdate() {
- Timber.d("$TAG:Checking for app updates...")
-
- appUpdateManager.appUpdateInfo
- .addOnSuccessListener { appUpdateInfo ->
- Timber.d("$TAG:Update availability: ${appUpdateInfo.updateAvailability()}")
- Timber.d("$TAG:Update priority: ${appUpdateInfo.updatePriority()}")
- Timber.d(
- "$TAG:Client version staleness days: ${appUpdateInfo.clientVersionStalenessDays()}",
- )
- Timber.d("$TAG:Available version code: ${appUpdateInfo.availableVersionCode()}")
- Timber.d("$TAG:Install status: ${appUpdateInfo.installStatus()}")
-
- when {
- appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE &&
- appUpdateInfo.updatePriority() >= 4 &&
- appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) -> {
- Timber.d("$TAG:Starting immediate update (high priority)")
- startImmediateUpdate(appUpdateInfo)
- }
- appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE &&
- appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE) -> {
- val stalenessDays = appUpdateInfo.clientVersionStalenessDays() ?: 0
- Timber.d("$TAG:Update staleness: $stalenessDays days")
-
- if (stalenessDays >= 1) {
- Timber.d("$TAG:Starting flexible update (staleness criteria met)")
- startFlexibleUpdate(appUpdateInfo)
- } else {
- Timber.d("$TAG:Update available but staleness criteria not met")
- }
- }
- appUpdateInfo.updateAvailability() ==
- UpdateAvailability.UPDATE_AVAILABLE -> {
- Timber.d("$TAG:Update available but no update type allowed")
- Timber.d(
- "$TAG:Immediate allowed: ${appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)}",
- )
- Timber.d(
- "$TAG:Flexible allowed: ${appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)}",
- )
- }
- else -> {
- Timber.d("$TAG:No update available or update not applicable")
- }
- }
- }.addOnFailureListener { exception ->
- Timber.e("$TAG:Failed to check for app updates:$exception")
- }
- }
-
- private fun startImmediateUpdate(appUpdateInfo: AppUpdateInfo) {
- Timber.d("Launching immediate update flow")
- appUpdateManager.startUpdateFlowForResult(
- appUpdateInfo,
- updateResultLauncher,
- AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build(),
- )
- }
-
- private fun startFlexibleUpdate(appUpdateInfo: AppUpdateInfo) {
- Timber.d("Launching flexible update flow")
- appUpdateManager.startUpdateFlowForResult(
- appUpdateInfo,
- updateResultLauncher,
- AppUpdateOptions.newBuilder(AppUpdateType.FLEXIBLE).build(),
- )
- }
-
- private fun showUpdateDownloadedSnackbar() {
- Timber.d("Showing update downloaded snackbar")
- Snackbar
- .make(
- binding.root,
- "An update has been downloaded.",
- Snackbar.LENGTH_INDEFINITE,
- ).apply {
- setAction("RESTART") {
- Timber.d("User clicked restart - completing update")
- appUpdateManager.completeUpdate()
- }
- show()
- }
- }
-
- private fun checkForReviewRequest() {
- val lastReviewRequest = prefs.getLong(PREF_LAST_REVIEW_REQUEST, 0)
- val currentTime = System.currentTimeMillis()
-
- if (currentTime - lastReviewRequest >= REVIEW_INTERVAL_MILLIS) {
- requestReviewInfo()
- }
- }
-
- private fun requestReviewInfo() {
- val request = reviewManager.requestReviewFlow()
- request.addOnCompleteListener { task ->
- if (task.isSuccessful) {
- reviewInfo = task.result
- launchReviewFlow()
- } else {
- Timber.e("$TAG:Failed to request review info:${task.exception}")
- }
- }
- }
-
- private fun launchReviewFlow() {
- reviewInfo?.let { info ->
- val flow = reviewManager.launchReviewFlow(this, info)
- flow.addOnCompleteListener {
- prefs.edit { putLong(PREF_LAST_REVIEW_REQUEST, System.currentTimeMillis()) }
- reviewInfo = null
- }
- }
- }
-}
diff --git a/app/src/main/java/com/dscvit/vitty/activity/InstructionsActivity.kt b/app/src/main/java/com/dscvit/vitty/activity/InstructionsActivity.kt
index 956b9ca..d23fc02 100755
--- a/app/src/main/java/com/dscvit/vitty/activity/InstructionsActivity.kt
+++ b/app/src/main/java/com/dscvit/vitty/activity/InstructionsActivity.kt
@@ -15,15 +15,12 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.edit
import androidx.databinding.DataBindingUtil
-import androidx.lifecycle.ViewModelProvider
import com.dscvit.vitty.BuildConfig
import com.dscvit.vitty.R
import com.dscvit.vitty.databinding.ActivityInstructionsBinding
import com.dscvit.vitty.receiver.AlarmReceiver
-import com.dscvit.vitty.ui.auth.AuthViewModel
import com.dscvit.vitty.util.ArraySaverLoader.loadArray
import com.dscvit.vitty.util.ArraySaverLoader.saveArray
-import com.dscvit.vitty.util.Constants
import com.dscvit.vitty.util.Constants.ALARM_INTENT
import com.dscvit.vitty.util.Constants.EXAM_MODE
import com.dscvit.vitty.util.Constants.GROUP_ID
@@ -44,8 +41,8 @@ import timber.log.Timber
import java.util.Date
class InstructionsActivity : AppCompatActivity() {
+
private lateinit var binding: ActivityInstructionsBinding
- private lateinit var authViewModel: AuthViewModel
private val days =
listOf("monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday")
private lateinit var prefs: SharedPreferences
@@ -57,14 +54,12 @@ class InstructionsActivity : AppCompatActivity() {
binding = DataBindingUtil.setContentView(this, R.layout.activity_instructions)
prefs = getSharedPreferences(USER_INFO, 0)
uid = prefs.getString(UID, "").toString()
- authViewModel = ViewModelProvider(this)[AuthViewModel::class.java]
+
setupToolbar()
setGDSCVITChannel()
binding.doneButton.setOnClickListener {
- val token = prefs.getString(Constants.COMMUNITY_TOKEN, null)
- val username = prefs.getString(Constants.COMMUNITY_USERNAME, null)
- setupDoneButton(token, username)
+ setupDoneButton()
}
}
@@ -72,62 +67,20 @@ class InstructionsActivity : AppCompatActivity() {
super.onStart()
if (prefs.getInt(UPDATE, 0) == 1) {
createNotificationChannels()
- Toast
- .makeText(this, getString(R.string.updated), Toast.LENGTH_SHORT)
+ Toast.makeText(this, getString(R.string.updated), Toast.LENGTH_SHORT)
.show()
}
if (prefs.getInt(TIMETABLE_AVAILABLE, 0) == 1) {
setAlarm()
- val intent = Intent(this, HomeComposeActivity::class.java)
+ val intent = Intent(this, HomeActivity::class.java)
startActivity(intent)
finish()
}
}
- private fun setupDoneButton(
- token: String?,
- username: String?,
- ) {
+ private fun setupDoneButton() {
binding.loadingView.visibility = View.VISIBLE
-
- Timber.d("done button clicked")
-
- if (token != null && username != null) {
- authViewModel.getUserWithTimeTable(token, username)
- } else {
- Toast
- .makeText(this, "Please login again", Toast.LENGTH_LONG)
- .show()
- }
-
- authViewModel.user.observe(this) {
- Timber.d("user: $it")
- if (it != null) {
- val timetableDays = it.timetable?.data
- if (!timetableDays?.Monday.isNullOrEmpty() ||
- !timetableDays?.Tuesday.isNullOrEmpty() ||
- !timetableDays?.Wednesday.isNullOrEmpty() ||
- !timetableDays?.Thursday.isNullOrEmpty() ||
- !timetableDays?.Friday.isNullOrEmpty() ||
- !timetableDays?.Saturday.isNullOrEmpty() ||
- !timetableDays?.Sunday.isNullOrEmpty()
- ) {
- binding.loadingView.visibility = View.GONE
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- createNotificationChannels()
- } else {
- tellUpdated()
- }
- } else {
- binding.loadingView.visibility = View.GONE
- Toast
- .makeText(this, getString(R.string.follow_instructions), Toast.LENGTH_LONG)
- .show()
- }
- }
- }
-
- /*db.collection("users")
+ db.collection("users")
.document(uid)
.get()
.addOnSuccessListener { document ->
@@ -142,7 +95,7 @@ class InstructionsActivity : AppCompatActivity() {
Toast.makeText(this, getString(R.string.follow_instructions), Toast.LENGTH_LONG)
.show()
}
- }*/
+ }
}
private fun createNotificationChannels() {
@@ -156,8 +109,7 @@ class InstructionsActivity : AppCompatActivity() {
}
val newNotifChannels: ArrayList = ArrayList()
for (day in days) {
- db
- .collection("users")
+ db.collection("users")
.document(uid)
.collection("timetable")
.document(day)
@@ -172,17 +124,17 @@ class InstructionsActivity : AppCompatActivity() {
this,
cn,
"Course Code: $cc",
- GROUP_ID,
+ GROUP_ID
)
newNotifChannels.add(cn)
Timber.d(cn)
}
saveArray(newNotifChannels, NOTIFICATION_CHANNELS, this)
- if (day == "sunday") {
+ if (day == "sunday")
tellUpdated()
- }
- }.addOnFailureListener { e ->
+ }
+ .addOnFailureListener { e ->
Timber.d("Error: $e")
}
}
@@ -191,13 +143,11 @@ class InstructionsActivity : AppCompatActivity() {
private fun tellUpdated() {
prefs.edit().putInt(TIMETABLE_AVAILABLE, 1).apply()
prefs.edit().putInt(UPDATE, 0).apply()
- val updated =
- hashMapOf(
- "isTimetableAvailable" to true,
- "isUpdated" to false,
- )
- db
- .collection("users")
+ val updated = hashMapOf(
+ "isTimetableAvailable" to true,
+ "isUpdated" to false
+ )
+ db.collection("users")
.document(uid)
.set(updated)
.addOnSuccessListener {
@@ -205,21 +155,21 @@ class InstructionsActivity : AppCompatActivity() {
UtilFunctions.reloadWidgets(this)
val pm: PowerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
- Toast
- .makeText(
- this,
- "Please turn off the Battery Optimization Settings for VITTY to receive notifications on time.",
- Toast.LENGTH_LONG,
- ).show()
+ Toast.makeText(
+ this,
+ "Please turn off the Battery Optimization Settings for VITTY to receive notifications on time.",
+ Toast.LENGTH_LONG
+ ).show()
val pmIntent = Intent()
pmIntent.action = Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
startActivity(pmIntent)
} else {
- val intent = Intent(this, HomeComposeActivity::class.java)
+ val intent = Intent(this, HomeActivity::class.java)
startActivity(intent)
finish()
}
- }.addOnFailureListener { e ->
+ }
+ .addOnFailureListener { e ->
Timber.d("Error: $e")
}
}
@@ -229,13 +179,13 @@ class InstructionsActivity : AppCompatActivity() {
NotificationHelper.createNotificationGroup(
this,
getString(R.string.gdscvit),
- GROUP_ID_2,
+ GROUP_ID_2
)
NotificationHelper.createNotificationChannel(
this,
getString(R.string.default_notification_channel_name),
"Notifications from GDSC VIT",
- GROUP_ID_2,
+ GROUP_ID_2
)
prefs.edit {
putBoolean("gdscvitChannelCreated", true)
@@ -249,7 +199,7 @@ class InstructionsActivity : AppCompatActivity() {
NotificationHelper.createNotificationGroup(
this,
getString(R.string.notif_group),
- GROUP_ID,
+ GROUP_ID
)
prefs.edit {
putBoolean("groupCreated", true)
@@ -265,10 +215,8 @@ class InstructionsActivity : AppCompatActivity() {
val pendingIntent =
PendingIntent.getBroadcast(
- this,
- ALARM_INTENT,
- intent,
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
+ this, ALARM_INTENT, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
@@ -278,7 +226,7 @@ class InstructionsActivity : AppCompatActivity() {
AlarmManager.RTC_WAKEUP,
date,
(1000 * 60 * NOTIF_DELAY).toLong(),
- pendingIntent,
+ pendingIntent
)
prefs.edit {
@@ -296,7 +244,6 @@ class InstructionsActivity : AppCompatActivity() {
LogoutHelper.logout(this, this as Activity, prefs)
true
}
-
else -> false
}
}
diff --git a/app/src/main/java/com/dscvit/vitty/activity/MaintenanceActivity.kt b/app/src/main/java/com/dscvit/vitty/activity/MaintenanceActivity.kt
deleted file mode 100644
index 1b4fef1..0000000
--- a/app/src/main/java/com/dscvit/vitty/activity/MaintenanceActivity.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.dscvit.vitty.activity
-
-import android.content.Intent
-import android.os.Bundle
-import androidx.compose.ui.platform.ViewCompositionStrategy
-import androidx.databinding.DataBindingUtil
-import androidx.fragment.app.FragmentActivity
-import com.dscvit.vitty.R
-import com.dscvit.vitty.databinding.ActivityMaintenanceBinding
-import com.dscvit.vitty.theme.VittyTheme
-import com.dscvit.vitty.ui.maintenance.MaintenanceScreen
-import com.dscvit.vitty.util.MaintenanceChecker
-
-class MaintenanceActivity : FragmentActivity() {
-
- private lateinit var binding: ActivityMaintenanceBinding
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- binding = DataBindingUtil.setContentView(this, R.layout.activity_maintenance)
-
- binding.composeView.apply {
- setViewCompositionStrategy(
- ViewCompositionStrategy.DisposeOnLifecycleDestroyed(this@MaintenanceActivity)
- )
- setContent {
- VittyTheme {
- MaintenanceScreen(
- onRetryClick = { retryConnection() },
- onExitClick = { exitApp() }
- )
- }
- }
- }
- }
-
- private fun retryConnection() {
- MaintenanceChecker.checkMaintenanceStatusAsync(this) { isUnderMaintenance ->
- if (!isUnderMaintenance) {
- val intent = Intent(this, InstructionsActivity::class.java)
- intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
- startActivity(intent)
- finish()
- }
- }
- }
-
- private fun exitApp() {
- finishAffinity()
- }
-}
diff --git a/app/src/main/java/com/dscvit/vitty/activity/SettingsActivity.kt b/app/src/main/java/com/dscvit/vitty/activity/SettingsActivity.kt
index bcd4d4b..6292018 100755
--- a/app/src/main/java/com/dscvit/vitty/activity/SettingsActivity.kt
+++ b/app/src/main/java/com/dscvit/vitty/activity/SettingsActivity.kt
@@ -40,7 +40,6 @@ class SettingsActivity : AppCompatActivity() {
onBackPressed()
true
}
-
else -> false
}
}
diff --git a/app/src/main/java/com/dscvit/vitty/activity/VITEventsActivity.kt b/app/src/main/java/com/dscvit/vitty/activity/VITEventsActivity.kt
index 1cb120a..b91f085 100644
--- a/app/src/main/java/com/dscvit/vitty/activity/VITEventsActivity.kt
+++ b/app/src/main/java/com/dscvit/vitty/activity/VITEventsActivity.kt
@@ -41,7 +41,6 @@ class VITEventsActivity : AppCompatActivity() {
onBackPressed()
true
}
-
else -> false
}
}
diff --git a/app/src/main/java/com/dscvit/vitty/adapter/DayAdapter.kt b/app/src/main/java/com/dscvit/vitty/adapter/DayAdapter.kt
index dcc0370..bd7f139 100755
--- a/app/src/main/java/com/dscvit/vitty/adapter/DayAdapter.kt
+++ b/app/src/main/java/com/dscvit/vitty/adapter/DayAdapter.kt
@@ -5,7 +5,7 @@ import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.dscvit.vitty.ui.schedule.DayFragment
-class DayAdapter(fa: Fragment, private val username: String?, private val isFriendsTimetable: Boolean = false) : FragmentStateAdapter(fa) {
+class DayAdapter(fa: Fragment) : FragmentStateAdapter(fa) {
private val numPages = 7
override fun getItemCount(): Int = numPages
@@ -13,8 +13,6 @@ class DayAdapter(fa: Fragment, private val username: String?, private val isFrie
override fun createFragment(position: Int): Fragment {
val bundle = Bundle()
bundle.putString("frag_id", position.toString())
- bundle.putString("username", username)
- bundle.putBoolean("isFriendsTimetable", isFriendsTimetable)
val fragment = DayFragment()
fragment.arguments = bundle
return fragment
diff --git a/app/src/main/java/com/dscvit/vitty/adapter/EventAdapter.kt b/app/src/main/java/com/dscvit/vitty/adapter/EventAdapter.kt
index 9d49995..0ba0191 100644
--- a/app/src/main/java/com/dscvit/vitty/adapter/EventAdapter.kt
+++ b/app/src/main/java/com/dscvit/vitty/adapter/EventAdapter.kt
@@ -27,12 +27,8 @@ class EventAdapter(private val dataSet: List) :
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
- val date: Date = SimpleDateFormat(
- "hh:mm z",
- Locale.getDefault()
- ).parse("${dataSet[position].Time} IST") as Date
- val time: String =
- SimpleDateFormat("h:mm a", Locale.getDefault()).format(date).uppercase(Locale.ROOT)
+ val date: Date = SimpleDateFormat("hh:mm z", Locale.getDefault()).parse("${dataSet[position].Time} IST") as Date
+ val time: String = SimpleDateFormat("h:mm a", Locale.getDefault()).format(date).uppercase(Locale.ROOT)
viewHolder.eventName.text = dataSet[position].EventName
viewHolder.eventTime.text = time
}
diff --git a/app/src/main/java/com/dscvit/vitty/adapter/FriendAdapter.kt b/app/src/main/java/com/dscvit/vitty/adapter/FriendAdapter.kt
deleted file mode 100644
index af8e94f..0000000
--- a/app/src/main/java/com/dscvit/vitty/adapter/FriendAdapter.kt
+++ /dev/null
@@ -1,171 +0,0 @@
-package com.dscvit.vitty.adapter
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.databinding.DataBindingUtil
-import androidx.navigation.findNavController
-import androidx.recyclerview.widget.RecyclerView
-import coil.load
-import com.dscvit.vitty.R
-import com.dscvit.vitty.databinding.CardFriendBinding
-import com.dscvit.vitty.network.api.community.responses.user.UserResponse
-import com.dscvit.vitty.util.Effects.vibrateOnClick
-import timber.log.Timber
-
-class FriendAdapter(
- dataList: List,
- private val pinnedFriendAdapterListener: PinnedFriendAdapterListener
-) :
- RecyclerView.Adapter() {
-
-
- private val dataSet = pinFriendsOnTop(dataList).toMutableList()
-
- class ViewHolder(private val binding: CardFriendBinding) :
- RecyclerView.ViewHolder(binding.root) {
- val friend_name = binding.friendName
- val friend_class = binding.friendClass
- val friend_status = binding.friendStatus
- val friend_image = binding.icon
- val pin = binding.pin
-
- fun bind(data: UserResponse) {
- binding.friendDetails = data
- }
- }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- return ViewHolder(
- DataBindingUtil.inflate(
- LayoutInflater.from(parent.context),
- R.layout.card_friend,
- parent,
- false
- )
- )
- }
-
- override fun onBindViewHolder(holder: ViewHolder, position: Int) {
- val item = dataSet[holder.adapterPosition]
- holder.bind(item)
-
-
- /* val startTime: Date = item.startTime.toDate()
- val simpleDateFormat = SimpleDateFormat("h:mm a", Locale.getDefault())
- val sTime: String = simpleDateFormat.format(startTime).uppercase(Locale.ROOT)
-
- val endTime: Date = item.endTime.toDate()
- val eTime: String = simpleDateFormat.format(endTime).uppercase(Locale.ROOT)*/
-
- /*val now = Calendar.getInstance()
- val s = Calendar.getInstance()
- s.time = startTime
- val start = Calendar.getInstance()
- start[Calendar.HOUR_OF_DAY] = s[Calendar.HOUR_OF_DAY]
- start[Calendar.MINUTE] = s[Calendar.MINUTE]
- val e = Calendar.getInstance()
- e.time = endTime
- val end = Calendar.getInstance()
- end[Calendar.HOUR_OF_DAY] = e[Calendar.HOUR_OF_DAY]
- end[Calendar.MINUTE] = e[Calendar.MINUTE]*/
-
- holder.friend_status.text = item.current_status?.venue ?: "Free"
- val status = item.current_status?.status
- val course = item.current_status?.`class`
-
- holder.friend_class.text =
- if (status == null || status.lowercase() == "free" || status.lowercase() == "unknown") {
- "Not in a class right now"
- } else {
- "$course"
- }
- val pinnedFriends = pinnedFriendAdapterListener.getPinnedFriends()
- if (pinnedFriends.contains(item.username)) {
- holder.pin.visibility = View.VISIBLE
- } else {
- holder.pin.visibility = View.GONE
- }
-
- holder.friend_image.load(item.picture) {
- crossfade(true)
- placeholder(R.drawable.ic_gdscvit)
- error(R.drawable.ic_gdscvit)
- }
-
- holder.itemView.apply {
- setOnClickListener {
- val bundle = Bundle()
- bundle.putString("username", item.username)
- bundle.putString("name", item.name)
- bundle.putString("profile_picture", item.picture)
- bundle.putString("friend_status", item.friend_status)
-
- findNavController().navigate(
- R.id.action_navigation_community_to_friendFragment,
- bundle
- )
- }
- }
-
- holder.itemView.apply {
- setOnLongClickListener {
- vibrateOnClick(context)
- val updatedPinnedFriends = pinnedFriendAdapterListener.getPinnedFriends()
- if (updatedPinnedFriends.contains(item.username)) {
- if (pinnedFriendAdapterListener.unPinFriend(item.username)) {
- holder.pin.visibility = View.GONE
- notifyItemMoved(
- holder.adapterPosition,
- pinnedFriendAdapterListener.getPinnedFriends().size
- )
- Timber.d("Pinned Friends: ${pinnedFriendAdapterListener.getPinnedFriends()}")
- }
- } else {
- if (pinnedFriendAdapterListener.pinFriend(item.username)) {
- holder.pin.visibility = View.VISIBLE
- notifyItemMoved(holder.adapterPosition, updatedPinnedFriends.size)
- Timber.d("Pinned Friends: ${pinnedFriendAdapterListener.getPinnedFriends()}")
- }
-
- }
- true
- }
- }
-
-
- }
-
- override fun getItemCount() = dataSet.size
-
- private fun pinFriendsOnTop(dataSet: List): List {
- val pinnedFriends = pinnedFriendAdapterListener.getPinnedFriends()
- val pinnedFriendsList = mutableListOf()
- val otherFriendsList = mutableListOf()
- for (i in pinnedFriends) {
- for (j in dataSet) {
- if (i == j.username) {
- pinnedFriendsList.add(j)
- continue
- }
- }
- }
- for (i in dataSet) {
- if (!pinnedFriends.contains(i.username)) {
- pinnedFriendsList.add(i)
- }
- }
-
- return pinnedFriendsList + otherFriendsList
- }
-}
-
-
-interface PinnedFriendAdapterListener {
- fun pinFriend(username: String): Boolean
-
- fun unPinFriend(username: String): Boolean
-
- fun getPinnedFriends(): List
-}
diff --git a/app/src/main/java/com/dscvit/vitty/adapter/PeriodAdapter.kt b/app/src/main/java/com/dscvit/vitty/adapter/PeriodAdapter.kt
index 0e54fee..761e008 100755
--- a/app/src/main/java/com/dscvit/vitty/adapter/PeriodAdapter.kt
+++ b/app/src/main/java/com/dscvit/vitty/adapter/PeriodAdapter.kt
@@ -3,7 +3,6 @@ package com.dscvit.vitty.adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.core.content.ContextCompat
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.RecyclerView
import com.dscvit.vitty.R
@@ -18,44 +17,42 @@ import java.util.Calendar
import java.util.Date
import java.util.Locale
-class PeriodAdapter(
- private val dataSet: ArrayList,
- private val day: Int,
-) : RecyclerView.Adapter() {
+class PeriodAdapter(private val dataSet: ArrayList, private val day: Int) :
+ RecyclerView.Adapter() {
+
+ private var previousExpandedPosition = -1
+ private var mExpandedPosition = -1
private var active = -1
- class ViewHolder(
- private val binding: CardPeriodBinding,
- ) : RecyclerView.ViewHolder(binding.root) {
+ class ViewHolder(private val binding: CardPeriodBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+ val arrow = binding.arrowMoreInfo
+ val moreInfo = binding.moreInfo
+ val expandedBackground = binding.expandedBackground
val activePeriod = binding.activePeriod
val periodTime = binding.periodTime
val classNav = binding.classNav
val classIdOnline = binding.classIdOnline
- val periodCard = binding.periodCard
+ // val courseCode = binding.courseCode
fun bind(data: PeriodDetails) {
binding.periodDetails = data
}
}
- override fun onCreateViewHolder(
- parent: ViewGroup,
- viewType: Int,
- ): ViewHolder =
- ViewHolder(
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ return ViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.card_period,
parent,
- false,
- ),
+ false
+ )
)
+ }
- override fun onBindViewHolder(
- holder: ViewHolder,
- position: Int,
- ) {
- val item = dataSet[holder.adapterPosition]
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val item = dataSet[position]
holder.bind(item)
val startTime: Date = item.startTime.toDate()
@@ -88,10 +85,8 @@ class PeriodAdapter(
}
holder.apply {
- periodTime.text = "$sTime - $eTime | ${item.slot}"
+ periodTime.text = "$sTime - $eTime"
activePeriod.visibility = View.INVISIBLE
- periodCard.strokeWidth = 0
-
classNav.apply {
setOnClickListener {
VITMap.openClassMap(classNav.context, item.roomNo)
@@ -101,7 +96,7 @@ class PeriodAdapter(
context,
"Room Number",
"ROOM_NUMBER_ITEM",
- item.roomNo,
+ item.roomNo
)
true
}
@@ -109,26 +104,46 @@ class PeriodAdapter(
}
if ((((day + 1) % 7) + 1) == now[Calendar.DAY_OF_WEEK]) {
- if ((start.before(now) && end.after(now)) ||
- start.equals(now) ||
- (start.after(now) && active == -1) ||
- active == holder.adapterPosition
- ) {
+ if ((start.before(now) && end.after(now)) || start.equals(now) || (start.after(now) && active == -1) || active == position) {
holder.activePeriod.visibility = View.VISIBLE
- holder.periodCard.strokeWidth = 2
- holder.periodCard.strokeColor = ContextCompat.getColor(holder.itemView.context, R.color.translucent)
- active = holder.adapterPosition
+ active = position
}
}
+ val isExpanded = position == mExpandedPosition
+ holder.apply {
+ if (isExpanded) {
+ expandedBackground.visibility = View.VISIBLE
+ moreInfo.visibility = View.VISIBLE
+// courseCode.visibility = View.VISIBLE
+ arrow.rotation = 180F
+ } else {
+ moreInfo.visibility = View.GONE
+ expandedBackground.visibility = View.GONE
+// courseCode.visibility = View.GONE
+ arrow.rotation = 0F
+ }
+ itemView.isActivated = isExpanded
+ }
+
+ if (isExpanded) previousExpandedPosition = position
+
holder.itemView.apply {
setOnClickListener {
vibrateOnClick(holder.itemView.context)
+ mExpandedPosition = if (isExpanded) -1 else position
+ notifyItemChanged(previousExpandedPosition)
+ notifyItemChanged(position)
}
setOnLongClickListener {
+ mExpandedPosition = position
+ notifyItemChanged(previousExpandedPosition)
+ notifyItemChanged(position)
true
}
}
+
+
}
override fun getItemCount() = dataSet.size
diff --git a/app/src/main/java/com/dscvit/vitty/adapter/SearchAdapter.kt b/app/src/main/java/com/dscvit/vitty/adapter/SearchAdapter.kt
deleted file mode 100644
index 23efe31..0000000
--- a/app/src/main/java/com/dscvit/vitty/adapter/SearchAdapter.kt
+++ /dev/null
@@ -1,191 +0,0 @@
-package com.dscvit.vitty.adapter
-
-import android.annotation.SuppressLint
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.Button
-import android.widget.TextView
-import androidx.appcompat.content.res.AppCompatResources
-import androidx.databinding.DataBindingUtil
-import androidx.navigation.findNavController
-import androidx.recyclerview.widget.RecyclerView
-import coil.load
-import com.dscvit.vitty.R
-import com.dscvit.vitty.databinding.CardRequestBinding
-import com.dscvit.vitty.network.api.community.responses.user.UserResponse
-import com.dscvit.vitty.ui.community.CommunityViewModel
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-
-class SearchAdapter(
- dataSet: List,
- private val token: String,
- private val communityViewModel: CommunityViewModel,
- private val isSearchMode: Boolean,
- private val isAllReqPage: Boolean
-) :
- RecyclerView.Adapter() {
-
- private val mutableDataSet = dataSet.toMutableList()
-
- class ViewHolder(private val binding: CardRequestBinding) :
- RecyclerView.ViewHolder(binding.root) {
- val name = binding.name
- val actionLayout = binding.actionLayout
- val pendingRequestLayout = binding.acceptRejectLayout
- val sendRequestLayout = binding.sendRequestLayout
- val sentLayout = binding.sentLayout
- val accept = binding.accept
- val reject = binding.reject
- val sendRequest = binding.sendRequest
- val image = binding.icon
- val username = binding.username
- fun bind(data: UserResponse) {
- binding.personDetails = data
- }
- }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- return ViewHolder(
- DataBindingUtil.inflate(
- LayoutInflater.from(parent.context),
- R.layout.card_request,
- parent,
- false
- )
- )
- }
-
- @SuppressLint("SetTextI18n")
- override fun onBindViewHolder(holder: ViewHolder, position: Int) {
- val item = mutableDataSet[holder.adapterPosition]
- holder.bind(item)
-
- if (isSearchMode) {
- holder.actionLayout.visibility = View.GONE
- }
- when (item.friend_status) {
- "received" -> {
- holder.pendingRequestLayout.visibility = View.VISIBLE
- holder.sendRequestLayout.visibility = View.GONE
- holder.sentLayout.visibility = View.GONE
- }
-
- "sent" -> {
- holder.pendingRequestLayout.visibility = View.GONE
- holder.sendRequestLayout.visibility = View.GONE
- holder.sentLayout.visibility = View.VISIBLE
- }
-
- else -> {
- holder.pendingRequestLayout.visibility = View.GONE
- holder.sendRequestLayout.visibility = View.VISIBLE
- holder.sentLayout.visibility = View.GONE
- }
- }
-
- holder.image.load(item.picture) {
- crossfade(true)
- placeholder(R.drawable.ic_gdscvit)
- error(R.drawable.ic_gdscvit)
- }
-
-
- holder.accept.apply {
- setOnClickListener {
- communityViewModel.acceptRequest(token, item.username)
- mutableDataSet.removeAt(holder.adapterPosition)
- notifyItemRemoved(holder.adapterPosition)
- notifyItemRangeChanged(holder.adapterPosition, mutableDataSet.size)
- }
- }
-
- holder.reject.apply {
- setOnClickListener {
-
- val v: View = LayoutInflater
- .from(context)
- .inflate(R.layout.dialog_setup_complete, null)
- val dialog = MaterialAlertDialogBuilder(context)
- .setView(v)
- .setBackground(
- AppCompatResources.getDrawable(
- context,
- R.color.transparent
- )
- )
- .create()
- dialog.setCanceledOnTouchOutside(true)
- dialog.show()
-
- val skip = v.findViewById(R.id.skip)
- val next = v.findViewById(R.id.next)
- val title = v.findViewById(R.id.title)
- val desc = v.findViewById(R.id.description)
-
- title.text = "Reject Request"
- desc.text = "Are you sure you want to reject this request?"
- skip.text = "Cancel"
- next.text = "Reject"
-
- skip.setOnClickListener {
- dialog.dismiss()
- }
-
- next.setOnClickListener {
- communityViewModel.rejectRequest(token, item.username)
- mutableDataSet.removeAt(holder.adapterPosition)
- notifyItemRemoved(holder.adapterPosition)
- notifyItemRangeChanged(holder.adapterPosition, mutableDataSet.size)
- dialog.dismiss()
- }
-
- }
- }
-
- holder.sendRequest.apply {
- setOnClickListener {
- holder.sendRequestLayout.visibility = View.GONE
- holder.sentLayout.visibility = View.VISIBLE
- communityViewModel.sendRequest(token, item.username)
- }
- }
-
-
-
- holder.itemView.apply {
- setOnClickListener {
- val bundle = Bundle()
- bundle.putString("username", item.username)
- bundle.putString("name", item.name)
- bundle.putString("profile_picture", item.picture)
- bundle.putString("friend_status", item.friend_status)
-
- if (isSearchMode) {
- findNavController().navigate(
- R.id.action_searchFragment_to_friendFragment,
- bundle
- )
- } else if (isAllReqPage) {
- findNavController().navigate(
- R.id.action_allRequestFragment_to_friendFragment,
- bundle
- )
- } else {
- findNavController().navigate(
- R.id.action_navigation_requests_to_friendFragment,
- bundle
- )
- }
- }
-
- }
-
-
- }
-
- override fun getItemCount() = mutableDataSet.size
-
-}
-
diff --git a/app/src/main/java/com/dscvit/vitty/network/api/events/APIEvents.kt b/app/src/main/java/com/dscvit/vitty/api/APIEvents.kt
similarity index 88%
rename from app/src/main/java/com/dscvit/vitty/network/api/events/APIEvents.kt
rename to app/src/main/java/com/dscvit/vitty/api/APIEvents.kt
index 68b4834..3f02fdc 100644
--- a/app/src/main/java/com/dscvit/vitty/network/api/events/APIEvents.kt
+++ b/app/src/main/java/com/dscvit/vitty/api/APIEvents.kt
@@ -1,10 +1,8 @@
-package com.dscvit.vitty.network.api.events
-
+package com.dscvit.vitty.api
import com.dscvit.vitty.model.EventDetails
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.QueryMap
-
/**
* API for getting User list from https://reqres.in/api/users?&page=1
*/
@@ -12,6 +10,4 @@ interface APIEvents {
// https://reqres.in/api/users?page=1
@GET("event?")
fun getEvents(@QueryMap options: Map): Call
-
-
}
diff --git a/app/src/main/java/com/dscvit/vitty/network/api/events/ApiEventRestClient.kt b/app/src/main/java/com/dscvit/vitty/api/ApiEventRestClient.kt
similarity index 96%
rename from app/src/main/java/com/dscvit/vitty/network/api/events/ApiEventRestClient.kt
rename to app/src/main/java/com/dscvit/vitty/api/ApiEventRestClient.kt
index efc1cde..08b7b00 100644
--- a/app/src/main/java/com/dscvit/vitty/network/api/events/ApiEventRestClient.kt
+++ b/app/src/main/java/com/dscvit/vitty/api/ApiEventRestClient.kt
@@ -1,4 +1,4 @@
-package com.dscvit.vitty.network.api.events
+package com.dscvit.vitty.api
import com.dscvit.vitty.model.EventDetails
import retrofit2.Call
@@ -33,7 +33,6 @@ class ApiEventRestClient {
retrofitEventListener.onSuccess(call, response.body())
}
}
-
override fun onFailure(call: Call, t: Throwable) {
retrofitEventListener.onError(call, t)
}
diff --git a/app/src/main/java/com/dscvit/vitty/network/api/events/NetworkClient.kt b/app/src/main/java/com/dscvit/vitty/api/NetworkClient.kt
similarity index 73%
rename from app/src/main/java/com/dscvit/vitty/network/api/events/NetworkClient.kt
rename to app/src/main/java/com/dscvit/vitty/api/NetworkClient.kt
index d601c73..89f6a22 100644
--- a/app/src/main/java/com/dscvit/vitty/network/api/events/NetworkClient.kt
+++ b/app/src/main/java/com/dscvit/vitty/api/NetworkClient.kt
@@ -1,7 +1,7 @@
-package com.dscvit.vitty.network.api.events
+package com.dscvit.vitty.api
-import com.dscvit.vitty.util.WebConstants.COMMUNITY_BASE_URL
-import com.dscvit.vitty.util.WebConstants.TIMEOUT
+import com.dscvit.vitty.util.APIConstants.BASE_URL
+import com.dscvit.vitty.util.APIConstants.TIMEOUT
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
@@ -9,7 +9,7 @@ import java.util.concurrent.TimeUnit
object NetworkClient {
- private var retrofit: Retrofit? = null
+ var retrofit: Retrofit? = null
val retrofitClient: Retrofit
get() {
@@ -17,7 +17,7 @@ object NetworkClient {
val okHttpClientBuilder = OkHttpClient.Builder()
okHttpClientBuilder.connectTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS)
retrofit = Retrofit.Builder()
- .baseUrl(COMMUNITY_BASE_URL)
+ .baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClientBuilder.build())
.build()
diff --git a/app/src/main/java/com/dscvit/vitty/network/api/events/RetrofitEventListener.kt b/app/src/main/java/com/dscvit/vitty/api/RetrofitEventListener.kt
similarity index 83%
rename from app/src/main/java/com/dscvit/vitty/network/api/events/RetrofitEventListener.kt
rename to app/src/main/java/com/dscvit/vitty/api/RetrofitEventListener.kt
index a2935a4..cb76aec 100644
--- a/app/src/main/java/com/dscvit/vitty/network/api/events/RetrofitEventListener.kt
+++ b/app/src/main/java/com/dscvit/vitty/api/RetrofitEventListener.kt
@@ -1,4 +1,4 @@
-package com.dscvit.vitty.network.api.events
+package com.dscvit.vitty.api
import com.dscvit.vitty.model.EventDetails
import retrofit2.Call
@@ -7,4 +7,3 @@ interface RetrofitEventListener {
fun onSuccess(call: Call?, response: EventDetails?)
fun onError(call: Call?, t: Throwable?)
}
-
diff --git a/app/src/main/java/com/dscvit/vitty/data/converter/Converters.kt b/app/src/main/java/com/dscvit/vitty/data/converter/Converters.kt
deleted file mode 100644
index 715e212..0000000
--- a/app/src/main/java/com/dscvit/vitty/data/converter/Converters.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.dscvit.vitty.data.converter
-
-import androidx.room.TypeConverter
-import com.dscvit.vitty.ui.coursepage.models.NoteType
-
-class Converters {
- @TypeConverter
- fun fromNoteType(noteType: NoteType): String = noteType.name
-
- @TypeConverter
- fun toNoteType(noteType: String): NoteType = NoteType.valueOf(noteType)
-}
diff --git a/app/src/main/java/com/dscvit/vitty/data/dao/NoteDao.kt b/app/src/main/java/com/dscvit/vitty/data/dao/NoteDao.kt
deleted file mode 100644
index c224ce5..0000000
--- a/app/src/main/java/com/dscvit/vitty/data/dao/NoteDao.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.dscvit.vitty.data.dao
-
-import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
-import androidx.room.Query
-import androidx.room.Update
-import com.dscvit.vitty.data.entity.NoteEntity
-import kotlinx.coroutines.flow.Flow
-
-@Dao
-interface NoteDao {
- @Query("SELECT * FROM notes WHERE courseId = :courseId ORDER BY createdAt DESC")
- fun getNotesByCourse(courseId: String): Flow>
-
- @Query("SELECT * FROM notes WHERE courseId = :courseId AND isStarred = 1 ORDER BY createdAt DESC")
- fun getStarredNotesByCourse(courseId: String): Flow>
-
- @Query("SELECT * FROM notes WHERE id = :noteId")
- suspend fun getNoteById(noteId: Long): NoteEntity?
-
- @Insert
- suspend fun insertNote(note: NoteEntity): Long
-
- @Update
- suspend fun updateNote(note: NoteEntity)
-
- @Delete
- suspend fun deleteNote(note: NoteEntity)
-
- @Query("DELETE FROM notes WHERE courseId = :courseId")
- suspend fun deleteNotesByCourse(courseId: String)
-
- @Query("UPDATE notes SET isStarred = :isStarred WHERE id = :noteId")
- suspend fun updateStarredStatus(
- noteId: Long,
- isStarred: Boolean,
- )
-
- @Query(
- "SELECT * FROM notes WHERE courseId = :courseId AND (title LIKE '%' || :query || '%' OR content LIKE '%' || :query || '%') ORDER BY createdAt DESC",
- )
- fun searchNotes(
- courseId: String,
- query: String,
- ): Flow>
-}
diff --git a/app/src/main/java/com/dscvit/vitty/data/dao/ReminderDao.kt b/app/src/main/java/com/dscvit/vitty/data/dao/ReminderDao.kt
deleted file mode 100644
index 2a5fe0d..0000000
--- a/app/src/main/java/com/dscvit/vitty/data/dao/ReminderDao.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.dscvit.vitty.data.dao
-import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
-import androidx.room.Query
-import androidx.room.Update
-import com.dscvit.vitty.data.entity.ReminderEntity
-import kotlinx.coroutines.flow.Flow
-
-@Dao
-interface ReminderDao {
- @Query("SELECT * FROM reminders WHERE courseId = :courseId ORDER BY dateMillis ASC")
- fun getRemindersByCourse(courseId: String): Flow>
-
- @Query("SELECT * FROM reminders ORDER BY dateMillis ASC")
- fun getAllReminders(): Flow>
-
- @Query("SELECT * FROM reminders WHERE id = :id")
- suspend fun getReminderById(id: Long): ReminderEntity?
-
- @Query("SELECT * FROM reminders WHERE dateMillis >= :startTime AND dateMillis <= :endTime AND isCompleted = 0")
- suspend fun getRemindersInRange(
- startTime: Long,
- endTime: Long,
- ): List
-
- @Insert
- suspend fun insertReminder(reminder: ReminderEntity): Long
-
- @Update
- suspend fun updateReminder(reminder: ReminderEntity)
-
- @Delete
- suspend fun deleteReminder(reminder: ReminderEntity)
-
- @Query("DELETE FROM reminders WHERE courseId = :courseId")
- suspend fun deleteRemindersByCourse(courseId: String)
-
- @Query("UPDATE reminders SET isCompleted = :isCompleted WHERE id = :id")
- suspend fun updateCompletedStatus(
- id: Long,
- isCompleted: Boolean,
- )
-
- @Query("SELECT * FROM reminders WHERE isCompleted = 0 ORDER BY dateMillis ASC")
- suspend fun getAllPendingReminders(): List
-}
diff --git a/app/src/main/java/com/dscvit/vitty/data/database/VittyDatabase.kt b/app/src/main/java/com/dscvit/vitty/data/database/VittyDatabase.kt
deleted file mode 100644
index 1a5f3d2..0000000
--- a/app/src/main/java/com/dscvit/vitty/data/database/VittyDatabase.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.dscvit.vitty.data.database
-
-import android.content.Context
-import androidx.room.Database
-import androidx.room.Room
-import androidx.room.RoomDatabase
-import androidx.room.TypeConverters
-import com.dscvit.vitty.data.converter.Converters
-import com.dscvit.vitty.data.dao.NoteDao
-import com.dscvit.vitty.data.dao.ReminderDao
-import com.dscvit.vitty.data.entity.NoteEntity
-import com.dscvit.vitty.data.entity.ReminderEntity
-
-@Database(
- entities = [NoteEntity::class, ReminderEntity::class],
- version = 3,
- exportSchema = false,
-)
-@TypeConverters(Converters::class)
-abstract class VittyDatabase : RoomDatabase() {
- abstract fun noteDao(): NoteDao
- abstract fun reminderDao(): ReminderDao
-
- companion object {
- @Volatile
- private var _instance: VittyDatabase? = null
-
- fun getDatabase(context: Context): VittyDatabase =
- _instance ?: synchronized(this) {
- val instance =
- Room
- .databaseBuilder(
- context.applicationContext,
- VittyDatabase::class.java,
- "vitty_database",
- )
- .fallbackToDestructiveMigration(true)
- .build()
- _instance = instance
- instance
- }
- }
-}
diff --git a/app/src/main/java/com/dscvit/vitty/data/entity/NoteEntity.kt b/app/src/main/java/com/dscvit/vitty/data/entity/NoteEntity.kt
deleted file mode 100644
index aeec5f6..0000000
--- a/app/src/main/java/com/dscvit/vitty/data/entity/NoteEntity.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.dscvit.vitty.data.entity
-
-import androidx.room.Entity
-import androidx.room.PrimaryKey
-import com.dscvit.vitty.ui.coursepage.models.NoteType
-
-@Entity(tableName = "notes")
-data class NoteEntity(
- @PrimaryKey(autoGenerate = true)
- val id: Long = 0,
- val courseId: String,
- val title: String,
- val content: String,
- val type: NoteType,
- val isStarred: Boolean = false,
- val imagePath: String? = null,
- val createdAt: Long = System.currentTimeMillis(),
- val updatedAt: Long = System.currentTimeMillis(),
-)
diff --git a/app/src/main/java/com/dscvit/vitty/data/entity/ReminderEntity.kt b/app/src/main/java/com/dscvit/vitty/data/entity/ReminderEntity.kt
deleted file mode 100644
index 7bd249a..0000000
--- a/app/src/main/java/com/dscvit/vitty/data/entity/ReminderEntity.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.dscvit.vitty.data.entity
-
-import androidx.room.Entity
-import androidx.room.PrimaryKey
-
-@Entity(tableName = "reminders")
-data class ReminderEntity(
- @PrimaryKey(autoGenerate = true)
- val id: Long = 0,
- val courseId: String,
- val courseTitle: String,
- val title: String,
- val description: String,
- val dateMillis: Long,
- val fromTimeHour: Int,
- val fromTimeMinute: Int,
- val toTimeHour: Int,
- val toTimeMinute: Int,
- val isAllDay: Boolean,
- val alertDaysBefore: Int,
- val attachmentUrl: String? = null,
- val isCompleted: Boolean = false,
- val createdAt: Long = System.currentTimeMillis(),
- val updatedAt: Long = System.currentTimeMillis()
-)
diff --git a/app/src/main/java/com/dscvit/vitty/data/repository/NoteRepository.kt b/app/src/main/java/com/dscvit/vitty/data/repository/NoteRepository.kt
deleted file mode 100644
index 6587176..0000000
--- a/app/src/main/java/com/dscvit/vitty/data/repository/NoteRepository.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.dscvit.vitty.data.repository
-
-import com.dscvit.vitty.data.dao.NoteDao
-import com.dscvit.vitty.data.entity.NoteEntity
-import com.dscvit.vitty.ui.coursepage.models.Note
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
-
-class NoteRepository(
- private val noteDao: NoteDao,
-) {
- fun getNotesByCourse(courseId: String): Flow> =
- noteDao.getNotesByCourse(courseId).map { entities ->
- entities.map { it.toNote() }
- }
-
- suspend fun getNoteById(noteId: Long): Note? = noteDao.getNoteById(noteId)?.toNote()
-
- suspend fun insertNote(
- note: Note,
- courseId: String,
- ): Long = noteDao.insertNote(note.toEntity(courseId))
-
- suspend fun updateNote(
- note: Note,
- courseId: String,
- noteId: Long,
- ) {
- noteDao.updateNote(note.toEntity(courseId, noteId))
- }
-
- suspend fun deleteNote(
- note: Note,
- courseId: String,
- noteId: Long,
- ) {
- noteDao.deleteNote(note.toEntity(courseId, noteId))
- }
-
- suspend fun updateStarredStatus(
- noteId: Long,
- isStarred: Boolean,
- ) {
- noteDao.updateStarredStatus(noteId, isStarred)
- }
-
- fun searchNotes(
- courseId: String,
- query: String,
- ): Flow> =
- noteDao.searchNotes(courseId, query).map { entities ->
- entities.map { it.toNote() }
- }
-
- private fun NoteEntity.toNote(): Note =
- Note(
- id = id,
- title = title,
- content = content,
- type = type,
- isStarred = isStarred,
- imagePath = imagePath,
- )
-
- private fun Note.toEntity(
- courseId: String,
- id: Long = 0,
- ): NoteEntity =
- NoteEntity(
- id = if (id == 0L) this.id else id,
- courseId = courseId,
- title = title,
- content = content,
- type = type,
- isStarred = isStarred,
- imagePath = imagePath,
- updatedAt = System.currentTimeMillis(),
- )
-}
diff --git a/app/src/main/java/com/dscvit/vitty/data/repository/ReminderRepository.kt b/app/src/main/java/com/dscvit/vitty/data/repository/ReminderRepository.kt
deleted file mode 100644
index 2d6beec..0000000
--- a/app/src/main/java/com/dscvit/vitty/data/repository/ReminderRepository.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-package com.dscvit.vitty.data.repository
-
-import com.dscvit.vitty.data.dao.ReminderDao
-import com.dscvit.vitty.data.entity.ReminderEntity
-import com.dscvit.vitty.ui.coursepage.models.Reminder
-import com.dscvit.vitty.ui.coursepage.models.ReminderStatus
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
-import java.text.SimpleDateFormat
-import java.util.Calendar
-import java.util.Date
-import java.util.Locale
-
-class ReminderRepository(
- private val reminderDao: ReminderDao,
-) {
- fun getRemindersByCourse(courseId: String): Flow> =
- reminderDao.getRemindersByCourse(courseId).map { entities ->
- entities.map { it.toReminder() }
- }
-
- fun getAllReminders(): Flow> =
- reminderDao.getAllReminders().map { entities ->
- entities.map { it.toReminder() }
- }
-
- suspend fun insertReminder(
- reminder: Reminder,
- courseId: String,
- courseTitle: String,
- ): Long = reminderDao.insertReminder(reminder.toEntity(courseId, courseTitle))
-
- suspend fun deleteReminder(
- reminder: Reminder,
- courseId: String,
- courseTitle: String,
- id: Long,
- ) {
- reminderDao.deleteReminder(reminder.toEntity(courseId, courseTitle, id))
- }
-
- suspend fun updateCompletedStatus(
- id: Long,
- isCompleted: Boolean,
- ) {
- reminderDao.updateCompletedStatus(id, isCompleted)
- }
-
- private fun ReminderEntity.toReminder(): Reminder {
- val calendar = Calendar.getInstance()
- calendar.timeInMillis = dateMillis
- val currentTime = System.currentTimeMillis()
-
- val status =
- when {
- isCompleted -> ReminderStatus.COMPLETED
- dateMillis < currentTime -> ReminderStatus.UPCOMING
- else -> ReminderStatus.CAN_WAIT
- }
-
- val dateFormat = SimpleDateFormat("dd MMM", Locale.getDefault())
- val fullDateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
-
- return Reminder(
- id = id,
- title = title,
- description = description,
- dueDate = dateFormat.format(Date(dateMillis)),
- date = fullDateFormat.format(Date(dateMillis)),
- status = status,
- dateMillis = dateMillis,
- fromTime = if (isAllDay) "" else String.format(Locale.getDefault(), "%02d:%02d", fromTimeHour, fromTimeMinute),
- toTime = if (isAllDay) "" else String.format(Locale.getDefault(), "%02d:%02d", toTimeHour, toTimeMinute),
- isAllDay = isAllDay,
- alertDaysBefore = alertDaysBefore,
- attachmentUrl = attachmentUrl,
- courseId = courseId,
- courseTitle = courseTitle,
- )
- }
-
- private fun Reminder.toEntity(
- courseId: String,
- courseTitle: String,
- id: Long = 0,
- ): ReminderEntity {
- val fromTimeParts = fromTime.split(":")
- val toTimeParts = toTime.split(":")
-
- return ReminderEntity(
- id = if (id == 0L) this.id else id,
- courseId = courseId.ifEmpty { this.courseId },
- courseTitle = courseTitle.ifEmpty { this.courseTitle },
- title = title,
- description = description,
- dateMillis = dateMillis,
- fromTimeHour = if (fromTimeParts.size >= 2) fromTimeParts[0].toIntOrNull() ?: 0 else 0,
- fromTimeMinute = if (fromTimeParts.size >= 2) fromTimeParts[1].toIntOrNull() ?: 0 else 0,
- toTimeHour = if (toTimeParts.size >= 2) toTimeParts[0].toIntOrNull() ?: 0 else 0,
- toTimeMinute = if (toTimeParts.size >= 2) toTimeParts[1].toIntOrNull() ?: 0 else 0,
- isAllDay = isAllDay,
- alertDaysBefore = alertDaysBefore,
- attachmentUrl = attachmentUrl,
- isCompleted = status == ReminderStatus.COMPLETED,
- updatedAt = System.currentTimeMillis(),
- )
- }
-}
diff --git a/app/src/main/java/com/dscvit/vitty/network/api/community/APICommunity.kt b/app/src/main/java/com/dscvit/vitty/network/api/community/APICommunity.kt
deleted file mode 100644
index f3a0380..0000000
--- a/app/src/main/java/com/dscvit/vitty/network/api/community/APICommunity.kt
+++ /dev/null
@@ -1,227 +0,0 @@
-package com.dscvit.vitty.network.api.community
-
-import com.dscvit.vitty.network.api.community.requests.CampusUpdateRequestBody
-import com.dscvit.vitty.network.api.community.requests.CircleBatchRequestBody
-import com.dscvit.vitty.network.api.community.requests.UsernameRequestBody
-import com.dscvit.vitty.network.api.community.responses.circle.CircleBatchRequestResponse
-import com.dscvit.vitty.network.api.community.responses.circle.CircleRequestsResponse
-import com.dscvit.vitty.network.api.community.responses.circle.CreateCircleRequest
-import com.dscvit.vitty.network.api.community.responses.circle.CreateCircleResponse
-import com.dscvit.vitty.network.api.community.responses.circle.JoinCircleResponse
-import com.dscvit.vitty.network.api.community.responses.requests.RequestsResponse
-import com.dscvit.vitty.network.api.community.responses.timetable.TimetableResponse
-import com.dscvit.vitty.network.api.community.responses.user.ActiveFriendResponse
-import com.dscvit.vitty.network.api.community.responses.user.CircleResponse
-import com.dscvit.vitty.network.api.community.responses.user.FriendResponse
-import com.dscvit.vitty.network.api.community.responses.user.GhostPostResponse
-import com.dscvit.vitty.network.api.community.responses.user.PostResponse
-import com.dscvit.vitty.network.api.community.responses.user.SignInResponse
-import com.dscvit.vitty.network.api.community.responses.user.UserResponse
-import retrofit2.Call
-import retrofit2.http.Body
-import retrofit2.http.DELETE
-import retrofit2.http.GET
-import retrofit2.http.Header
-import retrofit2.http.Headers
-import retrofit2.http.PATCH
-import retrofit2.http.POST
-import retrofit2.http.Path
-import retrofit2.http.Query
-
-interface APICommunity {
- @GET("/")
- fun checkServerStatus(): Call
-
- @Headers("Content-Type: application/json")
- @POST("/api/v3/auth/check-username")
- fun checkUsername(
- @Body body: UsernameRequestBody,
- ): Call
-
- @Headers("Content-Type: application/json")
- @POST("/api/v3/auth/firebase/")
- fun signInInfo(
- @Body body: Any,
- ): Call
-
- @GET("/api/v3/users/{username}")
- fun getUser(
- @Header("Authorization") authToken: String,
- @Path("username") username: String,
- ): Call
-
- @GET("/api/v3/timetable/{username}/")
- fun getTimeTable(
- @Header("Authorization") authToken: String,
- @Path("username") username: String,
- ): Call
-
- @GET("/api/v3/circles/{circleId}/{username}/")
- fun getCircleTimeTable(
- @Header("Authorization") authToken: String,
- @Path("circleId") circleId: String,
- @Path("username") username: String,
- ): Call
-
- @GET("/api/v3/friends/{username}/")
- fun getFriendList(
- @Header("Authorization") authToken: String,
- @Path("username") username: String,
- ): Call
-
- @GET("/api/v3/users/search")
- fun searchUsers(
- @Header("Authorization") authToken: String,
- @Query("query") query: String,
- ): Call>
-
- @GET("/api/v3/requests/")
- fun getFriendRequests(
- @Header("Authorization") authToken: String,
- ): Call
-
- @GET("/api/v3/users/suggested/")
- fun getSuggestedFriends(
- @Header("Authorization") authToken: String,
- ): Call>
-
- @POST("/api/v3/requests/{username}/send")
- fun sendRequest(
- @Header("Authorization") authToken: String,
- @Path("username") username: String,
- ): Call
-
- @POST("/api/v3/requests/{username}/accept/")
- fun acceptRequest(
- @Header("Authorization") authToken: String,
- @Path("username") username: String,
- ): Call
-
- @POST("/api/v3/requests/{username}/decline/")
- fun declineRequest(
- @Header("Authorization") authToken: String,
- @Path("username") username: String,
- ): Call
-
- @DELETE("/api/v3/friends/{username}/")
- fun deleteFriend(
- @Header("Authorization") authToken: String,
- @Path("username") username: String,
- ): Call
-
- @Headers("Content-Type: application/json")
- @PATCH("/api/v3/users/campus")
- fun updateCampus(
- @Header("Authorization") authToken: String,
- @Body campusRequestBody: CampusUpdateRequestBody,
- ): Call
-
- @POST("/api/v3/friends/ghost/{username}")
- fun enableGhostMode(
- @Header("Authorization") authToken: String,
- @Path("username") username: String,
- ): Call
-
- @POST("/api/v3/friends/alive/{username}")
- fun disableGhostMode(
- @Header("Authorization") authToken: String,
- @Path("username") username: String,
- ): Call
-
- @GET("/api/v3/circles")
- fun getCircles(
- @Header("Authorization") authToken: String,
- ): Call
-
- @POST("/api/v3/circles/create")
- fun createCircle(
- @Header("Authorization") authToken: String,
- @Body requestBody: CreateCircleRequest //
- ): Call
-
- @POST("/api/v3/circles/join")
- fun joinCircleByCode(
- @Header("Authorization") authToken: String,
- @Query("code") joinCode: String,
- ): Call
-
- @GET("/api/v3/circles/{circleId}")
- fun getCircleDetails(
- @Header("Authorization") authToken: String,
- @Path("circleId") circleId: String,
- ): Call
-
- @POST("/api/v3/circles/sendRequest/{circleId}/{username}")
- fun sendCircleRequest(
- @Header("Authorization") authToken: String,
- @Path("circleId") circleId: String,
- @Path("username") username: String,
- ): Call
-
- @Headers("Content-Type: application/json")
- @POST("/api/v3/circles/sendRequest/{circleId}")
- fun sendBatchCircleRequest(
- @Header("Authorization") authToken: String,
- @Path("circleId") circleId: String,
- @Body body: CircleBatchRequestBody,
- ): Call
-
- @GET("/api/v3/circles/requests/received")
- fun getReceivedCircleRequests(
- @Header("Authorization") authToken: String,
- ): Call
-
- @GET("/api/v3/circles/requests/sent")
- fun getSentCircleRequests(
- @Header("Authorization") authToken: String,
- ): Call
-
- @DELETE("/api/v3/circles/{circleId}")
- fun deleteCircle(
- @Header("Authorization") authToken: String,
- @Path("circleId") circleId: String,
- ): Call
-
- @DELETE("/api/v3/circles/leave/{circleId}")
- fun leaveCircle(
- @Header("Authorization") authToken: String,
- @Path("circleId") circleId: String,
- ): Call
-
- @POST("/api/v3/circles/acceptRequest/{circleId}")
- fun acceptCircleRequest(
- @Header("Authorization") authToken: String,
- @Path("circleId") circleId: String,
- ): Call
-
- @POST("/api/v3/circles/declineRequest/{circleId}")
- fun declineCircleRequest(
- @Header("Authorization") authToken: String,
- @Path("circleId") circleId: String,
- ): Call
-
- @DELETE("/api/v3/circles/unsendRequest/{circleId}/{username}")
- fun unsendCircleRequest(
- @Header("Authorization") authToken: String,
- @Path("circleId") circleId: String,
- @Path("username") username: String,
- ): Call
-
- @DELETE("/api/v3/circles/remove/{circleId}/{username}")
- fun removeUserFromCircle(
- @Header("Authorization") authToken: String,
- @Path("circleId") circleId: String,
- @Path("username") username: String,
- ): Call
-
- @GET("/api/v3/timetable/emptyClassRooms")
- fun getEmptyClassrooms(
- @Header("Authorization") authToken: String,
- @Query("slot") slot: String,
- ): Call>>
-
- @GET(value = "/api/v3/friends/active")
- fun getActiveFriends(
- @Header("Authorization") authToken: String,
- ): Call
-}
diff --git a/app/src/main/java/com/dscvit/vitty/network/api/community/APICommunityRestClient.kt b/app/src/main/java/com/dscvit/vitty/network/api/community/APICommunityRestClient.kt
deleted file mode 100644
index 5ef302a..0000000
--- a/app/src/main/java/com/dscvit/vitty/network/api/community/APICommunityRestClient.kt
+++ /dev/null
@@ -1,1079 +0,0 @@
-package com.dscvit.vitty.network.api.community
-
-import com.dscvit.vitty.network.api.community.requests.AuthRequestBodyWithCampus
-import com.dscvit.vitty.network.api.community.requests.AuthRequestBodyWithoutCampus
-import com.dscvit.vitty.network.api.community.requests.CampusUpdateRequestBody
-import com.dscvit.vitty.network.api.community.requests.CircleBatchRequestBody
-import com.dscvit.vitty.network.api.community.requests.UsernameRequestBody
-import com.dscvit.vitty.network.api.community.responses.circle.CircleBatchRequestResponse
-import com.dscvit.vitty.network.api.community.responses.circle.CircleRequestsResponse
-import com.dscvit.vitty.network.api.community.responses.circle.CreateCircleRequest
-import com.dscvit.vitty.network.api.community.responses.circle.CreateCircleResponse
-import com.dscvit.vitty.network.api.community.responses.circle.JoinCircleResponse
-import com.dscvit.vitty.network.api.community.responses.requests.RequestsResponse
-import com.dscvit.vitty.network.api.community.responses.timetable.TimetableResponse
-import com.dscvit.vitty.network.api.community.responses.user.ActiveFriendResponse
-import com.dscvit.vitty.network.api.community.responses.user.CircleResponse
-import com.dscvit.vitty.network.api.community.responses.user.FriendResponse
-import com.dscvit.vitty.network.api.community.responses.user.GhostPostResponse
-import com.dscvit.vitty.network.api.community.responses.user.PostResponse
-import com.dscvit.vitty.network.api.community.responses.user.SignInResponse
-import com.dscvit.vitty.network.api.community.responses.user.UserResponse
-import com.google.gson.Gson
-import com.google.gson.JsonSyntaxException
-import retrofit2.Call
-import retrofit2.Callback
-import retrofit2.Response
-import timber.log.Timber
-
-class APICommunityRestClient {
- companion object {
- val instance = APICommunityRestClient()
- }
-
- private var mApiUser: APICommunity? = null
- private val retrofit = CommunityNetworkClient.retrofitClientCommunity
-
- fun signInWithUsernameRegNo(
- username: String,
- regno: String,
- uuid: String,
- campus: String,
- retrofitCommunitySignInListener: RetrofitCommunitySignInListener,
- retrofitSelfUserListener: RetrofitSelfUserListener,
- ) {
- mApiUser = retrofit.create(APICommunity::class.java)
-
- val requestBody =
- if (campus != "") {
- AuthRequestBodyWithCampus(
- reg_no = regno,
- username = username,
- uuid = uuid,
- campus = campus,
- )
- } else {
- AuthRequestBodyWithoutCampus(
- reg_no = regno,
- username = username,
- uuid = uuid,
- )
- }
-
- val apiSignInCall = mApiUser!!.signInInfo(requestBody)
-
- apiSignInCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- retrofitCommunitySignInListener.onSuccess(call, response.body())
- val token = response.body()?.token.toString()
- val res_username = response.body()?.username.toString()
-
- getUserWithTimeTable(token, res_username, retrofitSelfUserListener)
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitCommunitySignInListener.onError(call, t)
- }
- },
- )
- }
-
- fun getUserWithTimeTable(
- token: String,
- username: String,
- retrofitSelfUserListener: RetrofitSelfUserListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiUserCall = mApiUser!!.getUser(bearerToken, username)
- apiUserCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("UserResponse: $response")
- retrofitSelfUserListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.e("Error fetching user with timetable: ${t.message}")
- retrofitSelfUserListener.onError(call, t)
- }
- },
- )
- }
-
- fun getTimeTable(
- token: String,
- username: String,
- retrofitTimeTableListener: RetrofitTimetableListener,
- ) {
- val token = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiTimetableCall = mApiUser!!.getTimeTable(token, username)
- apiTimetableCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- retrofitTimeTableListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitTimeTableListener.onError(call, t)
- }
- },
- )
- }
-
- fun getCircleTimeTable(
- token: String,
- circleId: String,
- username: String,
- retrofitTimeTableListener: RetrofitTimetableListener,
- ) {
- val token = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiCircleTimetableCall = mApiUser!!.getCircleTimeTable(token, circleId, username)
- apiCircleTimetableCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- retrofitTimeTableListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitTimeTableListener.onError(call, t)
- }
- },
- )
- }
-
- fun getFriendList(
- token: String,
- username: String,
- retrofitFriendListListener: RetrofitFriendListListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiFriendListCall = mApiUser!!.getFriendList(bearerToken, username)
- apiFriendListCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("FriendListResponse: ${response.body()}")
- retrofitFriendListListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitFriendListListener.onError(call, t)
- }
- },
- )
- }
-
- fun getCircles(
- token: String,
- retrofitCircleListener: RetrofitCircleListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiCirclesCall = mApiUser!!.getCircles(bearerToken)
- apiCirclesCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- retrofitCircleListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitCircleListener.onError(call, t)
- }
- },
- )
- }
-
- fun createCircle(
- token: String,
- circleName: String,
- retrofitCreateCircleListener: RetrofitCreateCircleListener,
- ) {
- val bearerToken = "Bearer $token"
-
- Timber.d("APICommunityRestClient.createCircle called with circleName: $circleName")
- val requestBody = CreateCircleRequest(circleName = circleName)
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiCreateCircleCall = mApiUser!!.createCircle(bearerToken, requestBody)
- Timber.d("API call created with request body, enqueueing request...")
-
-
- apiCreateCircleCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("API Response received: ${response.code()}, body: ${response.body()}")
- if (response.isSuccessful) {
- retrofitCreateCircleListener.onSuccess(call, response.body())
- } else {
- val errorBody = response.errorBody()?.string()
- Timber.e("API Error: ${response.code()} - $errorBody")
- retrofitCreateCircleListener.onError(call, Throwable("API Error: ${response.code()} - ${errorBody ?: "Unknown error"}"))
- }
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.e("API Call failed: ${t.message}")
- retrofitCreateCircleListener.onError(call, t)
- }
- },
- )
- }
-
- fun joinCircleByCode(
- token: String,
- joinCode: String,
- retrofitJoinCircleListener: RetrofitJoinCircleListener,
- ) {
- val bearerToken = "Bearer $token"
-
- Timber.d("APICommunityRestClient.joinCircleByCode called with joinCode: $joinCode")
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiJoinCircleCall = mApiUser!!.joinCircleByCode(bearerToken, joinCode)
-
- Timber.d("Join circle API call created, enqueueing request...")
-
- apiJoinCircleCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("Join Circle API Response received: ${response.code()}, body: ${response.body()}")
- if (response.isSuccessful) {
- retrofitJoinCircleListener.onSuccess(call, response.body())
- } else {
- // Handle error responses (400, 409, 500)
- val errorMessage =
- when (response.code()) {
- 400 -> "Invalid join code"
- 409 -> "You are already part of the circle"
- 500 -> "Failed to join circle"
- else -> "Unknown error occurred"
- }
- Timber.e("Join Circle API Error: ${response.code()} - $errorMessage")
- retrofitJoinCircleListener.onError(call, Throwable(errorMessage))
- }
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.e("Join Circle API Call failed: ${t.message}")
- retrofitJoinCircleListener.onError(call, t)
- }
- },
- )
- }
-
- fun getCircleDetails(
- token: String,
- circleId: String,
- retrofitFriendListListener: RetrofitFriendListListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiCircleDetailsCall = mApiUser!!.getCircleDetails(bearerToken, circleId)
- apiCircleDetailsCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- retrofitFriendListListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitFriendListListener.onError(call, t)
- }
- },
- )
- }
-
- fun getSearchResult(
- token: String,
- query: String,
- retrofitSearchResultListener: RetrofitSearchResultListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiSearchResultCall = mApiUser!!.searchUsers(bearerToken, query)
- apiSearchResultCall.enqueue(
- object : Callback> {
- override fun onResponse(
- call: Call>,
- response: Response>,
- ) {
- Timber.d("SearchResult4: $response")
- retrofitSearchResultListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call>,
- t: Throwable,
- ) {
- retrofitSearchResultListener.onError(call, t)
- }
- },
- )
- }
-
- fun getSuggestedFriends(
- token: String,
- retrofitSearchResultListener: RetrofitSearchResultListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiSuggestedResultCall = mApiUser!!.getSuggestedFriends(bearerToken)
- apiSuggestedResultCall.enqueue(
- object : Callback> {
- override fun onResponse(
- call: Call>,
- response: Response>,
- ) {
- Timber.d("SearchResult4: $response")
- Timber.d("Response Code: ${response.code()}")
- Timber.d("Response Headers: ${response.headers()}")
- Timber.d("Response Body: ${response.body()}")
- Timber.d("Response Raw: ${response.raw()}")
- Timber.d("Response isSuccessful: ${response.isSuccessful}")
-
- if (response.isSuccessful) {
- val body = response.body()
- if (body != null) {
- Timber.d("Suggested Friends Count: ${body.size}")
- retrofitSearchResultListener.onSuccess(call, body)
- } else {
- Timber.d("Response body is null, treating as empty list")
- retrofitSearchResultListener.onSuccess(call, emptyList())
- }
- } else {
- Timber.d("Response not successful: ${response.code()}")
- retrofitSearchResultListener.onError(call, Exception("HTTP ${response.code()}"))
- }
- }
-
- override fun onFailure(
- call: Call>,
- t: Throwable,
- ) {
- Timber.d("API Call Failed: ${t.message}")
- retrofitSearchResultListener.onError(call, t)
- }
- },
- )
- }
-
- fun getFriendRequest(
- token: String,
- retrofitFriendRequestListener: RetrofitFriendRequestListener,
- ) {
- val bearerToken = "Bearer $token"
- Timber.d("FriendReqToken--: $bearerToken")
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiFriendRequestCall = mApiUser!!.getFriendRequests(bearerToken)
- apiFriendRequestCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("FriendRequest--: $response")
- retrofitFriendRequestListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("FriendRequestError--: ${t.message}")
- retrofitFriendRequestListener.onError(call, t)
- }
- },
- )
- }
-
- fun acceptRequest(
- token: String,
- username: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiAcceptRequestCall = mApiUser!!.acceptRequest(bearerToken, username)
- apiAcceptRequestCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun rejectRequest(
- token: String,
- username: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiRejectRequestCall = mApiUser!!.declineRequest(bearerToken, username)
- apiRejectRequestCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun sendRequest(
- token: String,
- username: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiSendRequestCall = mApiUser!!.sendRequest(bearerToken, username)
- apiSendRequestCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun unfriend(
- token: String,
- username: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiUnfriendCall = mApiUser!!.deleteFriend(bearerToken, username)
- apiUnfriendCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun sendCircleRequest(
- token: String,
- circleId: String,
- username: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiSendCircleRequestCall = mApiUser!!.sendCircleRequest(bearerToken, circleId, username)
- apiSendCircleRequestCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("SendCircleResponse: $response")
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun sendBatchCircleRequest(
- token: String,
- circleId: String,
- usernames: List,
- callback: (CircleBatchRequestResponse?) -> Unit,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val requestBody = CircleBatchRequestBody(usernames)
- val apiSendBatchCircleRequestCall = mApiUser!!.sendBatchCircleRequest(bearerToken, circleId, requestBody)
- apiSendBatchCircleRequestCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("SendBatchCircleResponse: $response")
- callback(response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("SendBatchCircleRequestError: ${t.message}")
- callback(null)
- }
- },
- )
- }
-
- fun checkUsername(
- username: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- mApiUser = retrofit.create(APICommunity::class.java)
- val usernameRequestBody = UsernameRequestBody(username)
- val apiCheckUsernameCall = mApiUser!!.checkUsername(usernameRequestBody)
- apiCheckUsernameCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- if (response.isSuccessful) {
- retrofitUserActionListener.onSuccess(call, response.body())
- } else {
- val gson = Gson()
- val errorString = response.errorBody()?.string()
- Timber.d("ResponseV: $errorString")
- try {
- val errorResponse = gson.fromJson(errorString, PostResponse::class.java)
- retrofitUserActionListener.onSuccess(call, errorResponse)
- } catch (e: JsonSyntaxException) {
- // Handle any JSON parsing errors.
- val errorMessage = "Username is not valid/available."
- retrofitUserActionListener.onSuccess(call, PostResponse(errorMessage))
- }
- }
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("ErrorV: ${t.message}")
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun enableGhostMode(
- token: String,
- username: String,
- retrofitUserActionListener: RetrofitGhostActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiGhostModeCall = mApiUser!!.enableGhostMode(bearerToken, username)
- apiGhostModeCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun disableGhostMode(
- token: String,
- username: String,
- retrofitUserActionListener: RetrofitGhostActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiGhostModeCall = mApiUser!!.disableGhostMode(bearerToken, username)
- apiGhostModeCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun getReceivedCircleRequests(
- token: String,
- retrofitCircleRequestListener: RetrofitCircleRequestListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiReceivedCircleRequestsCall = mApiUser!!.getReceivedCircleRequests(bearerToken)
- apiReceivedCircleRequestsCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("ReceivedCircleRequests: ${response.body()}")
- retrofitCircleRequestListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("ReceivedCircleRequestsError: ${t.message}")
- retrofitCircleRequestListener.onError(call, t)
- }
- },
- )
- }
-
- fun getSentCircleRequests(
- token: String,
- retrofitCircleRequestListener: RetrofitCircleRequestListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiSentCircleRequestsCall = mApiUser!!.getSentCircleRequests(bearerToken)
- apiSentCircleRequestsCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("SentCircleRequests: ${response.body()}")
- retrofitCircleRequestListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("SentCircleRequestsError: ${t.message}")
- retrofitCircleRequestListener.onError(call, t)
- }
- },
- )
- }
-
- fun deleteCircle(
- token: String,
- circleId: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiDeleteCircleCall = mApiUser!!.deleteCircle(bearerToken, circleId)
- apiDeleteCircleCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("DeleteCircle: ${response.body()}")
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("DeleteCircleError: ${t.message}")
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun leaveCircle(
- token: String,
- circleId: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiLeaveCircleCall = mApiUser!!.leaveCircle(bearerToken, circleId)
- apiLeaveCircleCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("LeaveCircle: ${response.body()}")
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("LeaveCircleError: ${t.message}")
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun acceptCircleRequest(
- token: String,
- circleId: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiAcceptCircleRequestCall = mApiUser!!.acceptCircleRequest(bearerToken, circleId)
- apiAcceptCircleRequestCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("AcceptCircleRequest: ${response.body()}")
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("AcceptCircleRequestError: ${t.message}")
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun declineCircleRequest(
- token: String,
- circleId: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiDeclineCircleRequestCall = mApiUser!!.declineCircleRequest(bearerToken, circleId)
- apiDeclineCircleRequestCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("DeclineCircleRequest: ${response.body()}")
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("DeclineCircleRequestError: ${t.message}")
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun unsendCircleRequest(
- token: String,
- circleId: String,
- username: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiUnsendCircleRequestCall = mApiUser!!.unsendCircleRequest(bearerToken, circleId, username)
- apiUnsendCircleRequestCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("UnsendCircleRequest: ${response.body()}")
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("UnsendCircleRequestError: ${t.message}")
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun getEmptyClassrooms(
- token: String,
- slot: String,
- callback: (Map>?) -> Unit,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiEmptyClassroomsCall = mApiUser!!.getEmptyClassrooms(bearerToken, slot)
- apiEmptyClassroomsCall.enqueue(
- object : Callback>> {
- override fun onResponse(
- call: Call>>,
- response: Response>>,
- ) {
- Timber.d("EmptyClassrooms: ${response.body()}")
- callback(response.body())
- }
-
- override fun onFailure(
- call: Call>>,
- t: Throwable,
- ) {
- Timber.d("EmptyClassroomsError: ${t.message}")
- callback(null)
- }
- },
- )
- }
-
- fun removeUserFromCircle(
- token: String,
- circleId: String,
- username: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiRemoveUserCall = mApiUser!!.removeUserFromCircle(bearerToken, circleId, username)
- apiRemoveUserCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("RemoveUserFromCircle: ${response.body()}")
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("RemoveUserFromCircleError: ${t.message}")
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun updateCampus(
- token: String,
- campus: String,
- retrofitUserActionListener: RetrofitUserActionListener,
- ) {
- val bearerToken = "Bearer $token"
-
- mApiUser = retrofit.create(APICommunity::class.java)
- val requestBody = CampusUpdateRequestBody(campus)
- val apiUpdateCampusCall = mApiUser!!.updateCampus(bearerToken, requestBody)
- apiUpdateCampusCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("UpdateCampus: ${response.body()}")
- retrofitUserActionListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("UpdateCampusError: ${t.message}")
- retrofitUserActionListener.onError(call, t)
- }
- },
- )
- }
-
- fun getActiveFriends(
- token: String,
- retrofitActiveFriendsListener: RetrofitActiveFriendsListener,
- ) {
- val bearerToken = "Bearer $token"
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiActiveFriendsCall = mApiUser!!.getActiveFriends(bearerToken)
- apiActiveFriendsCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("ActiveFriends: ${response.body()}")
- retrofitActiveFriendsListener.onSuccess(call, response.body())
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("ActiveFriendsError: ${t.message}")
- retrofitActiveFriendsListener.onError(call, t)
- }
- },
- )
- }
-
- fun checkServerStatus(
- retrofitServerStatusListener: RetrofitServerStatusListener,
- ) {
- mApiUser = retrofit.create(APICommunity::class.java)
- val apiServerStatusCall = mApiUser!!.checkServerStatus()
- apiServerStatusCall.enqueue(
- object : Callback {
- override fun onResponse(
- call: Call,
- response: Response,
- ) {
- Timber.d("ServerStatus: ${response.body()}")
- retrofitServerStatusListener.onSuccess(call, response.body(), response.isSuccessful)
- }
-
- override fun onFailure(
- call: Call,
- t: Throwable,
- ) {
- Timber.d("ServerStatusError: ${t.message}")
- retrofitServerStatusListener.onError(call, t)
- }
- },
- )
- }
-}
diff --git a/app/src/main/java/com/dscvit/vitty/network/api/community/CommunityNetworkClient.kt b/app/src/main/java/com/dscvit/vitty/network/api/community/CommunityNetworkClient.kt
deleted file mode 100644
index c9b4f93..0000000
--- a/app/src/main/java/com/dscvit/vitty/network/api/community/CommunityNetworkClient.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.dscvit.vitty.network.api.community
-
-import com.dscvit.vitty.util.WebConstants.COMMUNITY_BASE_URL
-import com.dscvit.vitty.util.WebConstants.TIMEOUT
-import okhttp3.OkHttpClient
-import okhttp3.logging.HttpLoggingInterceptor
-import retrofit2.Retrofit
-import retrofit2.converter.gson.GsonConverterFactory
-import java.util.concurrent.TimeUnit
-
-object CommunityNetworkClient {
- private var retrofit: Retrofit? = null
-
- val retrofitClientCommunity: Retrofit
- get() {
- if (retrofit == null) {
- val loggingInterceptor =
- HttpLoggingInterceptor().apply {
- level = HttpLoggingInterceptor.Level.BODY
- }
-
- val okHttpClient =
- OkHttpClient
- .Builder()
- .addInterceptor(loggingInterceptor)
- .connectTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS)
- .readTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS)
- .writeTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS)
- .build()
-
- retrofit =
- Retrofit
- .Builder()
- .baseUrl(COMMUNITY_BASE_URL)
- .addConverterFactory(GsonConverterFactory.create())
- .client(okHttpClient)
- .build()
- }
- return retrofit!!
- }
-}
diff --git a/app/src/main/java/com/dscvit/vitty/network/api/community/RetrofitCommunityListener.kt b/app/src/main/java/com/dscvit/vitty/network/api/community/RetrofitCommunityListener.kt
deleted file mode 100644
index f178876..0000000
--- a/app/src/main/java/com/dscvit/vitty/network/api/community/RetrofitCommunityListener.kt
+++ /dev/null
@@ -1,183 +0,0 @@
-package com.dscvit.vitty.network.api.community
-
-import com.dscvit.vitty.network.api.community.responses.circle.CircleRequestsResponse
-import com.dscvit.vitty.network.api.community.responses.circle.CreateCircleResponse
-import com.dscvit.vitty.network.api.community.responses.circle.JoinCircleResponse
-import com.dscvit.vitty.network.api.community.responses.requests.RequestsResponse
-import com.dscvit.vitty.network.api.community.responses.timetable.TimetableResponse
-import com.dscvit.vitty.network.api.community.responses.user.ActiveFriendResponse
-import com.dscvit.vitty.network.api.community.responses.user.CircleResponse
-import com.dscvit.vitty.network.api.community.responses.user.FriendResponse
-import com.dscvit.vitty.network.api.community.responses.user.GhostPostResponse
-import com.dscvit.vitty.network.api.community.responses.user.PostResponse
-import com.dscvit.vitty.network.api.community.responses.user.SignInResponse
-import com.dscvit.vitty.network.api.community.responses.user.UserResponse
-import retrofit2.Call
-
-interface RetrofitCommunitySignInListener {
- fun onSuccess(
- call: Call?,
- response: SignInResponse?,
- )
-
- fun onError(
- call: Call?,
- t: Throwable?,
- )
-}
-
-interface RetrofitSelfUserListener {
- fun onSuccess(
- call: Call?,
- response: UserResponse?,
- )
-
- fun onError(
- call: Call?,
- t: Throwable?,
- )
-}
-
-interface RetrofitTimetableListener {
- fun onSuccess(
- call: Call?,
- response: TimetableResponse?,
- )
-
- fun onError(
- call: Call?,
- t: Throwable?,
- )
-}
-
-interface RetrofitFriendListListener {
- fun onSuccess(
- call: Call?,
- response: FriendResponse?,
- )
-
- fun onError(
- call: Call?,
- t: Throwable?,
- )
-}
-
-interface RetrofitSearchResultListener {
- fun onSuccess(
- call: Call>?,
- response: List?,
- )
-
- fun onError(
- call: Call>?,
- t: Throwable?,
- )
-}
-
-interface RetrofitFriendRequestListener {
- fun onSuccess(
- call: Call?,
- response: RequestsResponse?,
- )
-
- fun onError(
- call: Call?,
- t: Throwable?,
- )
-}
-
-interface RetrofitCircleRequestListener {
- fun onSuccess(
- call: Call?,
- response: CircleRequestsResponse?,
- )
-
- fun onError(
- call: Call?,
- t: Throwable?,
- )
-}
-
-interface RetrofitUserActionListener {
- fun onSuccess(
- call: Call