diff --git a/app/build.gradle b/app/build.gradle
index 1c3191e..04eb635 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -33,6 +33,7 @@ android {
}
}
compileOptions {
+ coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
@@ -77,7 +78,7 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
//security
- implementation "androidx.security:security-crypto:1.1.0-alpha05"
+ implementation "androidx.security:security-crypto:1.1.0-alpha06"
// Import the Firebase BoM
implementation platform('com.google.firebase:firebase-bom:31.3.0')
@@ -89,6 +90,11 @@ dependencies {
//Hilt
implementation "com.google.dagger:hilt-android:2.44"
kapt "com.google.dagger:hilt-compiler:2.44"
+
+ //Time
+ coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
+
+ implementation "ru.tinkoff.decoro:decoro:1.1.1"
}
kapt {
correctErrorTypes true
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 049602f..06b4750 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -41,7 +41,7 @@
+ android:resource="@drawable/ic_logo" />
diff --git a/app/src/main/java/ru/nsu/fit/modao/MasterActivity.kt b/app/src/main/java/ru/nsu/fit/modao/MasterActivity.kt
index c1387b6..48969c3 100644
--- a/app/src/main/java/ru/nsu/fit/modao/MasterActivity.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/MasterActivity.kt
@@ -30,4 +30,5 @@ class MasterActivity: AppCompatActivity() {
return@setOnItemSelectedListener true
}
}
+
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/adapter/ExpensesAdapter.kt b/app/src/main/java/ru/nsu/fit/modao/adapter/ExpensesAdapter.kt
index f283b18..ed3c739 100644
--- a/app/src/main/java/ru/nsu/fit/modao/adapter/ExpensesAdapter.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/adapter/ExpensesAdapter.kt
@@ -6,33 +6,89 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import ru.nsu.fit.modao.R
+import ru.nsu.fit.modao.databinding.CounterEventItemBinding
+import ru.nsu.fit.modao.databinding.DeletedEventItemBinding
import ru.nsu.fit.modao.databinding.ExpenseItemBinding
+import ru.nsu.fit.modao.databinding.TransferItemBinding
import ru.nsu.fit.modao.models.Currency
import ru.nsu.fit.modao.models.Expense
import ru.nsu.fit.modao.models.ExpenseListItem
import ru.nsu.fit.modao.models.LoadItems
class ExpensesAdapter: RecyclerView.Adapter() {
- private var expensesList: Array = arrayOf()
+ private var expensesList: MutableList = mutableListOf()
private lateinit var listener: AdapterListener
companion object {
const val EXPENSE = 0
- const val LOAD = 1
+ const val TRANSFER = 1
+ const val DELETED = 2
+ const val DELETING = 3
+ const val LOAD = 4
}
fun attachListener(listener: AdapterListener){
this.listener = listener
}
fun setList(list: Array){
- expensesList = list
+ expensesList = list.toMutableList()
notifyDataSetChanged()
}
+ fun addItems(list: Array) {
+ val size = expensesList.size
+ expensesList.addAll(list)
+ notifyItemRangeChanged(size, list.size)
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+
+ return when (viewType) {
+ EXPENSE -> ExpensesHolder(inflater.inflate(R.layout.expense_item, parent, false))
+ TRANSFER -> TransferHolder(inflater.inflate(R.layout.transfer_item, parent, false))
+ DELETED -> DeletedEventHolder(inflater.inflate(R.layout.deleted_event_item, parent, false))
+ DELETING -> CounterEventHolder(inflater.inflate(R.layout.counter_event_item, parent, false))
+ LOAD -> LoadHolder(inflater.inflate(R.layout.empty_item, parent, false))
+ else -> throw IllegalArgumentException("Illegal view type: $viewType")
+ }
+ }
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ when (holder) {
+ is ExpensesHolder -> holder.bind(expensesList[position] as Expense, listener)
+ is TransferHolder -> holder.bind(expensesList[position] as Expense, listener)
+ is DeletedEventHolder -> holder.bind(expensesList[position] as Expense, listener)
+ is CounterEventHolder -> holder.bind(expensesList[position] as Expense, listener)
+ is LoadHolder -> holder.bind(expensesList[position] as LoadItems, listener)
+ }
+
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return when (expensesList[position]) {
+ is Expense -> {
+ val expense = expensesList[position] as Expense
+
+ when (expense.status) {
+ 0 -> if (expense.type == 0) EXPENSE else TRANSFER
+ 1 -> if (expense.type == 0) EXPENSE else TRANSFER
+ -2 -> DELETING
+ -1 -> DELETED
+ else -> throw IllegalArgumentException("status ${expense.status}")
+ }
+ }
+ is LoadItems -> LOAD
+ }
+ }
+
+ override fun getItemCount(): Int {
+ return expensesList.size
+ }
class LoadHolder(item: View): RecyclerView.ViewHolder(item) {
fun bind(load: LoadItems, listener: AdapterListener) {
listener.onClickItem(load)
}
}
- class ExpensesHolder(item: View): RecyclerView.ViewHolder(item){
- val binding = ExpenseItemBinding.bind(item)
+ class DeletedEventHolder(item: View): RecyclerView.ViewHolder(item) {
+ val binding = DeletedEventItemBinding.bind(item)
fun bind(expense: Expense, listener: AdapterListener) = with(binding){
shortInfo.text = expense.name
amountExpense.text = expense.price.toString()
@@ -51,33 +107,65 @@ class ExpensesAdapter: RecyclerView.Adapter() {
}
}
}
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
- val inflater = LayoutInflater.from(parent.context)
- return when (viewType) {
- EXPENSE -> ExpensesHolder(inflater.inflate(R.layout.expense_item, parent, false))
- LOAD -> LoadHolder(inflater.inflate(R.layout.empty_item, parent, false))
- else -> throw IllegalArgumentException("Illegal view type: $viewType")
+ class CounterEventHolder(item: View): RecyclerView.ViewHolder(item) {
+ val binding = CounterEventItemBinding.bind(item)
+ fun bind(expense: Expense, listener: AdapterListener) = with(binding){
+ shortInfo.text = expense.name
+ amountExpense.text = expense.price.toString()
+ if (expense.price!! > 0){
+ if (expense.currency == Currency.RUB){
+ currencyImage.setImageResource(R.drawable.ic_profit_rub)
+ }
+ } else {
+ if (expense.currency == Currency.RUB) {
+ currencyImage.setImageResource(R.drawable.ic_loss_rub)
+ amountExpense.setTextColor(Color.parseColor("#D46E6E"))
+ }
+ }
+ root.setOnClickListener {
+ listener.onClickItem(expense)
+ }
}
}
-
- override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
- when (holder) {
- is ExpensesHolder -> holder.bind(expensesList[position] as Expense, listener)
- is LoadHolder -> holder.bind(expensesList[position] as LoadItems, listener)
+ class TransferHolder(item: View): RecyclerView.ViewHolder(item) {
+ val binding = TransferItemBinding.bind(item)
+ fun bind(expense: Expense, listener: AdapterListener) = with(binding){
+ shortInfo.text = expense.name
+ amountExpense.text = expense.price.toString()
+ if (expense.price!! > 0){
+ if (expense.currency == Currency.RUB){
+ currencyImage.setImageResource(R.drawable.ic_profit_rub)
+ }
+ } else {
+ if (expense.currency == Currency.RUB) {
+ currencyImage.setImageResource(R.drawable.ic_loss_rub)
+ amountExpense.setTextColor(Color.parseColor("#D46E6E"))
+ }
+ }
+ root.setOnClickListener {
+ listener.onClickItem(expense)
+ }
}
-
}
-
- override fun getItemViewType(position: Int): Int {
- return when (expensesList[position]) {
- is Expense -> EXPENSE
- is LoadItems -> LOAD
+ class ExpensesHolder(item: View): RecyclerView.ViewHolder(item){
+ val binding = ExpenseItemBinding.bind(item)
+ fun bind(expense: Expense, listener: AdapterListener) = with(binding){
+ shortInfo.text = expense.name
+ amountExpense.text = expense.price.toString()
+ if (expense.price!! > 0){
+ if (expense.currency == Currency.RUB){
+ currencyImage.setImageResource(R.drawable.ic_profit_rub)
+ }
+ } else {
+ if (expense.currency == Currency.RUB) {
+ currencyImage.setImageResource(R.drawable.ic_loss_rub)
+ amountExpense.setTextColor(Color.parseColor("#D46E6E"))
+ }
+ }
+ root.setOnClickListener {
+ listener.onClickItem(expense)
+ }
}
}
- override fun getItemCount(): Int {
- return expensesList.size
- }
-
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/adapter/FriendsAdapter.java b/app/src/main/java/ru/nsu/fit/modao/adapter/FriendsAdapter.java
index 655e0c3..2ac7489 100644
--- a/app/src/main/java/ru/nsu/fit/modao/adapter/FriendsAdapter.java
+++ b/app/src/main/java/ru/nsu/fit/modao/adapter/FriendsAdapter.java
@@ -3,12 +3,12 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
+import com.google.android.material.button.MaterialButton;
+
import ru.nsu.fit.modao.R;
import ru.nsu.fit.modao.models.User;
@@ -46,10 +46,9 @@ public static final class FriendsHolder extends RecyclerView.ViewHolder {
View itemView;
public void bind(User friend, AdapterListener listener) {
- ImageView imageView = itemView.findViewById(R.id.friendItem);
- imageView.setOnClickListener(v -> listener.onClickItem(friend));
- TextView textView = itemView.findViewById(R.id.nameFriends);
- textView.setText(friend.getUsername());
+ MaterialButton cell = itemView.findViewById(R.id.friendItem);
+ cell.setOnClickListener(v -> listener.onClickItem(friend));
+ cell.setText(friend.getUsername());
}
public FriendsHolder(@NonNull View itemView) {
diff --git a/app/src/main/java/ru/nsu/fit/modao/adapter/GroupAdapter.kt b/app/src/main/java/ru/nsu/fit/modao/adapter/GroupAdapter.kt
index fcff5d7..9113e3e 100644
--- a/app/src/main/java/ru/nsu/fit/modao/adapter/GroupAdapter.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/adapter/GroupAdapter.kt
@@ -1,18 +1,22 @@
package ru.nsu.fit.modao.adapter
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import ru.nsu.fit.modao.R
+import ru.nsu.fit.modao.databinding.GroupItemArchiveBinding
import ru.nsu.fit.modao.databinding.GroupItemBinding
import ru.nsu.fit.modao.models.Group
-class GroupAdapter: RecyclerView.Adapter() {
+class GroupAdapter: RecyclerView.Adapter() {
private var listener: AdapterListener? = null
private var groupsList: Array = arrayOf()
+ companion object {
+ const val ACTIVE = 0
+ const val ARCHIVE = 1
+ }
fun attachListener(listener: AdapterListener){
this.listener = listener
}
@@ -20,27 +24,55 @@ class GroupAdapter: RecyclerView.Adapter() {
this.groupsList = groupsList
notifyDataSetChanged()
}
+
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return when (viewType) {
+ ACTIVE -> GroupHolder(inflater.inflate(R.layout.group_item, parent, false))
+ ARCHIVE -> ArchiveGroupHolder(inflater.inflate(R.layout.group_item_archive, parent, false))
+ else -> throw IllegalArgumentException("Unknown type $viewType")
+ }
+ }
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ when (holder) {
+ is GroupHolder -> holder.bind(groupsList[position], listener!!)
+ is ArchiveGroupHolder -> holder.bind(groupsList[position], listener!!)
+ }
+
+ }
+
+ override fun getItemCount(): Int {
+ return groupsList.size
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return when (groupsList[position].typeGroup) {
+ 0 -> ACTIVE
+ 1 -> ARCHIVE
+ else -> throw IllegalArgumentException("Unknown type ${groupsList[position].typeGroup}")
+ }
+ }
+
class GroupHolder(item: View): RecyclerView.ViewHolder(item){
val binding = GroupItemBinding.bind(item)
val view = item
fun bind(group: Group, listener: AdapterListener){
binding.nameGroup.text = group.groupName
- view.setOnClickListener(){
+ binding.nameGroup.setOnClickListener {
listener.onClickItem(group)
}
}
}
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GroupHolder {
- val view = LayoutInflater.from(parent.context).inflate(R.layout.group_item, parent, false)
- return GroupHolder(view)
- }
-
- override fun onBindViewHolder(holder: GroupHolder, position: Int) {
- holder.bind(groupsList[position], listener!!)
- }
-
- override fun getItemCount(): Int {
- return groupsList.size
+ class ArchiveGroupHolder(item: View): RecyclerView.ViewHolder(item) {
+ val binding = GroupItemArchiveBinding.bind(item)
+ val view = item
+ fun bind(group: Group, listener: AdapterListener){
+ binding.nameGroup.text = group.groupName
+ binding.nameGroup.setOnClickListener {
+ listener.onClickItem(group)
+ }
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/adapter/NotificationFriendsAdapter.kt b/app/src/main/java/ru/nsu/fit/modao/adapter/NotificationFriendsAdapter.kt
index f888340..3ef8112 100644
--- a/app/src/main/java/ru/nsu/fit/modao/adapter/NotificationFriendsAdapter.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/adapter/NotificationFriendsAdapter.kt
@@ -1,6 +1,5 @@
package ru.nsu.fit.modao.adapter
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -39,20 +38,17 @@ class NotificationFriendsAdapter: RecyclerView.Adapter,
listenerGroup: AdapterListener){
if (elem.nameGroup != null){
- binding.frameNewGroup.visibility = View.VISIBLE
binding.nameNewGroup.visibility = View.VISIBLE
binding.nameNewGroup.text = elem.nameGroup
binding.newGroup.visibility = View.VISIBLE
- binding.root.setOnClickListener {
- Log.d("MyTag", "Notification adapter group")
+ binding.nameNewGroup.setOnClickListener {
listenerGroup.onClickItem(elem)
}
} else {
- binding.frameNewFriend.visibility = View.VISIBLE
binding.nameNewFriend.visibility = View.VISIBLE
binding.newFriend.visibility = View.VISIBLE
binding.nameNewFriend.text = elem.username
- binding.root.setOnClickListener {
+ binding.nameNewFriend.setOnClickListener {
listenerFriend.onClickItem(elem)
}
}
diff --git a/app/src/main/java/ru/nsu/fit/modao/api/ApiService.kt b/app/src/main/java/ru/nsu/fit/modao/api/ApiService.kt
index 3784535..d9d8caf 100644
--- a/app/src/main/java/ru/nsu/fit/modao/api/ApiService.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/api/ApiService.kt
@@ -8,20 +8,45 @@ interface ApiService {
@POST("/api/auth/login")
suspend fun login(@Body user: User): Response
+ @POST("/api/auth/token")
+ suspend fun getAccessToken(@Body refreshToken: Tokens): Response
+
+ @POST("/api/auth/refresh")
+ suspend fun getRefreshToken(@Body refreshToken: Tokens): Response
+
@GET("/user/myInfo")
suspend fun getUser(
@Header("Authorization") token: String
): Response
- @GET("/user/listGroups")
- suspend fun getUserGroups(
+
+ @GET("/user/exitUser")
+ suspend fun exit(
@Header("Authorization") token: String
+ ): Response
+
+ @GET("/user/listGroups/{type}")
+ suspend fun getUserGroups(
+ @Header("Authorization") token: String,
+ @Path("type") type: Int
): Response>
+ @GET("/group/delete/{groupId}")
+ suspend fun deleteGroup(
+ @Header("Authorization") token: String,
+ @Path("groupId") groupId: Long
+ ): Response
+ @GET("/group/archive/{groupId}")
+ suspend fun archiveGroup(
+ @Header("Authorization") token: String,
+ @Path("groupId") groupId: Long
+ ): Response
+
@POST("/group/create")
suspend fun createGroup(
@Header("Authorization") token: String,
@Body group: Group
): Response
+
@PUT("/group/addUserInGroup/{groupUUID}")
suspend fun addToGroup(
@Header("Authorization") token: String,
@@ -38,13 +63,38 @@ interface ApiService {
@Path("groupId") groupId: Long
): Response
- @GET("/event/listEventsConfirmed/{mode}/{groupId}/{type}")
+ @PUT("/event/delete/{groupId}/{eventId}")
+ suspend fun deleteEvent(
+ @Header("Authorization") token: String,
+ @Path("groupId") groupId: Long,
+ @Path("eventId") eventId: Long,
+ @Body name: String
+ ): Response
+
+ @GET("/group/deleteUser/{groupId}/{userId}")
+ suspend fun deleteUser(
+ @Header("Authorization") token: String,
+ @Path("groupId") groupId: Long,
+ @Path("userId") userId: Long
+ ): Response
+
+ @GET("/group/archiveNo/{groupId}")
+ suspend fun makeGroupActive(
+ @Header("Authorization") token: String,
+ @Path("groupId") groupId: Long
+ ): Response
+
+ @GET("/event/listEventsConfirmed/{mode}/{groupId}/{type}/{minTime}/{maxTime}")
suspend fun getGroupExpenses(
@Header("Authorization") token: String,
@Path("groupId") id: Long,
@Path("mode") mode: Int,
- @Path("type") type: Int
- ): Response>
+ @Path("type") type: Int,
+ @Path("minTime") minTime: Long,
+ @Path("maxTime") maxTime: Long,
+ @Query("offset") offset: Int,
+ @Query("limit") limit: Int
+ ): Response
@GET("/event/listEventsUnconfirmed/{groupId}")
suspend fun getGroupUnconfirmedExpenses(
@@ -85,55 +135,66 @@ interface ApiService {
@Header("Authorization") token: String,
@Path("groupId") groupId: Long
): Response>
+
@GET("/debt/{userId}/{groupId}")
suspend fun getUserDebtInGroup(
@Header("Authorization") token: String,
@Path("userId") userId: Long,
@Path("groupId") groupId: Long
): Response>
+
@GET("/group/listOrganizers/{groupId}")
suspend fun getListOrganizers(
@Header("Authorization") token: String,
@Path("groupId") groupId: Long
): Response>
+
@GET("/group/info/{groupId}")
suspend fun getGroupInfo(
@Header("Authorization") token: String,
@Path("groupId") groupId: Long
): Response
+
@GET("/invitation/getInvitationsFriend")
suspend fun getInvitationsFriend(
@Header("Authorization") token: String
): Response>
+
@POST("/invitation/createInvitationFriend/{userUuid}")
suspend fun addFriend(
@Header("Authorization") token: String,
@Path("userUuid") userUuid: String
): Response
+
@GET("/invitation/getInvitationsInGroup")
suspend fun getInvitationsGroup(
@Header("Authorization") token: String
): Response>
+
@POST("/invitation/acceptInvitationFriend/{invitationId}")
suspend fun acceptInvitationFriend(
@Header("Authorization") token: String,
@Path("invitationId") invitationId: Long
): Response
+
@POST("/invitation/declineInvitationFriend/{invitationId}")
suspend fun denyInvitationFriend(
@Header("Authorization") token: String,
@Path("invitationId") invitationId: Long
): Response
+
@POST("/invitation/acceptInvitationInGroup/{invitationId}")
suspend fun acceptInvitationGroup(
@Header("Authorization") token: String,
@Path("invitationId") invitationId: Long
): Response
+
@POST("/invitation/declineInvitationInGroup/{invitationId}")
suspend fun denyInvitationGroup(
@Header("Authorization") token: String,
@Path("invitationId") invitationId: Long
): Response
+
@GET("/user/listFriends")
suspend fun getListFriends(
@Header("Authorization") token: String
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/AddMemberFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/AddMemberFragment.kt
index babecc7..b39a26c 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/AddMemberFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/AddMemberFragment.kt
@@ -50,7 +50,6 @@ class AddMemberFragment : BottomSheetDialogFragment(), AdapterListener !members.contains(user)}.map { user ->
ParticipantEvent(
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/AuthorizationFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/AuthorizationFragment.kt
index 371429a..da8d381 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/AuthorizationFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/AuthorizationFragment.kt
@@ -15,6 +15,7 @@ import ru.nsu.fit.modao.models.Authorization
import ru.nsu.fit.modao.utils.App
import ru.nsu.fit.modao.utils.Constants.Companion.ACCESS_TOKEN
import ru.nsu.fit.modao.utils.Constants.Companion.ID_USER
+import ru.nsu.fit.modao.utils.Constants.Companion.REFRESH_TOKEN
import ru.nsu.fit.modao.viewmodels.LoginViewModel
import javax.inject.Inject
@@ -54,7 +55,8 @@ class AuthorizationFragment : Fragment() {
binding.tipMessage.setText(R.string.wait)
loginViewModel.login(
login = binding.personLogin.text.toString(),
- password = binding.personPassword.text.toString()
+ password = binding.personPassword.text.toString(),
+ app.deviceToken
)
}
binding.buttonSignUp.setOnClickListener {
@@ -67,7 +69,8 @@ class AuthorizationFragment : Fragment() {
app.accessToken = it.accessToken
app.refreshToken = it.refreshToken
val edit = app.encryptedSharedPreferences.edit()
- edit.putString(ACCESS_TOKEN, it.accessToken).putLong(ID_USER, it.id).apply()
+ edit.putString(ACCESS_TOKEN, it.accessToken).putLong(ID_USER, it.id)
+ .putString(REFRESH_TOKEN, it.refreshToken).apply()
activity?.findViewById(R.id.bottomMenu)?.visibility = View.VISIBLE
findNavController().navigate(AuthorizationFragmentDirections.actionAuthorizationFragmentToProfileFragment())
}
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/CreateExpenseFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/CreateExpenseFragment.kt
index 400f261..0eceed7 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/CreateExpenseFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/CreateExpenseFragment.kt
@@ -22,17 +22,25 @@ import ru.nsu.fit.modao.utils.App
import ru.nsu.fit.modao.viewmodels.CreateExpenseViewModel
import ru.nsu.fit.modao.viewmodels.MainViewModel
import javax.inject.Inject
+
@AndroidEntryPoint
class CreateExpenseFragment : Fragment(), AdapterListener {
private var _binding: FragmentCreateExpenseBinding? = null
private val binding get() = _binding!!
private var menuList = listOf("Who spent", "Participants", "Coefficient")
private val adapter = MenuAdapter()
+ private val listDestinations = listOf(
+ R.id.enterCostFragment,
+ R.id.selectParticipantsFragment,
+ R.id.enterCoefficientsFragment
+ )
+
@Inject
lateinit var app: App
private val args by navArgs()
private val mainViewModel: MainViewModel by viewModels()
private val createExpenseViewModel: CreateExpenseViewModel by viewModels()
+
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -50,6 +58,8 @@ class CreateExpenseFragment : Fragment(), AdapterListener {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+
+ initOrganizer()
binding.recyclerMenu.layoutManager =
LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
adapter.attachListener(this)
@@ -59,10 +69,22 @@ class CreateExpenseFragment : Fragment(), AdapterListener {
mainViewModel.getUsersInGroup(args.dataExpense.group.id!!)
createExpenseViewModel.eventId.observe(viewLifecycleOwner) {
- findNavController().navigate(
- CreateExpenseFragmentDirections
- .actionCreateExpenseFragmentToGroupExpensesFragment(args.dataExpense.group)
- )
+ if (args.dataExpense.group.isOrganizer == null) {
+ findNavController().navigate(
+ CreateExpenseFragmentDirections
+ .actionCreateExpenseFragmentToDataConfirmationFragment(args.dataExpense.group)
+ )
+ } else if (args.dataExpense.group.isOrganizer!!) {
+ findNavController().navigate(
+ CreateExpenseFragmentDirections
+ .actionCreateExpenseFragmentToGroupExpensesFragment(args.dataExpense.group)
+ )
+ } else {
+ findNavController().navigate(
+ CreateExpenseFragmentDirections
+ .actionCreateExpenseFragmentToDataConfirmationFragment(args.dataExpense.group)
+ )
+ }
}
mainViewModel.usersInGroup.observe(viewLifecycleOwner) {
createExpenseViewModel.participants.value = it.map { user ->
@@ -100,6 +122,15 @@ class CreateExpenseFragment : Fragment(), AdapterListener {
}
}
+ private fun initOrganizer() {
+ if (args.dataExpense.group.isOrganizer == null) {
+ mainViewModel.getListOrganizers(args.dataExpense.group.id!!)
+ mainViewModel.organizers.observe(viewLifecycleOwner) {
+ args.dataExpense.group.isOrganizer = it.any { org -> org.id == app.userId }
+ }
+ }
+ }
+
override fun onClickItem(item: String) {
when (item) {
menuList[0] -> activity?.findNavController(R.id.innerFragment)
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/CreateGroupFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/CreateGroupFragment.kt
index 570f71d..f652eac 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/CreateGroupFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/CreateGroupFragment.kt
@@ -1,7 +1,6 @@
package ru.nsu.fit.modao.fragments
import android.os.Bundle
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -34,9 +33,11 @@ class CreateGroupFragment: Fragment() {
super.onViewCreated(view, savedInstanceState)
mainViewModel.groupId.observe(viewLifecycleOwner) {
- mainViewModel.getUserGroups()
- group?.id = it
- findNavController().navigate(CreateGroupFragmentDirections.actionCreateGroupFragmentToGroupInfoFragment(group!!))
+ mainViewModel.getGroupInfo(it)
+ }
+ mainViewModel.groupInfo.observe(viewLifecycleOwner) {
+ findNavController().navigate(CreateGroupFragmentDirections
+ .actionCreateGroupFragmentToGroupInfoFragment(it))
}
binding.buttonNext.setOnClickListener {
val name = binding.nameText.text.toString()
@@ -46,7 +47,6 @@ class CreateGroupFragment: Fragment() {
}
group = Group(typeGroup = 0, groupName = name,
description = binding.descriptionText.text.toString())
- Log.d("MyTag", "In button")
mainViewModel.createGroup(group!!)
}
}
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/CreateNewEventFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/CreateNewEventFragment.kt
index 25f09cf..a9f7c40 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/CreateNewEventFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/CreateNewEventFragment.kt
@@ -2,6 +2,7 @@ package ru.nsu.fit.modao.fragments
import android.app.AlertDialog
import android.os.Bundle
+import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -26,6 +27,7 @@ import javax.inject.Inject
class CreateNewEventFragment : Fragment() {
private var _binding: FragmentCreateNewEventBinding? = null
private val binding get() = _binding!!
+
@Inject
lateinit var app: App
private val createExpenseViewModel: CreateExpenseViewModel by activityViewModels()
@@ -48,38 +50,31 @@ class CreateNewEventFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+
mainViewModel.getUsersInGroup(args.group.id!!)
createExpenseViewModel.payFor = false
+ initObserver()
+ initButton()
+ initOrganizer()
+ }
+
+ private fun initOrganizer() {
+ if (args.group.isOrganizer == null) {
+ mainViewModel.getListOrganizers(args.group.id!!)
+ mainViewModel.organizers.observe(viewLifecycleOwner) {
+ args.group.isOrganizer = it.any { org -> org.id == app.userId }
+ }
+ }
+ }
+ private fun initButton() {
binding.grayNewTransfer.setOnClickListener {
changeMode(View.VISIBLE, View.GONE)
}
binding.grayNewExpense.setOnClickListener {
changeMode(View.GONE, View.VISIBLE)
}
- mainViewModel.usersInGroup.observe(viewLifecycleOwner) {
- val array = it.map { user ->
- createListParticipant(user)
- }.toTypedArray()
- createExpenseViewModel.users = array
- createExpenseViewModel.participants.value = array.clone()
- }
- createExpenseViewModel.message.observe(viewLifecycleOwner) {
- val builder = AlertDialog.Builder(context)
- builder.setMessage(it)
- builder.setPositiveButton("OK") { _, _ -> }
- builder.create().show()
- createExpenseViewModel.message.value = null
- }
- createExpenseViewModel.eventId.observe(viewLifecycleOwner) {
- if (lastEvent === it){
- return@observe
- }
- createExpenseViewModel.eventId.value = lastEvent
- findNavController().navigate(CreateNewEventFragmentDirections
- .actionCreateAnExpenseFragmentToGroupExpensesFragment(args.group))
- }
binding.buttonMoreOptions.setOnClickListener {
createExpenseViewModel.payFor = false
@@ -93,18 +88,26 @@ class CreateNewEventFragment : Fragment() {
}
val cost: Float
try {
- cost = binding.enterCost.text.toString().toFloat()
+ cost = binding.enterCost.text.toString().toFloat()
} catch (e: NumberFormatException) {
builder.setTitle("Enter cost")
builder.create().show()
return@setOnClickListener
}
- findNavController().navigate(CreateNewEventFragmentDirections
- .actionCreateAnExpenseFragmentToCreateExpenseFragment(CreationExpense(args.group, cost, description)))
+ findNavController().navigate(
+ CreateNewEventFragmentDirections
+ .actionCreateAnExpenseFragmentToCreateExpenseFragment(
+ CreationExpense(
+ args.group,
+ cost,
+ description
+ )
+ )
+ )
}
binding.buttonAll.setOnClickListener {
- //createExpenseViewModel.participants.value?.forEach { user -> user.selected = true }
+ createExpenseViewModel.participants.value?.forEach { user -> user.selected = true }
createExpenseViewModel.payFor = false
createExpenseViewModel.participants.value = createExpenseViewModel.users
Toast.makeText(context, "All members are selected", Toast.LENGTH_SHORT).show()
@@ -112,18 +115,24 @@ class CreateNewEventFragment : Fragment() {
binding.buttonTwo.setOnClickListener {
createExpenseViewModel.payFor = false
- findNavController().navigate(CreateNewEventFragmentDirections
- .actionCreateAnExpenseFragmentToSelectSecondParticipantFragment(args.group))
+ findNavController().navigate(
+ CreateNewEventFragmentDirections
+ .actionCreateAnExpenseFragmentToSelectSecondParticipantFragment(args.group)
+ )
}
binding.selectParticipant.setOnClickListener {
createExpenseViewModel.payFor = false
- findNavController().navigate(CreateNewEventFragmentDirections
- .actionCreateAnExpenseFragmentToSelectSecondParticipantFragment(args.group))
+ findNavController().navigate(
+ CreateNewEventFragmentDirections
+ .actionCreateAnExpenseFragmentToSelectSecondParticipantFragment(args.group)
+ )
}
binding.buttonPayFor.setOnClickListener {
createExpenseViewModel.payFor = true
- findNavController().navigate(CreateNewEventFragmentDirections
- .actionCreateAnExpenseFragmentToSelectSecondParticipantFragment(args.group))
+ findNavController().navigate(
+ CreateNewEventFragmentDirections
+ .actionCreateAnExpenseFragmentToSelectSecondParticipantFragment(args.group)
+ )
}
binding.buttonFinish.setOnClickListener {
var type = 0
@@ -138,8 +147,50 @@ class CreateNewEventFragment : Fragment() {
}
}
+ private fun initObserver() {
+ mainViewModel.usersInGroup.observe(viewLifecycleOwner) {
+ val array = it.map { user ->
+ createListParticipant(user)
+ }.toTypedArray()
+ createExpenseViewModel.users = array
+ createExpenseViewModel.participants.value = array.clone()
+ }
+ createExpenseViewModel.message.observe(viewLifecycleOwner) {
+ if (it != null) {
+ val builder = AlertDialog.Builder(context)
+ builder.setMessage(it)
+ builder.setPositiveButton("OK") { _, _ -> }
+ builder.create().show()
+ createExpenseViewModel.message.postValue(null)
+ } else Log.d("MyTag", "null")
+ }
- private fun changeMode(transfer: Int, expense: Int){
+ createExpenseViewModel.eventId.observe(viewLifecycleOwner) {
+ if (lastEvent === it) {
+ return@observe
+ }
+ createExpenseViewModel.eventId.value = lastEvent
+ if (args.group.isOrganizer == null) {
+ findNavController().navigate(
+ CreateNewEventFragmentDirections
+ .actionCreateAnExpenseFragmentToDataConfirmationFragment(args.group)
+ )
+ } else if (args.group.isOrganizer!!) {
+ findNavController().navigate(
+ CreateNewEventFragmentDirections
+ .actionCreateAnExpenseFragmentToGroupExpensesFragment(args.group)
+ )
+ } else {
+ findNavController().navigate(
+ CreateNewEventFragmentDirections
+ .actionCreateAnExpenseFragmentToDataConfirmationFragment(args.group)
+ )
+ }
+
+ }
+ }
+
+ private fun changeMode(transfer: Int, expense: Int) {
binding.grayNewExpense.visibility = transfer
binding.newExpenseButton.visibility = expense
binding.grayNewTransfer.visibility = expense
@@ -150,6 +201,7 @@ class CreateNewEventFragment : Fragment() {
binding.buttonAll.visibility = expense
binding.buttonPayFor.visibility = expense
}
+
private fun createListParticipant(user: User): ParticipantEvent {
return if (user.id == app.userId) {
ParticipantEvent(
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/DataConfirmationFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/DataConfirmationFragment.kt
index 971c1f7..b282522 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/DataConfirmationFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/DataConfirmationFragment.kt
@@ -2,11 +2,11 @@ package ru.nsu.fit.modao.fragments
import android.app.AlertDialog
import android.os.Bundle
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
+import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
@@ -22,16 +22,20 @@ import ru.nsu.fit.modao.databinding.PopUpWindowDataConfBinding
import ru.nsu.fit.modao.models.Expense
import ru.nsu.fit.modao.models.ExpenseListItem
import ru.nsu.fit.modao.models.LoadItems
-import ru.nsu.fit.modao.utils.Constants
+import ru.nsu.fit.modao.utils.App
import ru.nsu.fit.modao.viewmodels.MainViewModel
+import javax.inject.Inject
@AndroidEntryPoint
class DataConfirmationFragment : Fragment(), AdapterListener {
private var _binding: FragmentDataConfirmationBinding? = null
private val binding get() = _binding!!
private val mainViewModel: MainViewModel by viewModels()
+ @Inject
+ lateinit var app: App
private val adapter = ExpensesAdapter()
private val args by navArgs()
+ private var organizer = false
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentDataConfirmationBinding.inflate(inflater, container, false)
return binding.root
@@ -42,9 +46,25 @@ class DataConfirmationFragment : Fragment(), AdapterListener {
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+ class OnBack(enable: Boolean): OnBackPressedCallback(enable) {
+ override fun handleOnBackPressed() {
+ if (findNavController().currentBackStackEntry?.destination?.id == R.id.dataConfirmationFragment) {
+ if (findNavController().previousBackStackEntry?.destination?.id != R.id.groupInfoFragment) {
+ findNavController().navigate(DataConfirmationFragmentDirections
+ .actionDataConfirmationFragmentToGroupExpensesFragment(args.group))
+ } else {
+ findNavController().popBackStack()
+ }
+ } else {
+ findNavController().popBackStack()
+ }
+ }
+ }
+ activity?.onBackPressedDispatcher?.addCallback(viewLifecycleOwner, OnBack(true))
initObserver()
mainViewModel.getGroupUnconfirmedExpenses(args.group.id!!)
+ mainViewModel.getListOrganizers(args.group.id!!)
adapter.attachListener(this)
binding.recyclerUnconfirmed.layoutManager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false)
binding.recyclerUnconfirmed.adapter = adapter
@@ -52,7 +72,9 @@ class DataConfirmationFragment : Fragment(), AdapterListener {
private fun initObserver() {
mainViewModel.infoEvent.observe(viewLifecycleOwner) {item ->
- Log.d("MyTag", "infoEvent")
+ if (item == null) {
+ return@observe
+ }
val builder = AlertDialog.Builder(context)
val view = layoutInflater.inflate(R.layout.pop_up_window_data_conf, null)
val alertBinding = PopUpWindowDataConfBinding.bind(view)
@@ -60,6 +82,11 @@ class DataConfirmationFragment : Fragment(), AdapterListener {
alertBinding.cost.text = item.price?.toString()
alertBinding.description.text = item.name
alertBinding.whoCreated.text = item.usernameCreator
+ if (!organizer || args.group.typeGroup == 1) {
+ alertBinding.noButton.visibility = View.GONE
+ alertBinding.yesButton.visibility = View.GONE
+ alertBinding.textConfirm.visibility = View.GONE
+ }
val dialog = builder.create()
alertBinding.noButton.setOnClickListener {
val id = item.id
@@ -80,15 +107,18 @@ class DataConfirmationFragment : Fragment(), AdapterListener {
}
dialog.show()
+ mainViewModel.infoEvent.postValue(null)
}
mainViewModel.unconfirmedExpenses.observe(viewLifecycleOwner){
val list: MutableList = it.toMutableList()
- if (it.size == Constants.PAGE_SIZE) {
- list.add(Constants.PAGE_SIZE - 5, LoadItems(isLoad = false))
- }
adapter.setList(list.toTypedArray())
}
+ mainViewModel.organizers.observe(viewLifecycleOwner) {
+ organizer = it.any { org -> org.id == app.userId }
+ }
}
+
+
override fun onClickItem(item: ExpenseListItem) {
when (item) {
is LoadItems -> {
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/FriendsFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/FriendsFragment.kt
index 41ce4dd..c5cf9e7 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/FriendsFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/FriendsFragment.kt
@@ -15,6 +15,10 @@ import ru.nsu.fit.modao.adapter.FriendsAdapter
import ru.nsu.fit.modao.databinding.FragmentFriendsBinding
import ru.nsu.fit.modao.models.User
import ru.nsu.fit.modao.viewmodels.MainViewModel
+import ru.tinkoff.decoro.MaskImpl
+import ru.tinkoff.decoro.parser.UnderscoreDigitSlotsParser
+import ru.tinkoff.decoro.watchers.MaskFormatWatcher
+
@AndroidEntryPoint
class FriendsFragment : Fragment(), AdapterListener {
private var _binding: FragmentFriendsBinding? = null
@@ -38,7 +42,6 @@ class FriendsFragment : Fragment(), AdapterListener {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
-
adapter.setListener(this)
binding.friendsRecycler.layoutManager =
LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false)
@@ -58,14 +61,16 @@ class FriendsFragment : Fragment(), AdapterListener {
builder.setPositiveButton("OK") { _, _ -> }
builder.create().show()
}
+ val slots = UnderscoreDigitSlotsParser().parseSlots("___-___-___")
+ MaskFormatWatcher(MaskImpl.createTerminated(slots)).installOn(binding.AddByUUID)
}
override fun onClickItem(item: User) {
- val builder = AlertDialog.Builder(context)
+ /*val builder = AlertDialog.Builder(context)
builder.setTitle(item.username)
builder.setMessage("Phone: " + item.phone_number + "\n" + "Bank: " + item.bank)
builder.setPositiveButton("OK") { _, _ -> }
- builder.create().show()
+ builder.create().show()*/
}
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/GroupExpensesFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/GroupExpensesFragment.kt
index e3c8ec1..f11dd71 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/GroupExpensesFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/GroupExpensesFragment.kt
@@ -1,12 +1,12 @@
package ru.nsu.fit.modao.fragments
import android.app.AlertDialog
+import android.graphics.Paint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.PopupWindow
-import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
@@ -24,10 +24,10 @@ import ru.nsu.fit.modao.databinding.PopUpWindowDataConfBinding
import ru.nsu.fit.modao.models.Expense
import ru.nsu.fit.modao.models.ExpenseListItem
import ru.nsu.fit.modao.models.LoadItems
+import ru.nsu.fit.modao.utils.App
import ru.nsu.fit.modao.utils.Constants.Companion.PAGE_SIZE
import ru.nsu.fit.modao.viewmodels.MainViewModel
-import java.text.DateFormat
-import java.util.*
+import javax.inject.Inject
@AndroidEntryPoint
class GroupExpensesFragment : Fragment(), AdapterListener {
@@ -36,14 +36,22 @@ class GroupExpensesFragment : Fragment(), AdapterListener {
private val adapter = ExpensesAdapter()
private val args by navArgs()
private val mainViewModel: MainViewModel by viewModels()
+ @Inject
+ lateinit var app: App
private var showEvent = true
private var showTransfer = true
private var showOnlyMy = false
private var lastEvent: Expense? = null
private lateinit var window: PopupWindow
+ private var totalPages = 2
+ private var lastPage = 0
private lateinit var bindingPopupWindow: FilterExpensesBinding
+ private var newList = true
+ private var minTime: Long = 0
+ private var maxTime: Long = 9999999999999L
private val Boolean.intValue
get() = if (this) 1 else 0
+
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -58,24 +66,62 @@ class GroupExpensesFragment : Fragment(), AdapterListener {
_binding = null
}
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ mainViewModel.getGroupExpenses(
+ args.group.id!!,
+ showOnlyMy.intValue,
+ 2,
+ minTime,
+ maxTime,
+ 0,
+ PAGE_SIZE
+ )
+ }
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
-
+ newList = true
+ lastPage = 0
+ minTime = 0
+ maxTime = 9999999999999L
setRecycler()
setButtonOnClick()
setPopupWindow()
- mainViewModel.getGroupExpenses(args.group.id!!, showOnlyMy.intValue, 2)
setObserver()
+ initOrganizer()
}
+ private fun initOrganizer() {
+ if (args.group.isOrganizer == null) {
+ mainViewModel.getListOrganizers(args.group.id!!)
+ mainViewModel.organizers.observe(viewLifecycleOwner) {
+ args.group.isOrganizer = it.any { org -> org.id == app.userId }
+ }
+ }
+ }
private fun setObserver() {
mainViewModel.expenses.observe(viewLifecycleOwner) {
+
val list: MutableList = it.toMutableList()
- if (it.size > PAGE_SIZE) {
- list.add(PAGE_SIZE - 5, LoadItems(isLoad = false))
+
+ if (totalPages > lastPage + 1) {
+ lastPage++
+ if (list.size > PAGE_SIZE - 5) {
+ list.add(PAGE_SIZE - 5, LoadItems(isLoad = false, lastPage))
+ }
+ }
+ if (newList) {
+ newList = false
+ adapter.setList(list.toTypedArray())
+ } else {
+ adapter.addItems(list.toTypedArray())
}
- adapter.setList(list.toTypedArray())
+
+ }
+ mainViewModel.totalPages.observe(viewLifecycleOwner) {
+ totalPages = it
}
mainViewModel.infoEvent.observe(viewLifecycleOwner) {
@@ -94,16 +140,33 @@ class GroupExpensesFragment : Fragment(), AdapterListener {
bindingAlert.textConfirm.visibility = View.GONE
builder.setView(bindingAlert.root)
val dialog = builder.create()
- bindingAlert.buttonDetails.setOnClickListener {_ ->
- dialog.dismiss()
- findNavController().navigate(GroupExpensesFragmentDirections
- .actionGroupExpensesFragmentToSeeDetailsFragment(false, it))
+ if (it.status != -2) {
+ bindingAlert.buttonDetails.setOnClickListener { _ ->
+ dialog.dismiss()
+ val action = GroupExpensesFragmentDirections
+ .actionGroupExpensesFragmentToSeeDetailsFragment(false, it)
+ action.group = args.group
+ findNavController().navigate(action)
+ }
+ } else {
+ bindingAlert.buttonDetails.text = "See deleted event"
+ bindingAlert.buttonDetails.paintFlags =
+ bindingAlert.buttonDetails.paintFlags or Paint.UNDERLINE_TEXT_FLAG
+ bindingAlert.buttonDetails.setOnClickListener {_ ->
+ dialog.dismiss()
+ mainViewModel.getEventInfo(it.deleteId!!, args.group.id!!)
+ }
}
+
dialog.show()
}
}
+
private fun setButtonOnClick() {
+ if (args.group.typeGroup == 1) {
+ binding.buttonAddEvent.visibility = View.GONE
+ }
binding.buttonAddEvent.setOnClickListener {
findNavController().navigate(
GroupExpensesFragmentDirections
@@ -125,42 +188,44 @@ class GroupExpensesFragment : Fragment(), AdapterListener {
showDatePicker()
}
}
- private fun showDatePicker(){
+
+ private fun showDatePicker() {
val dialog = MaterialDatePicker.Builder.dateRangePicker()
.setTheme(R.style.MaterialCalendarTheme)
.setPositiveButtonText("Save")
.setNegativeButtonText("Cancel")
.build()
dialog.addOnPositiveButtonClickListener {
- val date1 = Date(it.first)
- val date2 = Date(it.second)
- Toast.makeText(context, "${DateFormat.getDateInstance().format(date1)} " +
- "- ${DateFormat.getDateInstance().format(date2)}",
- Toast.LENGTH_LONG).show()
+ minTime = it.first - 3600000 * 3
+ maxTime = it.second + 3600000 * 21
+ getGroupExpenses()
}
dialog.show(childFragmentManager, "MyTag")
}
- private fun setRecycler(){
+
+ private fun setRecycler() {
adapter.attachListener(this)
binding.expensesRecycler.layoutManager =
LinearLayoutManager(this.context, RecyclerView.VERTICAL, false)
binding.expensesRecycler.adapter = adapter
}
- private fun setPopupWindow(){
+ private fun setPopupWindow() {
window = PopupWindow(context)
- val view = LayoutInflater.from(context).inflate(R.layout.filter_expenses, binding.root, false)
+ val view =
+ LayoutInflater.from(context).inflate(R.layout.filter_expenses, binding.root, false)
bindingPopupWindow = FilterExpensesBinding.bind(view)
window.contentView = bindingPopupWindow.root
- window.isFocusable = true
bindingPopupWindow.event.isChecked = true
bindingPopupWindow.transfer.isChecked = true
+ window.isFocusable = true
setButton()
}
- private fun setButton(){
+
+ private fun setButton() {
bindingPopupWindow.transfer.setOnClickListener {
- if (showTransfer){
- if (bindingPopupWindow.event.isChecked){
+ if (showTransfer) {
+ if (bindingPopupWindow.event.isChecked) {
showTransfer = false
bindingPopupWindow.transfer.isChecked = false
}
@@ -189,19 +254,21 @@ class GroupExpensesFragment : Fragment(), AdapterListener {
getGroupExpenses()
}
}
- private fun getGroupExpenses(){
- if (bindingPopupWindow.transfer.isChecked){
- if (bindingPopupWindow.event.isChecked) {
- mainViewModel.getGroupExpenses(args.group.id!!, showOnlyMy.intValue, 2)
- } else {
- mainViewModel.getGroupExpenses(args.group.id!!, showOnlyMy.intValue, 1)
- }
- } else {
- if (bindingPopupWindow.event.isChecked) {
- mainViewModel.getGroupExpenses(args.group.id!!, showOnlyMy.intValue, 0)
- }
- }
+
+ private fun getGroupExpenses() {
+ newList = true
+ lastPage = 0
+ mainViewModel.getGroupExpenses(
+ args.group.id!!,
+ showOnlyMy.intValue,
+ getFilter(),
+ minTime,
+ maxTime,
+ 0,
+ PAGE_SIZE
+ )
}
+
override fun onClickItem(item: ExpenseListItem) {
when (item) {
is Expense -> mainViewModel.getEventInfo(item.id!!, args.group.id!!)
@@ -210,8 +277,17 @@ class GroupExpensesFragment : Fragment(), AdapterListener {
return
}
item.isLoad = true
+ mainViewModel.getGroupExpenses(
+ args.group.id!!, showOnlyMy.intValue,
+ getFilter(), minTime, maxTime, item.page, PAGE_SIZE
+ )
}
}
+ }
+ private fun getFilter(): Int {
+ return if (bindingPopupWindow.transfer.isChecked) {
+ if (bindingPopupWindow.event.isChecked) 2 else 1
+ } else 0
}
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/GroupInfoFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/GroupInfoFragment.kt
index 15a38b2..10739f1 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/GroupInfoFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/GroupInfoFragment.kt
@@ -1,7 +1,7 @@
package ru.nsu.fit.modao.fragments
+import android.graphics.Color
import android.os.Bundle
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -41,22 +41,24 @@ class GroupInfoFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
if (args.notification && first) {
- Log.d("MyTag", "group info to data")
first = false
findNavController().navigate(GroupInfoFragmentDirections
.actionGroupInfoFragmentToDataConfirmationFragment(args.group))
}
binding.nameGroup.text = args.group.groupName
-
- mainViewModel.getListOrganizers(args.group.id!!)
- mainViewModel.organizers.observe(viewLifecycleOwner) {
- val isOrganizer = it.any { org -> org.id == app.userId }
- if (isOrganizer) {
- binding.buttonDataConfirmation.visibility = View.VISIBLE
- binding.textDataConfirmation.visibility = View.VISIBLE
- }
+ if (args.group.typeGroup == 1) {
+ binding.status.setTextColor(Color.parseColor("#FF00BCD4"))
+ binding.status.text = "Archived"
+ } else {
+ binding.status.setTextColor(Color.parseColor("#1AE622"))
+ binding.status.text = "Active"
}
+ mainViewModel.getListOrganizers(args.group.id!!)
+ initObserver()
+ initButton()
+ }
+ private fun initButton() {
binding.buttonGroupExpenses.setOnClickListener {
findNavController().navigate(
GroupInfoFragmentDirections.actionGroupInfoFragmentToGroupExpensesFragment(
@@ -85,5 +87,12 @@ class GroupInfoFragment : Fragment() {
)
)
}
+
+ }
+ private fun initObserver() {
+ mainViewModel.organizers.observe(viewLifecycleOwner) {
+ args.group.isOrganizer = it.any { org -> org.id == app.userId }
+ }
+
}
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/GroupInformationFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/GroupInformationFragment.kt
index d5f6ce1..07380ca 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/GroupInformationFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/GroupInformationFragment.kt
@@ -2,16 +2,22 @@ package ru.nsu.fit.modao.fragments
import android.os.Bundle
+import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
+import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import dagger.hilt.android.AndroidEntryPoint
+import ru.nsu.fit.modao.R
import ru.nsu.fit.modao.databinding.FragmentGroupInformationBinding
import ru.nsu.fit.modao.utils.App
+import ru.nsu.fit.modao.utils.Constants
import ru.nsu.fit.modao.viewmodels.MainViewModel
+import java.time.LocalDateTime
+import java.time.format.DateTimeFormatter
import javax.inject.Inject
@AndroidEntryPoint
@@ -19,33 +25,97 @@ class GroupInformationFragment : Fragment() {
private var _binding: FragmentGroupInformationBinding? = null
private val binding get() = _binding!!
private val mainViewModel: MainViewModel by viewModels()
+
@Inject
lateinit var app: App
private val args by navArgs()
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
_binding = FragmentGroupInformationBinding.inflate(inflater, container, false)
return binding.root
}
+
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainViewModel.getGroupInfo(args.group.id!!)
- mainViewModel.groupInfo.observe(viewLifecycleOwner) {
- binding.groupName.text = it.groupName
- binding.groupUuid.text = it.uuid
- binding.groupDescription.text = it.description
+ initView()
+ initButton()
+ initObserver()
+ }
+ private fun initView() {
+ val time = LocalDateTime.parse(args.group.time)
+ val pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
+ binding.dataCreation.text = time.format(pattern)
+ if (args.group.isOrganizer == null) {
+ mainViewModel.getListOrganizers(args.group.id!!)
+ } else if (args.group.isOrganizer!!) {
+ binding.archiveGroup.visibility = View.VISIBLE
+ binding.deleteGroup.visibility = View.VISIBLE
+ binding.titleGroupUuid.visibility = View.VISIBLE
+ binding.groupUuid.visibility = View.VISIBLE
+ }
+
+ }
+ private fun initButton() {
+ if (args.group.typeGroup == 1) {
+ binding.archiveGroup.setText(R.string.makeGroupActive)
+ binding.archiveGroup.setOnClickListener {
+ mainViewModel.makeGroupActive(args.group.id!!)
+ }
+ } else {
+ binding.archiveGroup.setOnClickListener {
+ mainViewModel.archiveGroup(args.group.id!!)
+ }
}
- mainViewModel.getListOrganizers(args.group.id!!)
+ binding.deleteGroup.setOnClickListener {
+ mainViewModel.deleteGroup(args.group.id!!)
+ }
+ }
+
+ private fun initObserver() {
mainViewModel.organizers.observe(viewLifecycleOwner) {
val isOrganizer = it.any { org -> org.id == app.userId }
+ args.group.isOrganizer = isOrganizer
if (isOrganizer) {
+ binding.archiveGroup.visibility = View.VISIBLE
+ binding.deleteGroup.visibility = View.VISIBLE
binding.titleGroupUuid.visibility = View.VISIBLE
binding.groupUuid.visibility = View.VISIBLE
}
}
+ mainViewModel.groupInfo.observe(viewLifecycleOwner) {
+ binding.groupName.text = it.groupName
+ binding.groupUuid.text = it.uuid
+ binding.groupDescription.text = it.description
+ }
+ mainViewModel.tipMessage.observe(viewLifecycleOwner) {
+ when (it) {
+ "Deleted" -> findNavController().navigate(
+ GroupInformationFragmentDirections
+ .actionGlobalNestedGroups()
+ )
+
+ "Archived" -> findNavController().navigate(
+ GroupInformationFragmentDirections
+ .actionGlobalNestedGroups()
+ )
+
+ Constants.SUCCESS -> findNavController().navigate(
+ GroupInformationFragmentDirections
+ .actionGlobalNestedGroups()
+ )
+
+ else -> Log.d("MyTag", "Unknown message $it")
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/GroupMembersFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/GroupMembersFragment.kt
index e839986..b22094a 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/GroupMembersFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/GroupMembersFragment.kt
@@ -16,7 +16,10 @@ import ru.nsu.fit.modao.adapter.AdapterListener
import ru.nsu.fit.modao.adapter.FriendsAdapter
import ru.nsu.fit.modao.databinding.FragmentGroupMembersBinding
import ru.nsu.fit.modao.models.User
+import ru.nsu.fit.modao.utils.App
import ru.nsu.fit.modao.viewmodels.MainViewModel
+import javax.inject.Inject
+
@AndroidEntryPoint
class GroupMembersFragment : Fragment(), AdapterListener {
private var _binding: FragmentGroupMembersBinding? = null
@@ -24,6 +27,9 @@ class GroupMembersFragment : Fragment(), AdapterListener {
private val mainViewModel: MainViewModel by viewModels()
private val args by navArgs()
private val adapter = FriendsAdapter()
+ private var organizer = false
+ @Inject
+ lateinit var app: App
override fun onCreateView(
inflater: LayoutInflater,
@@ -51,7 +57,7 @@ class GroupMembersFragment : Fragment(), AdapterListener {
mainViewModel.usersInGroup.observe(viewLifecycleOwner) {
adapter.setFriendsList(it)
}
-
+ mainViewModel.getListOrganizers(args.group.id!!)
mainViewModel.getUsersInGroup(args.group.id!!)
binding.buttonAddMember.setOnClickListener {
findNavController().navigate(GroupMembersFragmentDirections
@@ -63,15 +69,26 @@ class GroupMembersFragment : Fragment(), AdapterListener {
builder.setPositiveButton("OK") { _, _ -> }
builder.create().show()
}
+ mainViewModel.organizers.observe(viewLifecycleOwner) {
+ organizer = it.any { org -> org.id == app.userId }
+ }
}
override fun onClickItem(item: User) {
- val builder = AlertDialog.Builder(context)
- builder.setTitle(item.username)
- builder.setMessage("Phone: " + item.phone_number + "\n" + "Bank: " + item.bank)
- builder.setPositiveButton("OK") { _, _ -> }
- builder.create().show()
+
+ /*if (organizer && item.id != app.userId) {
+ val builder = AlertDialog.Builder(context)
+ builder.setTitle(item.username)
+ builder.setPositiveButton("OK") { _, _ -> }
+ if (organizer) {
+ builder.setNegativeButton("Delete user") { _, _ ->
+ mainViewModel.deleteUser(args.group.id!!, item.id!!)
+ }
+ }
+ builder.create().show()
+ }*/
+
}
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/GroupsFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/GroupsFragment.kt
index 6bcd0ae..7b54785 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/GroupsFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/GroupsFragment.kt
@@ -2,10 +2,11 @@ package ru.nsu.fit.modao.fragments
import android.app.AlertDialog
import android.os.Bundle
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.PopupWindow
+import android.widget.RadioButton
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
@@ -13,11 +14,17 @@ import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.hilt.android.AndroidEntryPoint
+import ru.nsu.fit.modao.R
import ru.nsu.fit.modao.adapter.AdapterListener
import ru.nsu.fit.modao.adapter.GroupAdapter
+import ru.nsu.fit.modao.databinding.FilterGroupsBinding
import ru.nsu.fit.modao.databinding.FragmentGroupsBinding
import ru.nsu.fit.modao.models.Group
import ru.nsu.fit.modao.viewmodels.MainViewModel
+import ru.tinkoff.decoro.MaskImpl
+import ru.tinkoff.decoro.parser.UnderscoreDigitSlotsParser
+import ru.tinkoff.decoro.watchers.MaskFormatWatcher
+
@AndroidEntryPoint
class GroupsFragment : Fragment(), AdapterListener {
private var _binding: FragmentGroupsBinding? = null
@@ -25,6 +32,9 @@ class GroupsFragment : Fragment(), AdapterListener {
private val adapter: GroupAdapter = GroupAdapter()
private val mainViewModel: MainViewModel by viewModels()
private val args by navArgs()
+ private lateinit var window: PopupWindow
+ private lateinit var bindingPopupWindow: FilterGroupsBinding
+ private var lastSelect: RadioButton? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -42,18 +52,17 @@ class GroupsFragment : Fragment(), AdapterListener {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+ setPopupWindow()
if (args.notification){
mainViewModel.getGroupInfo(args.groupId)
- Log.d("MyTag", "Notification")
mainViewModel.groupInfo.observe(viewLifecycleOwner) {
- Log.d("MyTag", "groups to group info")
val action = GroupsFragmentDirections.actionGroupsFragmentToGroupInfoFragment(it)
action.notification = true
findNavController().navigate(action)
}
}
- mainViewModel.getUserGroups()
+ mainViewModel.getUserGroups(0)
adapter.attachListener(this)
mainViewModel.userGroups.observe(viewLifecycleOwner){
adapter.setGroups(it)
@@ -74,11 +83,49 @@ class GroupsFragment : Fragment(), AdapterListener {
builder.setPositiveButton("OK") { _, _ -> }
builder.create().show()
}
-
-
+ binding.filterIcon.setOnClickListener {
+ window.showAsDropDown(binding.filterIcon, -250, 0)
+ }
+ val slots = UnderscoreDigitSlotsParser().parseSlots("___-___-___")
+ MaskFormatWatcher(MaskImpl.createTerminated(slots)).installOn(binding.editGroupUUID)
}
override fun onClickItem(item: Group) {
findNavController().navigate(GroupsFragmentDirections.actionGroupsFragmentToGroupInfoFragment(item))
}
+ private fun setPopupWindow(){
+ window = PopupWindow(context)
+ val view = LayoutInflater.from(context).inflate(R.layout.filter_groups, binding.root, false)
+ bindingPopupWindow = FilterGroupsBinding.bind(view)
+ window.contentView = bindingPopupWindow.root
+ window.isFocusable = true
+ bindingPopupWindow.active.isChecked = true
+ lastSelect = bindingPopupWindow.active
+ setButton()
+ }
+ private fun setButton() {
+ bindingPopupWindow.active.setOnClickListener {
+ if (switch(bindingPopupWindow.active)) {
+ mainViewModel.getUserGroups(0)
+ }
+ }
+ bindingPopupWindow.archive.setOnClickListener {
+ if (switch(bindingPopupWindow.archive)) {
+ mainViewModel.getUserGroups(1)
+ }
+ }
+ bindingPopupWindow.allGroups.setOnClickListener {
+ if (switch(bindingPopupWindow.allGroups)) {
+ mainViewModel.getUserGroups(2)
+ }
+ }
+ }
+ private fun switch(radioButton: RadioButton): Boolean {
+ if (lastSelect !== radioButton) {
+ lastSelect?.isChecked = false
+ lastSelect = radioButton
+ return true
+ }
+ return false
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/ProfileFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/ProfileFragment.kt
index fcdd5c5..a6eb27a 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/ProfileFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/ProfileFragment.kt
@@ -1,9 +1,13 @@
package ru.nsu.fit.modao.fragments
+import android.content.ClipData
+import android.content.ClipboardManager
+import android.content.Context.CLIPBOARD_SERVICE
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
@@ -12,6 +16,8 @@ import dagger.hilt.android.AndroidEntryPoint
import ru.nsu.fit.modao.R
import ru.nsu.fit.modao.databinding.FragmentProfileBinding
import ru.nsu.fit.modao.utils.App
+import ru.nsu.fit.modao.utils.Constants.Companion.FAIL
+import ru.nsu.fit.modao.utils.Constants.Companion.SUCCESS
import ru.nsu.fit.modao.viewmodels.MainViewModel
import javax.inject.Inject
@AndroidEntryPoint
@@ -34,19 +40,32 @@ class ProfileFragment: Fragment() {
mainViewModel.user.observe(viewLifecycleOwner){
binding.personName.text = it.username
- binding.personBank.text = it.bank
- binding.personPhone.text = it.phone_number
binding.personUuid.text = it.uuid
}
mainViewModel.getUser()
binding.logOutLayout.setOnClickListener {
- activity?.findViewById(R.id.bottomMenu)?.visibility = View.GONE
- val sharedPreferences = app.encryptedSharedPreferences
- sharedPreferences.edit().clear().apply()
- findNavController().navigate(ProfileFragmentDirections
- .actionProfileFragmentToAuthorizationFragment())
+ mainViewModel.exit()
+ }
+ binding.personUuid.setOnLongClickListener {
+ val clipboard = context?.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager?
+ val clip = ClipData.newPlainText("text", binding.personUuid.text.toString())
+ clipboard?.setPrimaryClip(clip)
+ Toast.makeText(context, "Copied!", Toast.LENGTH_LONG).show()
+ true
+ }
+ mainViewModel.tipMessage.observe(viewLifecycleOwner) {
+ when (it) {
+ FAIL -> Toast.makeText(context,
+ "Check internet connection", Toast.LENGTH_LONG).show()
+ SUCCESS -> {
+ activity?.findViewById(R.id.bottomMenu)?.visibility = View.GONE
+ val sharedPreferences = app.encryptedSharedPreferences
+ sharedPreferences.edit().clear().apply()
+ findNavController().navigate(ProfileFragmentDirections
+ .actionProfileFragmentToAuthorizationFragment())
+ }
+ }
}
-
}
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/RegistrationFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/RegistrationFragment.kt
index 0df9d57..b4cec57 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/RegistrationFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/RegistrationFragment.kt
@@ -39,7 +39,7 @@ class RegistrationFragment: Fragment() {
binding.tipMessage.text = it
}
loginViewModel.userId.observe(viewLifecycleOwner) {
- loginViewModel.login(login = login!!, password = password!!)
+ loginViewModel.login(login = login!!, password = password!!, app.deviceToken)
}
loginViewModel.token.observe(viewLifecycleOwner) {
app.userId = it.id
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/SeeDetailsFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/SeeDetailsFragment.kt
index a80ef4e..c49b600 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/SeeDetailsFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/SeeDetailsFragment.kt
@@ -5,6 +5,7 @@ import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.Toast
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
@@ -14,7 +15,13 @@ import dagger.hilt.android.AndroidEntryPoint
import ru.nsu.fit.modao.adapter.ParticipantsEventAdapter
import ru.nsu.fit.modao.databinding.FragmentSeeDetailsBinding
import ru.nsu.fit.modao.models.ParticipantEvent
+import ru.nsu.fit.modao.utils.App
+import ru.nsu.fit.modao.utils.Constants.Companion.FAIL
+import ru.nsu.fit.modao.utils.Constants.Companion.SUCCESS
import ru.nsu.fit.modao.viewmodels.MainViewModel
+import java.time.LocalDateTime
+import java.time.format.DateTimeFormatter
+import javax.inject.Inject
@AndroidEntryPoint
class SeeDetailsFragment : Fragment() {
@@ -23,6 +30,8 @@ class SeeDetailsFragment : Fragment() {
private val adapter = ParticipantsEventAdapter()
private val args by navArgs()
private val mainViewModel: MainViewModel by viewModels()
+ @Inject
+ lateinit var app: App
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -39,11 +48,22 @@ class SeeDetailsFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
-
+ initOrganizer()
setRecycler()
initView()
+ initObserver()
-
+ }
+ private fun initOrganizer() {
+ if (args.group?.isOrganizer == null) {
+ mainViewModel.getListOrganizers(args.group?.id!!)
+ mainViewModel.organizers.observe(viewLifecycleOwner) {
+ args.group?.isOrganizer = it.any { org -> org.id == app.userId }
+ processOrganizer(args.group?.isOrganizer!!)
+ }
+ } else {
+ processOrganizer(args.group?.isOrganizer!!)
+ }
}
private fun setRecycler(){
val list = args.expense.expenseDtoList?.map {
@@ -58,6 +78,7 @@ class SeeDetailsFragment : Fragment() {
binding.whoParticipatedRecycler.layoutManager =
LinearLayoutManager(context, RecyclerView.VERTICAL, false)
binding.whoParticipatedRecycler.adapter = adapter
+ binding.deleteButton
}
private fun initView(){
if (!args.isConfirmation){
@@ -68,22 +89,56 @@ class SeeDetailsFragment : Fragment() {
else {
initButton()
}
+
+ binding.deleteButton.setOnClickListener {
+ mainViewModel.deleteEvent(args.group?.id!!, args.expense.id!!, args.expense.name!!)
+ }
+ val time = LocalDateTime.parse(args.expense.time)
+ val pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
binding.theCost.text = args.expense.price.toString()
binding.theSpender.text = args.expense.usernamePaying
binding.theCreator.text = args.expense.usernameCreator
+ binding.theDate.text = time.format(pattern)
+ binding.expenseName.text = args.expense.name
}
private fun initButton() {
binding.noButton2.setOnClickListener {
val id = args.expense.id
- mainViewModel.notConfirmEvent(args.group!!.id!!, id!!.toLong())
- findNavController().navigate(SeeDetailsFragmentDirections
- .actionSeeDetailsFragmentToDataConfirmationFragment(args.group!!))
+ mainViewModel.notConfirmEvent(args.group!!.id!!, id!!)
}
binding.yesButton2.setOnClickListener {
val id = args.expense.id
- mainViewModel.confirmEvent(args.group!!.id!!, id!!.toLong())
- findNavController().navigate(SeeDetailsFragmentDirections
- .actionSeeDetailsFragmentToDataConfirmationFragment(args.group!!))
+ mainViewModel.confirmEvent(args.group!!.id!!, id!!)
+ }
+
+ }
+ private fun processOrganizer(isOrganizer: Boolean) {
+ if (isOrganizer && !args.isConfirmation && args.expense.status!! >= 0) {
+ binding.deleteButton.visibility = View.VISIBLE
+ }
+ if (!isOrganizer) {
+ binding.noButton2.visibility = View.GONE
+ binding.yesButton2.visibility = View.GONE
+ binding.textConfirm2.visibility = View.GONE
+ } else if (args.isConfirmation) {
+ binding.noButton2.visibility = View.VISIBLE
+ binding.yesButton2.visibility = View.VISIBLE
+ binding.textConfirm2.visibility = View.VISIBLE
+ }
+ }
+
+ private fun initObserver() {
+ mainViewModel.tipMessage.observe(viewLifecycleOwner) {
+ when (it) {
+ SUCCESS -> {
+ Toast.makeText(context, "Deleted", Toast.LENGTH_LONG).show()
+ findNavController().navigate(SeeDetailsFragmentDirections
+ .actionSeeDetailsFragmentToGroupExpensesFragment(args.group!!))
+ }
+ FAIL -> Toast.makeText(context, "Fail", Toast.LENGTH_LONG).show()
+ "OK" -> findNavController().navigate(SeeDetailsFragmentDirections
+ .actionSeeDetailsFragmentToDataConfirmationFragment(args.group!!))
+ }
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/SelectSecondParticipantFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/SelectSecondParticipantFragment.kt
index a847a35..7ca3131 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/SelectSecondParticipantFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/SelectSecondParticipantFragment.kt
@@ -47,10 +47,8 @@ class SelectSecondParticipantFragment : BottomSheetDialogFragment(),
initRecycler()
binding.buttonDone.setOnClickListener {
//createExpenseViewModel.users.forEach { Log.d("MyTag", "${it.username!!} select ${it.selected} sponsor ${it.isSponsor}") }
- createExpenseViewModel.participants.value = createExpenseViewModel.users.filter {
- it.id == app.userId ||
- it.id == lastUser?.id
- }.toTypedArray()
+ createExpenseViewModel.participants.value?.forEach { it.selected = it.id == app.userId ||
+ it.id == lastUser?.id }
//createExpenseViewModel.participants.value?.forEach { Log.d("MyTag", "${it.username!!} select ${it.selected} sponsor ${it.isSponsor}") }
findNavController().popBackStack(R.id.createAnExpenseFragment, inclusive = false)
}
diff --git a/app/src/main/java/ru/nsu/fit/modao/fragments/StartFragment.kt b/app/src/main/java/ru/nsu/fit/modao/fragments/StartFragment.kt
index ca9c313..630c158 100644
--- a/app/src/main/java/ru/nsu/fit/modao/fragments/StartFragment.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/fragments/StartFragment.kt
@@ -12,6 +12,7 @@ import com.google.android.material.bottomnavigation.BottomNavigationView
import dagger.hilt.android.AndroidEntryPoint
import ru.nsu.fit.modao.R
import ru.nsu.fit.modao.databinding.FragmentStartBinding
+import ru.nsu.fit.modao.models.Tokens
import ru.nsu.fit.modao.notification.PushService.Companion.KEY_ACTION
import ru.nsu.fit.modao.notification.PushService.Companion.KEY_GROUP_ID
import ru.nsu.fit.modao.notification.PushService.Companion.TO_DATA_CONFIRMATION
@@ -19,6 +20,7 @@ import ru.nsu.fit.modao.notification.PushService.Companion.TO_NOTIFICATION
import ru.nsu.fit.modao.utils.App
import ru.nsu.fit.modao.utils.Constants.Companion.ACCESS_TOKEN
import ru.nsu.fit.modao.utils.Constants.Companion.ID_USER
+import ru.nsu.fit.modao.utils.Constants.Companion.REFRESH_TOKEN
import ru.nsu.fit.modao.viewmodels.MainViewModel
import javax.inject.Inject
@@ -41,11 +43,20 @@ class StartFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
val sharedPreferences = app.encryptedSharedPreferences
- val accessToken: String? = sharedPreferences.getString(ACCESS_TOKEN, null)
- if (accessToken == null){
+ val refreshToken = sharedPreferences.getString(REFRESH_TOKEN, null)
+ if (refreshToken == null){
findNavController().navigate(StartFragmentDirections.actionStartFragmentToAuthorizationFragment())
} else {
- app.accessToken = accessToken
+ mainViewModel.getRefreshToken(Tokens(refreshToken = refreshToken))
+ }
+ mainViewModel.tokens.observe(viewLifecycleOwner) {
+ app.accessToken = it.accessToken
+ if (it.refreshToken != null) {
+ app.refreshToken = it.refreshToken
+ }
+ val edit = sharedPreferences.edit()
+ edit.putString(ACCESS_TOKEN, it.accessToken)
+ .putString(REFRESH_TOKEN, it.refreshToken).apply()
app.userId = sharedPreferences.getLong(ID_USER, -1)
binding.progressBar.visibility = View.VISIBLE
mainViewModel.getUser()
diff --git a/app/src/main/java/ru/nsu/fit/modao/models/Expense.kt b/app/src/main/java/ru/nsu/fit/modao/models/Expense.kt
index 732f7ab..69a7126 100644
--- a/app/src/main/java/ru/nsu/fit/modao/models/Expense.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/models/Expense.kt
@@ -8,9 +8,13 @@ data class Expense (
val currency: Currency? = null,
val id: Long? = null,
val type: Int = 0,
+ val description: String = "Description",
val name: String? = null,
val groupId: Long? = null,
val price: Float? = null,
+ val deleteId: Long? = null,
+ val time: String? = null,
+ val status: Int? = null,
val userPayingId: Long? = null,
val usernameCreator: String? = null,
val usernamePaying: String? = null,
diff --git a/app/src/main/java/ru/nsu/fit/modao/models/Group.kt b/app/src/main/java/ru/nsu/fit/modao/models/Group.kt
index 594534f..884686d 100644
--- a/app/src/main/java/ru/nsu/fit/modao/models/Group.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/models/Group.kt
@@ -3,14 +3,6 @@ package ru.nsu.fit.modao.models
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
-/*
- private Long id;
- private String groupName;
- private String description;
- private String uuid;
- private Integer typeGroup;
- private List userIdList;
- */
@Parcelize
data class Group(
@@ -19,6 +11,36 @@ data class Group(
val description: String? = null,
val groupName: String? = null,
val uuid: String? = null,
- val userIdList: Array? = null
- //val name: String? = null
-) : Parcelable
\ No newline at end of file
+ val userIdList: Array? = null,
+ val time: String? = null,
+ var isOrganizer: Boolean? = null
+) : Parcelable {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as Group
+
+ if (id != other.id) return false
+ if (typeGroup != other.typeGroup) return false
+ if (description != other.description) return false
+ if (groupName != other.groupName) return false
+ if (uuid != other.uuid) return false
+ if (userIdList != null) {
+ if (other.userIdList == null) return false
+ if (!userIdList.contentEquals(other.userIdList)) return false
+ } else if (other.userIdList != null) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = id?.hashCode() ?: 0
+ result = 31 * result + (typeGroup ?: 0)
+ result = 31 * result + (description?.hashCode() ?: 0)
+ result = 31 * result + (groupName?.hashCode() ?: 0)
+ result = 31 * result + (uuid?.hashCode() ?: 0)
+ result = 31 * result + (userIdList?.contentHashCode() ?: 0)
+ return result
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/models/LoadItems.kt b/app/src/main/java/ru/nsu/fit/modao/models/LoadItems.kt
index 791e1c0..bef8333 100644
--- a/app/src/main/java/ru/nsu/fit/modao/models/LoadItems.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/models/LoadItems.kt
@@ -1,3 +1,3 @@
package ru.nsu.fit.modao.models
-data class LoadItems(var isLoad: Boolean): ExpenseListItem()
+data class LoadItems(var isLoad: Boolean, val page: Int): ExpenseListItem()
diff --git a/app/src/main/java/ru/nsu/fit/modao/models/PageInfo.kt b/app/src/main/java/ru/nsu/fit/modao/models/PageInfo.kt
new file mode 100644
index 0000000..72fd9b7
--- /dev/null
+++ b/app/src/main/java/ru/nsu/fit/modao/models/PageInfo.kt
@@ -0,0 +1,10 @@
+package ru.nsu.fit.modao.models
+
+data class PageInfo(
+ val sort: SortInfo? = null,
+ val offset: Int? = null,
+ val pageNumber: Int? = null,
+ val pageSize: Int? = null,
+ val paged: Boolean? = null,
+ val unpaged: Boolean? = null
+)
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/models/PagingExpenses.kt b/app/src/main/java/ru/nsu/fit/modao/models/PagingExpenses.kt
new file mode 100644
index 0000000..1239c6b
--- /dev/null
+++ b/app/src/main/java/ru/nsu/fit/modao/models/PagingExpenses.kt
@@ -0,0 +1,33 @@
+package ru.nsu.fit.modao.models
+
+data class PagingExpenses(
+ val content: Array? = null,
+ val pageable: PageInfo? = null,
+ val totalPages: Int? = null,
+ val totalElements: Int? = null,
+ val last: Boolean? = null,
+ val number: Int? = null,
+ val sort: SortInfo? = null,
+ val size: Int? = null,
+ val numberOfElements: Int? = null,
+ val first: Boolean? = null,
+ val empty: Boolean? = null,
+) {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as PagingExpenses
+
+ if (content != null) {
+ if (other.content == null) return false
+ if (!content.contentEquals(other.content)) return false
+ } else if (other.content != null) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ return content?.contentHashCode() ?: 0
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/models/Registration.kt b/app/src/main/java/ru/nsu/fit/modao/models/Registration.kt
new file mode 100644
index 0000000..d9b8c81
--- /dev/null
+++ b/app/src/main/java/ru/nsu/fit/modao/models/Registration.kt
@@ -0,0 +1,6 @@
+package ru.nsu.fit.modao.models
+
+data class Registration(
+ val id: Long? = null,
+ val message: String? = null
+)
diff --git a/app/src/main/java/ru/nsu/fit/modao/models/SortInfo.kt b/app/src/main/java/ru/nsu/fit/modao/models/SortInfo.kt
new file mode 100644
index 0000000..f0cdb4e
--- /dev/null
+++ b/app/src/main/java/ru/nsu/fit/modao/models/SortInfo.kt
@@ -0,0 +1,7 @@
+package ru.nsu.fit.modao.models
+
+data class SortInfo(
+ val empty: Boolean? = null,
+ val sorted: Boolean? = null,
+ val unsorted: Boolean? = null,
+)
diff --git a/app/src/main/java/ru/nsu/fit/modao/models/Tokens.kt b/app/src/main/java/ru/nsu/fit/modao/models/Tokens.kt
new file mode 100644
index 0000000..7a504a5
--- /dev/null
+++ b/app/src/main/java/ru/nsu/fit/modao/models/Tokens.kt
@@ -0,0 +1,6 @@
+package ru.nsu.fit.modao.models
+
+data class Tokens(
+ var refreshToken: String? = null,
+ var accessToken: String? = null
+)
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/models/User.kt b/app/src/main/java/ru/nsu/fit/modao/models/User.kt
index f32e744..f54395c 100644
--- a/app/src/main/java/ru/nsu/fit/modao/models/User.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/models/User.kt
@@ -9,6 +9,8 @@ data class User(
val idPicture: Int? = null,
val id: Long? = null,
- val uuid: String? = null
- //val groupCustomPairIdNameList: ArrayList? = null
+ val uuid: String? = null,
+ val deviceToken: String? = null,
+ val packageName: String = "ru.nsu.fit.modao",
+ val appVersion: String = "1"
)
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/notification/PushService.kt b/app/src/main/java/ru/nsu/fit/modao/notification/PushService.kt
index 52c3b74..75f40ae 100644
--- a/app/src/main/java/ru/nsu/fit/modao/notification/PushService.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/notification/PushService.kt
@@ -7,6 +7,7 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
+import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import com.google.firebase.messaging.FirebaseMessagingService
@@ -16,7 +17,8 @@ import ru.nsu.fit.modao.R
import kotlin.random.Random
private const val CHANNEL_ID = "my_channel"
-class PushService: FirebaseMessagingService() {
+
+class PushService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
super.onNewToken(token)
}
@@ -27,30 +29,38 @@ class PushService: FirebaseMessagingService() {
val intent = Intent(this, MasterActivity::class.java)
message.data.forEach {
intent.putExtra(it.key, it.value)
+ Log.d("MyTag", "${it.key} - ${it.value}")
}
- val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ val notificationManager =
+ getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationID = Random.nextInt()
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel(notificationManager)
}
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
+ PendingIntent.getActivity(
+ this,
+ 0,
+ intent,
+ PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+ )
} else {
PendingIntent.getActivity(this, 0, intent, 0)
}
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
- .setContentTitle(message.data[KEY_TITLE])
- .setContentText(message.data[KEY_MESSAGE])
+ .setContentTitle(message.notification?.title)
+ .setContentText(message.notification?.body)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
- .setSmallIcon(R.drawable.ic_launcher_foreground)
+ .setSmallIcon(R.drawable.ic_logo)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.build()
notificationManager.notify(notificationID, notification)
}
+
@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(notificationManager: NotificationManager) {
val channelName = "channelName"
@@ -59,11 +69,8 @@ class PushService: FirebaseMessagingService() {
}
companion object {
- const val INTENT_FILTER = "PUSH_EVENT"
const val KEY_ACTION = "action"
const val KEY_GROUP_ID = "groupID"
- const val KEY_TITLE = "title"
- const val KEY_MESSAGE = "message"
const val TO_NOTIFICATION = "move to notification"
const val TO_DATA_CONFIRMATION = "move to data confirmation"
diff --git a/app/src/main/java/ru/nsu/fit/modao/repository/MainRepository.kt b/app/src/main/java/ru/nsu/fit/modao/repository/MainRepository.kt
index 0590619..6868be2 100644
--- a/app/src/main/java/ru/nsu/fit/modao/repository/MainRepository.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/repository/MainRepository.kt
@@ -5,14 +5,27 @@ import ru.nsu.fit.modao.models.*
import ru.nsu.fit.modao.utils.App
import ru.nsu.fit.modao.utils.Constants
-class MainRepository (private val app: App) {
+class MainRepository(private val app: App) {
suspend fun login(user: User): Response {
return app.api.login(user)
}
+
suspend fun createUser(user: User): Response {
return app.api.createUser(user)
}
+ suspend fun getAccessToken(refreshToken: Tokens): Response {
+ return app.api.getAccessToken(refreshToken)
+ }
+
+ suspend fun getRefreshToken(refreshToken: Tokens): Response {
+ return app.api.getRefreshToken(refreshToken)
+ }
+
+ suspend fun exit(): Response {
+ return app.api.exit(Constants.AUTH + app.accessToken)
+ }
+
suspend fun getUser(): Response {
return app.api.getUser(Constants.AUTH + app.accessToken)
}
@@ -22,14 +35,33 @@ class MainRepository (private val app: App) {
}
- suspend fun getGroupExpenses(id: Long, mode: Int, type: Int): Response> {
- return app.api.getGroupExpenses(Constants.AUTH + app.accessToken, id, mode, type)
+ suspend fun getGroupExpenses(
+ id: Long, mode: Int,
+ type: Int, minTime: Long, maxTime: Long,
+ offset: Int, limit: Int
+ ): Response {
+ return app.api.getGroupExpenses(
+ Constants.AUTH + app.accessToken,
+ id, mode, type, minTime, maxTime, offset, limit
+ )
}
suspend fun createExpense(expense: Expense): Response {
return app.api.createExpense(Constants.AUTH + app.accessToken, expense)
}
+ suspend fun deleteUser(groupId: Long, userId: Long): Response {
+ return app.api.deleteUser(Constants.AUTH + app.accessToken, groupId, userId)
+ }
+
+ suspend fun deleteEvent(groupId: Long, eventId: Long, name: String): Response {
+ return app.api.deleteEvent(Constants.AUTH + app.accessToken, groupId, eventId, name)
+ }
+
+ suspend fun makeGroupActive(groupId: Long): Response {
+ return app.api.makeGroupActive(Constants.AUTH + app.accessToken, groupId)
+ }
+
suspend fun addUserToGroup(groupId: Long, userId: Long): Response {
return app.api.addUserToGroup(Constants.AUTH + app.accessToken, groupId, userId)
}
@@ -57,39 +89,59 @@ class MainRepository (private val app: App) {
suspend fun getEventInfo(eventId: Long, groupId: Long): Response {
return app.api.getEventInfo(Constants.AUTH + app.accessToken, eventId, groupId)
}
+
suspend fun getGroupUnconfirmedExpenses(groupId: Long): Response> {
return app.api.getGroupUnconfirmedExpenses(Constants.AUTH + app.accessToken, groupId)
}
- suspend fun getUserGroups(): Response>{
- return app.api.getUserGroups(Constants.AUTH + app.accessToken)
+
+ suspend fun deleteGroup(groupId: Long): Response {
+ return app.api.deleteGroup(Constants.AUTH + app.accessToken, groupId)
}
- suspend fun getGroupInfo(groupId: Long): Response{
- return app.api.getGroupInfo(Constants.AUTH + app.accessToken ,groupId)
+
+ suspend fun archiveGroup(groupId: Long): Response {
+ return app.api.archiveGroup(Constants.AUTH + app.accessToken, groupId)
+ }
+
+ suspend fun getUserGroups(type: Int): Response> {
+ return app.api.getUserGroups(Constants.AUTH + app.accessToken, type)
}
+
+ suspend fun getGroupInfo(groupId: Long): Response {
+ return app.api.getGroupInfo(Constants.AUTH + app.accessToken, groupId)
+ }
+
suspend fun addFriend(userUuid: String): Response {
return app.api.addFriend(Constants.AUTH + app.accessToken, userUuid)
}
+
suspend fun getInvitationsFriend(): Response> {
return app.api.getInvitationsFriend(Constants.AUTH + app.accessToken)
}
+
suspend fun getInvitationsGroup(): Response> {
return app.api.getInvitationsGroup(Constants.AUTH + app.accessToken)
}
- suspend fun acceptInvitationFriend(invitationId: Long):Response {
+
+ suspend fun acceptInvitationFriend(invitationId: Long): Response {
return app.api.acceptInvitationFriend(Constants.AUTH + app.accessToken, invitationId)
}
- suspend fun denyInvitationFriend(invitationId: Long):Response {
+
+ suspend fun denyInvitationFriend(invitationId: Long): Response {
return app.api.denyInvitationFriend(Constants.AUTH + app.accessToken, invitationId)
}
- suspend fun acceptInvitationGroup(invitationId: Long):Response {
+
+ suspend fun acceptInvitationGroup(invitationId: Long): Response {
return app.api.acceptInvitationGroup(Constants.AUTH + app.accessToken, invitationId)
}
- suspend fun denyInvitationGroup(invitationId: Long):Response {
+
+ suspend fun denyInvitationGroup(invitationId: Long): Response {
return app.api.denyInvitationGroup(Constants.AUTH + app.accessToken, invitationId)
}
+
suspend fun getListFriends(): Response> {
return app.api.getListFriends(Constants.AUTH + app.accessToken)
}
+
suspend fun addToGroup(groupUUID: String): Response {
return app.api.addToGroup(Constants.AUTH + app.accessToken, groupUUID)
}
diff --git a/app/src/main/java/ru/nsu/fit/modao/utils/App.kt b/app/src/main/java/ru/nsu/fit/modao/utils/App.kt
index 391ea37..4bb0542 100644
--- a/app/src/main/java/ru/nsu/fit/modao/utils/App.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/utils/App.kt
@@ -1,8 +1,10 @@
package ru.nsu.fit.modao.utils
import android.app.Application
+import android.content.SharedPreferences
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
+import com.google.firebase.messaging.FirebaseMessaging
import dagger.hilt.android.HiltAndroidApp
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
@@ -28,35 +30,45 @@ class App: Application() {
val api: ApiService by lazy {
retrofit.create(ApiService::class.java)
}
-/*
+
override fun onCreate() {
super.onCreate()
FirebaseMessaging.getInstance().token.addOnCompleteListener {
if (!it.isSuccessful) {
return@addOnCompleteListener
}
- val token = it.result
- Log.d("MyTag", token)
+ deviceToken = it.result
}
- val intentFilter = IntentFilter()
- intentFilter.addAction(INTENT_FILTER)
- val receiver = MyReceiver()
- registerReceiver(receiver, intentFilter)
- }*/
+ }
+
+ val encryptedSharedPreferences: SharedPreferences by lazy {
+ val pref = applicationContext.getSharedPreferences("init_pref", MODE_PRIVATE)
+ val isEncrypted = pref
+ .getBoolean("is encrypted", true)
+ if (isEncrypted) {
+ try {
+ val masterKey: MasterKey = MasterKey.Builder(applicationContext)
+ .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
+ .build()
+ EncryptedSharedPreferences.create(
+ applicationContext,
+ "secret_shared_prefs",
+ masterKey,
+ EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
+ EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
+ )
+ } catch (e: Exception) {
+ pref.edit().putBoolean("is encrypted", false).apply()
+ applicationContext.getSharedPreferences("secret_shared_prefs", MODE_PRIVATE)
+ }
+ } else {
+ applicationContext.getSharedPreferences("secret_shared_prefs", MODE_PRIVATE)
+ }
+
- val encryptedSharedPreferences by lazy {
- val masterKey: MasterKey = MasterKey.Builder(applicationContext)
- .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
- .build()
- EncryptedSharedPreferences.create(
- applicationContext,
- "secret_shared_prefs",
- masterKey,
- EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
- EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
- )
}
var userId: Long = -1
var accessToken: String? = null
var refreshToken: String? = null
+ var deviceToken: String? = null
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/utils/Constatns.kt b/app/src/main/java/ru/nsu/fit/modao/utils/Constatns.kt
index c354311..bad332a 100644
--- a/app/src/main/java/ru/nsu/fit/modao/utils/Constatns.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/utils/Constatns.kt
@@ -2,17 +2,18 @@ package ru.nsu.fit.modao.utils
class Constants {
companion object {
- //const val BASE_URL = "http://192.168.137.1:8080"
+ //const val BASE_URL = "http://192.168.137.1:8080" // laptop wifi
//const val BASE_URL = "http://192.168.137.52:8080"
//const val BASE_URL = "http://192.168.137.3:8080" //wifi sister
- //const val BASE_URL = "http://139.59.143.34:5000"
- const val BASE_URL = "http://192.168.0.101:8080" //my wifi
+ const val BASE_URL = "http://139.59.143.34:5000" //server
+ //const val BASE_URL = "http://192.168.0.101:8080" //my wifi
//const val BASE_URL = "http://192.168.0.107:8080"
- const val PAGE_SIZE = 10
+ const val PAGE_SIZE = 20
const val AUTH = "Bearer "
const val ACCESS_TOKEN = "Access token"
const val REFRESH_TOKEN = "Refresh token"
const val ID_USER = "User id"
- const val BASE_URL_FCM = "https://fcm.googleapis.com"
+ const val FAIL = "Fail"
+ const val SUCCESS = "Success"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nsu/fit/modao/viewmodels/CreateExpenseViewModel.kt b/app/src/main/java/ru/nsu/fit/modao/viewmodels/CreateExpenseViewModel.kt
index 2ecfa6a..eaaf52d 100644
--- a/app/src/main/java/ru/nsu/fit/modao/viewmodels/CreateExpenseViewModel.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/viewmodels/CreateExpenseViewModel.kt
@@ -63,10 +63,14 @@ class CreateExpenseViewModel @Inject constructor(private val repository: MainRep
message.value = "Select participants"
return
}
-
- if (type == 1 || payFor) {
+ if (type == 1 && participantsEvent.size != 1) {
+ message.value = "Select participants"
+ return
+ }
+ if (type == 1 || payFor || !sponsor.selected) {
sponsor.coefficient = 0f
}
+
viewModelScope.launch(handler) {
val expense = Expense(
name = description, price = sum,
diff --git a/app/src/main/java/ru/nsu/fit/modao/viewmodels/LoginViewModel.kt b/app/src/main/java/ru/nsu/fit/modao/viewmodels/LoginViewModel.kt
index 609d78a..f314cbe 100644
--- a/app/src/main/java/ru/nsu/fit/modao/viewmodels/LoginViewModel.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/viewmodels/LoginViewModel.kt
@@ -1,13 +1,14 @@
package ru.nsu.fit.modao.viewmodels
-import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
+import com.google.gson.Gson
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.launch
import ru.nsu.fit.modao.models.Authorization
+import ru.nsu.fit.modao.models.Registration
import ru.nsu.fit.modao.models.User
import ru.nsu.fit.modao.repository.MainRepository
import javax.inject.Inject
@@ -19,12 +20,12 @@ class LoginViewModel @Inject constructor(private val repository: MainRepository)
val userId = MutableLiveData()
val message = MutableLiveData()
private val handler = CoroutineExceptionHandler { _, _ -> message.value = "Server problems"}
- fun login(login: String, password: String){
+ fun login(login: String, password: String, deviceToken: String?){
if (login == "" || password == ""){
message.value = "Enter the data"
return
}
- val user = User(login = login, password = password)
+ val user = User(login = login, password = password, deviceToken = deviceToken)
viewModelScope.launch(handler) {
val response = repository.login(user)
if (response.isSuccessful){
@@ -45,7 +46,29 @@ class LoginViewModel @Inject constructor(private val repository: MainRepository)
if (response.isSuccessful){
userId.value = response.body()
} else {
- message.value = "User with this login already exists"
+ val gson = Gson()
+ val errorResponse = gson.fromJson(response.errorBody()?.string()!!,
+ Registration::class.java)
+ when (errorResponse.message!!) {
+ "Пароль должен содержать " +
+ "как минимум одну букву в нижнем регистре" -> {
+ message.value = "The password must contain at least " +
+ "one letter in lowercase"
+ }
+ "Пароль должен содержать " +
+ "как минимум одну букву в верхнем регистре" -> {
+ message.value = "The password must contain at least " +
+ "one uppercase letter"
+ }
+ "Пароль слишком короткий\n" -> {
+ message.value = "The password must contain at least 6 characters"
+ }
+ "Логин должен быть от 3 до 20 символов\n" -> {
+ message.value = "Login must be from 3 to 20 characters "
+ }
+ else -> message.value = "User with this login already exists"
+ }
+
}
}
}
diff --git a/app/src/main/java/ru/nsu/fit/modao/viewmodels/MainViewModel.kt b/app/src/main/java/ru/nsu/fit/modao/viewmodels/MainViewModel.kt
index 1950735..a79fc8e 100644
--- a/app/src/main/java/ru/nsu/fit/modao/viewmodels/MainViewModel.kt
+++ b/app/src/main/java/ru/nsu/fit/modao/viewmodels/MainViewModel.kt
@@ -9,6 +9,8 @@ import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.launch
import ru.nsu.fit.modao.models.*
import ru.nsu.fit.modao.repository.MainRepository
+import ru.nsu.fit.modao.utils.Constants.Companion.FAIL
+import ru.nsu.fit.modao.utils.Constants.Companion.SUCCESS
import javax.inject.Inject
@HiltViewModel
@@ -27,16 +29,20 @@ class MainViewModel @Inject constructor(private val repository: MainRepository)
val groupInfo = MutableLiveData()
val invitationUser = MutableLiveData>()
val listFriends = MutableLiveData>()
-
+ val tokens = MutableLiveData()
+ val totalPages = MutableLiveData()
private val handler = CoroutineExceptionHandler { _, throwable ->
messageHandler.value = throwable.message
- Log.e("MyTag", "${throwable.message}\n" +
- "${throwable.cause}\n${throwable.localizedMessage}\n" +
- "${throwable.suppressed}\n${throwable.suppressedExceptions}\n" +
- "${throwable.stackTrace}")
+ Log.e(
+ "MyTag", "${throwable.message}\n" +
+ "${throwable.cause}\n${throwable.localizedMessage}\n" +
+ "${throwable.suppressed}\n${throwable.suppressedExceptions}\n" +
+ "${throwable.stackTrace}"
+ )
}
+
fun getUser() {
viewModelScope.launch(handler) {
val response = repository.getUser()
@@ -44,94 +50,208 @@ class MainViewModel @Inject constructor(private val repository: MainRepository)
user.value = response.body()
} else {
tipMessage.value = "error"
- Log.e("MyError", response.message())
+ Log.e("MyError", "Error ${response.errorBody()?.string()}")
+ }
+ }
+ }
+
+ fun getAccessToken(refreshToken: Tokens) {
+ viewModelScope.launch(handler) {
+ val response = repository.getAccessToken(refreshToken)
+ if (response.isSuccessful) {
+ tokens.value?.accessToken = response.body()?.accessToken
+ } else {
+ tipMessage.value = "error"
+ Log.e("MyError", "Error ${response.errorBody()?.string()}")
+ }
+ }
+ }
+
+ fun deleteGroup(groupId: Long) {
+ viewModelScope.launch(handler) {
+ val response = repository.deleteGroup(groupId)
+ if (response.isSuccessful) {
+ tipMessage.value = "Deleted"
+ } else {
+ Log.d("MyTag", "Error ${response.errorBody()?.string()}")
+ }
+ }
+ }
+
+ fun archiveGroup(groupId: Long) {
+ viewModelScope.launch(handler) {
+ val response = repository.archiveGroup(groupId)
+ if (response.isSuccessful) {
+ tipMessage.value = "Archived"
+ } else {
+ Log.d("MyTag", "Error ${response.errorBody()?.string()}")
+ }
+ }
+ }
+
+ fun getRefreshToken(refreshToken: Tokens) {
+ viewModelScope.launch(handler) {
+ val response = repository.getRefreshToken(refreshToken)
+ if (response.isSuccessful) {
+ tokens.value = Tokens(
+ refreshToken = response.body()?.refreshToken,
+ accessToken = response.body()?.accessToken
+ )
+ } else {
+ tipMessage.value = "error"
+ Log.e("MyError", "Error ${response.errorBody()?.string()}")
}
}
}
- fun getUserGroups(){
+
+ fun exit() {
viewModelScope.launch(handler) {
- val response = repository.getUserGroups()
- if (response.isSuccessful){
+ val response = repository.exit()
+ if (response.isSuccessful) {
+ tipMessage.value = SUCCESS
+ } else {
+ tipMessage.value = FAIL
+ }
+ }
+ }
+
+ fun getUserGroups(type: Int) {
+ viewModelScope.launch(handler) {
+ val response = repository.getUserGroups(type)
+ if (response.isSuccessful) {
userGroups.value = response.body()
} else {
- Log.e("MyTag", response.message())
+ Log.e("MyError", "Error ${response.errorBody()?.string()}")
}
}
}
- fun createGroup(group: Group){
+
+ fun createGroup(group: Group) {
viewModelScope.launch(handler) {
val response = repository.createGroup(group)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
groupId.value = response.body()
+ } else {
+ Log.e("MyError", "Error ${response.errorBody()?.string()}")
+ }
+ }
+ }
+
+ fun getGroupExpenses(
+ id: Long, mode: Int, filter: Int,
+ minTime: Long, maxTime: Long,
+ offset: Int, limit: Int
+ ) {
+ viewModelScope.launch(handler) {
+ val response = repository.getGroupExpenses(
+ id, mode, filter,
+ minTime, maxTime, offset, limit
+ )
+ if (response.isSuccessful) {
+ expenses.value = response.body()?.content!!
+ totalPages.value = response.body()?.totalPages!!
+ } else {
+ Log.e("MyError", "Error ${response.errorBody()?.string()}")
}
- else {
- Log.e("MyError", response.message())
+ }
+ }
+
+ fun deleteEvent(groupId: Long, eventId: Long, name: String) {
+ viewModelScope.launch(handler) {
+ val response = repository.deleteEvent(groupId, eventId, name)
+ if (response.isSuccessful) {
+ tipMessage.value = SUCCESS
+ } else {
+ tipMessage.value = FAIL
+ Log.e("MyError", "Error ${response.errorBody()?.string()}")
}
}
}
- fun getGroupExpenses(id: Long, mode: Int, filter: Int){
+
+ fun makeGroupActive(groupId: Long) {
viewModelScope.launch(handler) {
- val response = repository.getGroupExpenses(id, mode, filter)
- if (response.isSuccessful){
- expenses.value = response.body()
+ val response = repository.makeGroupActive(groupId)
+ if (response.isSuccessful) {
+ tipMessage.value = SUCCESS
+ } else {
+ tipMessage.value = FAIL
+ Log.e("MyError", "Error ${response.errorBody()?.string()}")
}
- else {
- Log.e("MyError", response.message())
+ }
+ }
+
+ fun deleteUser(groupId: Long, userId: Long) {
+ viewModelScope.launch(handler) {
+ val response = repository.deleteUser(groupId, userId)
+ if (response.isSuccessful) {
+ tipMessage.value = SUCCESS
+ getUsersInGroup(groupId)
+ } else {
+ tipMessage.value = FAIL
+ Log.e("MyError", "Error ${response.errorBody()?.string()}")
}
}
}
- fun getUsersInGroup(groupId: Long){
+
+ fun getUsersInGroup(groupId: Long) {
viewModelScope.launch(handler) {
val response = repository.getUsersInGroup(groupId)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
usersInGroup.value = response.body()
} else {
Log.e("MyTag", response.message())
}
}
}
- fun confirmEvent(groupId: Long, eventId: Long){
+
+ fun confirmEvent(groupId: Long, eventId: Long) {
viewModelScope.launch(handler) {
val response = repository.confirmEvent(groupId, eventId)
if (!response.isSuccessful) {
Log.d("MyTag", response.message())
} else {
+ tipMessage.value = "OK"
getGroupUnconfirmedExpenses(groupId)
}
}
}
- fun notConfirmEvent(groupId: Long, eventId: Long){
+
+ fun notConfirmEvent(groupId: Long, eventId: Long) {
viewModelScope.launch(handler) {
val response = repository.notConfirmEvent(groupId, eventId)
if (!response.isSuccessful) {
Log.d("MyTag", response.message())
} else {
+ tipMessage.value = "OK"
getGroupUnconfirmedExpenses(groupId)
}
}
}
- fun addUserToGroup(groupId: Long, userId: Long){
+
+ fun addUserToGroup(groupId: Long, userId: Long) {
viewModelScope.launch(handler) {
val response = repository.addUserToGroup(groupId, userId)
- if (!response.isSuccessful){
+ if (!response.isSuccessful) {
Log.e("My errors", "Error add friend")
}
}
}
- fun getUserDebtInGroup(userId: Long, groupId: Long){
+
+ fun getUserDebtInGroup(userId: Long, groupId: Long) {
viewModelScope.launch(handler) {
val response = repository.getUserDebtInGroup(userId, groupId)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
userExpenses.value = response.body()
} else {
Log.e("MyTag", response.message())
}
}
}
- fun getListOrganizers(groupId: Long){
+
+ fun getListOrganizers(groupId: Long) {
viewModelScope.launch(handler) {
val response = repository.getListOrganizers(groupId)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
organizers.value = response.body()
} else {
organizers.value = arrayOf()
@@ -139,122 +259,133 @@ class MainViewModel @Inject constructor(private val repository: MainRepository)
}
}
- fun getEventInfo(eventId: Long, groupId: Long){
+ fun getEventInfo(eventId: Long, groupId: Long) {
viewModelScope.launch(handler) {
val response = repository.getEventInfo(eventId, groupId)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
infoEvent.value = response.body()
} else {
Log.e("MyTag", response.message())
}
}
}
- fun getGroupUnconfirmedExpenses(groupId: Long){
+
+ fun getGroupUnconfirmedExpenses(groupId: Long) {
viewModelScope.launch(handler) {
val response = repository.getGroupUnconfirmedExpenses(groupId)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
unconfirmedExpenses.value = response.body()
} else {
Log.e("MyTag", response.message())
}
}
}
- fun getGroupInfo(groupId: Long){
+
+ fun getGroupInfo(groupId: Long) {
viewModelScope.launch(handler) {
val response = repository.getGroupInfo(groupId)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
groupInfo.value = response.body()
} else {
Log.e("MyTag", response.message())
}
}
}
- fun addFriend(userUuid: String){
+
+ fun addFriend(userUuid: String) {
viewModelScope.launch(handler) {
val response = repository.addFriend(userUuid)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
tipMessage.value = "Success"
} else {
tipMessage.value = "Incorrect data"
}
}
}
+
fun getInvitationsFriend() {
viewModelScope.launch(handler) {
val response = repository.getInvitationsFriend()
- if (response.isSuccessful){
+ if (response.isSuccessful) {
invitationUser.value = response.body()
} else {
Log.d("MyTag", "Fail")
}
}
}
+
fun getInvitationsGroup() {
viewModelScope.launch(handler) {
val response = repository.getInvitationsGroup()
- if (response.isSuccessful){
+ if (response.isSuccessful) {
invitationUser.value = response.body()
} else {
Log.d("MyTag", "Fail")
}
}
}
- fun acceptInvitationFriend(invitationId: Long){
+
+ fun acceptInvitationFriend(invitationId: Long) {
viewModelScope.launch(handler) {
val response = repository.acceptInvitationFriend(invitationId)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
tipMessage.value = "Success"
} else {
tipMessage.value = "Fail"
}
}
}
- fun denyInvitationFriend(invitationId: Long){
+
+ fun denyInvitationFriend(invitationId: Long) {
viewModelScope.launch(handler) {
val response = repository.denyInvitationFriend(invitationId)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
tipMessage.value = "Success"
} else {
tipMessage.value = "Fail"
}
}
}
- fun acceptInvitationGroup(invitationId: Long){
+
+ fun acceptInvitationGroup(invitationId: Long) {
viewModelScope.launch(handler) {
val response = repository.acceptInvitationGroup(invitationId)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
tipMessage.value = "Success"
} else {
tipMessage.value = "Fail"
}
}
}
- fun denyInvitationGroup(invitationId: Long){
+
+ fun denyInvitationGroup(invitationId: Long) {
viewModelScope.launch(handler) {
val response = repository.denyInvitationGroup(invitationId)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
tipMessage.value = "Success"
} else {
tipMessage.value = "Fail"
}
}
}
- fun getListFriends(){
+
+ fun getListFriends() {
viewModelScope.launch(handler) {
val response = repository.getListFriends()
- if (response.isSuccessful){
+ if (response.isSuccessful) {
listFriends.value = response.body()
} else {
Log.d("MyTag", "Fail")
}
}
}
- fun addToGroup(groupUUID: String){
+
+ fun addToGroup(groupUUID: String) {
viewModelScope.launch(handler) {
val response = repository.addToGroup(groupUUID)
- if (response.isSuccessful){
+ if (response.isSuccessful) {
tipMessage.value = "Success"
- getUserGroups()
+ getUserGroups(0)
} else {
tipMessage.value = "Incorrect uuid"
}
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
deleted file mode 100644
index 2b068d1..0000000
--- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/balloons.xml b/app/src/main/res/drawable/balloons.xml
new file mode 100644
index 0000000..67986e0
--- /dev/null
+++ b/app/src/main/res/drawable/balloons.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/baseline_calendar_month_24.xml b/app/src/main/res/drawable/baseline_calendar_month_24.xml
new file mode 100644
index 0000000..edc07b4
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_calendar_month_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/baseline_cancel_24.xml b/app/src/main/res/drawable/baseline_cancel_24.xml
new file mode 100644
index 0000000..d48a921
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_cancel_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/baseline_info_24.xml b/app/src/main/res/drawable/baseline_info_24.xml
new file mode 100644
index 0000000..26aca9d
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_info_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/baseline_people_outline_24.xml b/app/src/main/res/drawable/baseline_people_outline_24.xml
new file mode 100644
index 0000000..b10ecee
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_people_outline_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/baseline_warning_24.xml b/app/src/main/res/drawable/baseline_warning_24.xml
new file mode 100644
index 0000000..b1726a3
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_warning_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/button_add_expense.xml b/app/src/main/res/drawable/button_add_expense.xml
deleted file mode 100644
index 811cfb0..0000000
--- a/app/src/main/res/drawable/button_add_expense.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/button_add_friend.xml b/app/src/main/res/drawable/button_add_friend.xml
deleted file mode 100644
index 42413eb..0000000
--- a/app/src/main/res/drawable/button_add_friend.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/button_add_group.xml b/app/src/main/res/drawable/button_add_group.xml
deleted file mode 100644
index 5f70e15..0000000
--- a/app/src/main/res/drawable/button_add_group.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/button_add_member.xml b/app/src/main/res/drawable/button_add_member.xml
deleted file mode 100644
index 2863e4d..0000000
--- a/app/src/main/res/drawable/button_add_member.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/button_all_in.xml b/app/src/main/res/drawable/button_all_in.xml
deleted file mode 100644
index 40f265e..0000000
--- a/app/src/main/res/drawable/button_all_in.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/button_background.xml b/app/src/main/res/drawable/button_background.xml
deleted file mode 100644
index 12707c0..0000000
--- a/app/src/main/res/drawable/button_background.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/button_data_conf.xml b/app/src/main/res/drawable/button_data_conf.xml
deleted file mode 100644
index e7bd086..0000000
--- a/app/src/main/res/drawable/button_data_conf.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
diff --git a/app/src/main/res/drawable/button_expenses_group.xml b/app/src/main/res/drawable/button_expenses_group.xml
deleted file mode 100644
index 8ce7f6c..0000000
--- a/app/src/main/res/drawable/button_expenses_group.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/button_finish.xml b/app/src/main/res/drawable/button_finish.xml
deleted file mode 100644
index 0195fa8..0000000
--- a/app/src/main/res/drawable/button_finish.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/button_group.xml b/app/src/main/res/drawable/button_group.xml
deleted file mode 100644
index bfe8ed9..0000000
--- a/app/src/main/res/drawable/button_group.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/button_info_group.xml b/app/src/main/res/drawable/button_info_group.xml
deleted file mode 100644
index 972e482..0000000
--- a/app/src/main/res/drawable/button_info_group.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/button_member.xml b/app/src/main/res/drawable/button_member.xml
deleted file mode 100644
index 2a312fc..0000000
--- a/app/src/main/res/drawable/button_member.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/button_more_options.xml b/app/src/main/res/drawable/button_more_options.xml
deleted file mode 100644
index c47a182..0000000
--- a/app/src/main/res/drawable/button_more_options.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/button_next.xml b/app/src/main/res/drawable/button_next.xml
deleted file mode 100644
index 14f30ff..0000000
--- a/app/src/main/res/drawable/button_next.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/button_select_participant.xml b/app/src/main/res/drawable/button_select_participant.xml
deleted file mode 100644
index 8cc3f6b..0000000
--- a/app/src/main/res/drawable/button_select_participant.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/button_two.xml b/app/src/main/res/drawable/button_two.xml
deleted file mode 100644
index 84d3766..0000000
--- a/app/src/main/res/drawable/button_two.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/continue_button.xml b/app/src/main/res/drawable/continue_button.xml
deleted file mode 100644
index 1e670b3..0000000
--- a/app/src/main/res/drawable/continue_button.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/create_expense_head.xml b/app/src/main/res/drawable/create_expense_head.xml
deleted file mode 100644
index 35a30ae..0000000
--- a/app/src/main/res/drawable/create_expense_head.xml
+++ /dev/null
@@ -1,25163 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/done_button.xml b/app/src/main/res/drawable/done_button.xml
deleted file mode 100644
index 3e93a81..0000000
--- a/app/src/main/res/drawable/done_button.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/field_enter_cost.xml b/app/src/main/res/drawable/field_enter_cost.xml
deleted file mode 100644
index 54537ed..0000000
--- a/app/src/main/res/drawable/field_enter_cost.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/field_enter_description_expense.xml b/app/src/main/res/drawable/field_enter_description_expense.xml
deleted file mode 100644
index a302c0d..0000000
--- a/app/src/main/res/drawable/field_enter_description_expense.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/field_for_entering_cost.xml b/app/src/main/res/drawable/field_for_entering_cost.xml
deleted file mode 100644
index 847d418..0000000
--- a/app/src/main/res/drawable/field_for_entering_cost.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/frame_find_new_friend.xml b/app/src/main/res/drawable/frame_find_new_friend.xml
deleted file mode 100644
index 5ab9e1f..0000000
--- a/app/src/main/res/drawable/frame_find_new_friend.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/frame_new_expense.xml b/app/src/main/res/drawable/frame_new_expense.xml
deleted file mode 100644
index 0425137..0000000
--- a/app/src/main/res/drawable/frame_new_expense.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/frame_new_friend.xml b/app/src/main/res/drawable/frame_new_friend.xml
deleted file mode 100644
index 32973e7..0000000
--- a/app/src/main/res/drawable/frame_new_friend.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/frame_new_group.xml b/app/src/main/res/drawable/frame_new_group.xml
deleted file mode 100644
index 46a733b..0000000
--- a/app/src/main/res/drawable/frame_new_group.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/gray_new_expense.xml b/app/src/main/res/drawable/gray_new_expense.xml
deleted file mode 100644
index baf956c..0000000
--- a/app/src/main/res/drawable/gray_new_expense.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/gray_new_transfer.xml b/app/src/main/res/drawable/gray_new_transfer.xml
deleted file mode 100644
index f9ff919..0000000
--- a/app/src/main/res/drawable/gray_new_transfer.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/ic_add_friend.xml b/app/src/main/res/drawable/ic_add_friend.xml
deleted file mode 100644
index a40cdf6..0000000
--- a/app/src/main/res/drawable/ic_add_friend.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/ic_logo.xml b/app/src/main/res/drawable/ic_logo.xml
new file mode 100644
index 0000000..5134c90
--- /dev/null
+++ b/app/src/main/res/drawable/ic_logo.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_logo_square.xml b/app/src/main/res/drawable/ic_logo_square.xml
new file mode 100644
index 0000000..acfa6d7
--- /dev/null
+++ b/app/src/main/res/drawable/ic_logo_square.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_new_friend.xml b/app/src/main/res/drawable/ic_new_friend.xml
new file mode 100644
index 0000000..340e068
--- /dev/null
+++ b/app/src/main/res/drawable/ic_new_friend.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_new_group.xml b/app/src/main/res/drawable/ic_new_group.xml
new file mode 100644
index 0000000..da89c31
--- /dev/null
+++ b/app/src/main/res/drawable/ic_new_group.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_notification.xml b/app/src/main/res/drawable/ic_notification.xml
new file mode 100644
index 0000000..45b906f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_notification.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_wallet.xml b/app/src/main/res/drawable/ic_wallet.xml
deleted file mode 100644
index 4c1cce1..0000000
--- a/app/src/main/res/drawable/ic_wallet.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/icon_add_friend.xml b/app/src/main/res/drawable/icon_add_friend.xml
new file mode 100644
index 0000000..20dad5c
--- /dev/null
+++ b/app/src/main/res/drawable/icon_add_friend.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/login_in.xml b/app/src/main/res/drawable/login_in.xml
deleted file mode 100644
index 1eb13d1..0000000
--- a/app/src/main/res/drawable/login_in.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/money_transfer.xml b/app/src/main/res/drawable/money_transfer.xml
new file mode 100644
index 0000000..d6126e6
--- /dev/null
+++ b/app/src/main/res/drawable/money_transfer.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/new_expense.xml b/app/src/main/res/drawable/new_expense.xml
deleted file mode 100644
index 863df4a..0000000
--- a/app/src/main/res/drawable/new_expense.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/new_group_icon.xml b/app/src/main/res/drawable/new_group_icon.xml
new file mode 100644
index 0000000..fb815b4
--- /dev/null
+++ b/app/src/main/res/drawable/new_group_icon.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/new_transfer.xml b/app/src/main/res/drawable/new_transfer.xml
deleted file mode 100644
index c06a1e9..0000000
--- a/app/src/main/res/drawable/new_transfer.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/next.xml b/app/src/main/res/drawable/next.xml
deleted file mode 100644
index 14f30ff..0000000
--- a/app/src/main/res/drawable/next.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/no_button.xml b/app/src/main/res/drawable/no_button.xml
deleted file mode 100644
index da67296..0000000
--- a/app/src/main/res/drawable/no_button.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/notification_header.xml b/app/src/main/res/drawable/notification_header.xml
deleted file mode 100644
index 350fe0e..0000000
--- a/app/src/main/res/drawable/notification_header.xml
+++ /dev/null
@@ -1,317 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/sign_up.xml b/app/src/main/res/drawable/sign_up.xml
deleted file mode 100644
index 5edc9b2..0000000
--- a/app/src/main/res/drawable/sign_up.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/white_background.xml b/app/src/main/res/drawable/white_background.xml
index b76d4b4..c7c858e 100644
--- a/app/src/main/res/drawable/white_background.xml
+++ b/app/src/main/res/drawable/white_background.xml
@@ -1,6 +1,6 @@
-
-
-
diff --git a/app/src/main/res/layout/activity_master.xml b/app/src/main/res/layout/activity_master.xml
index fdf85b5..045791c 100644
--- a/app/src/main/res/layout/activity_master.xml
+++ b/app/src/main/res/layout/activity_master.xml
@@ -12,6 +12,7 @@
android:id="@+id/bottomMenu"
android:layout_width="match_parent"
android:layout_height="65dp"
+ style="@style/Widget.MaterialComponents.BottomNavigationView.PrimarySurface"
android:background="@color/bottom_menu"
android:visibility="gone"
app:itemIconSize="30dp"
diff --git a/app/src/main/res/layout/counter_event_item.xml b/app/src/main/res/layout/counter_event_item.xml
new file mode 100644
index 0000000..0b4f0b4
--- /dev/null
+++ b/app/src/main/res/layout/counter_event_item.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/deleted_event_item.xml b/app/src/main/res/layout/deleted_event_item.xml
new file mode 100644
index 0000000..7713d7e
--- /dev/null
+++ b/app/src/main/res/layout/deleted_event_item.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/filter_groups.xml b/app/src/main/res/layout/filter_groups.xml
new file mode 100644
index 0000000..f326ec9
--- /dev/null
+++ b/app/src/main/res/layout/filter_groups.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_add_member.xml b/app/src/main/res/layout/fragment_add_member.xml
index fcc19eb..9018f12 100644
--- a/app/src/main/res/layout/fragment_add_member.xml
+++ b/app/src/main/res/layout/fragment_add_member.xml
@@ -22,14 +22,17 @@
app:layout_constraintTop_toTopOf="parent" />
-
-
+ app:layout_constraintTop_toBottomOf="@+id/personPassword" />
-
+ app:layout_constraintStart_toStartOf="parent" />
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_create_expense.xml b/app/src/main/res/layout/fragment_create_expense.xml
index cf0b2e2..b6ac26d 100644
--- a/app/src/main/res/layout/fragment_create_expense.xml
+++ b/app/src/main/res/layout/fragment_create_expense.xml
@@ -6,19 +6,23 @@
android:layout_height="match_parent"
tools:context=".fragments.CreateExpenseFragment">
-
+ app:layout_constraintStart_toStartOf="parent" />
-
-
-
+ app:layout_constraintStart_toStartOf="parent" />
-
-
-
+
+
+
+
-
-
-
-
+ app:strokeColor="@color/gray"
+ app:strokeWidth="2dp" />
-
-
-
-
-
+
+
+
+
@@ -195,14 +247,4 @@
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_group_expenses.xml b/app/src/main/res/layout/fragment_group_expenses.xml
index c751d26..730734f 100644
--- a/app/src/main/res/layout/fragment_group_expenses.xml
+++ b/app/src/main/res/layout/fragment_group_expenses.xml
@@ -33,7 +33,7 @@
tools:listitem="@layout/expense_item" />
-
+ android:textColor="#FF6200EE"
+ android:textSize="@dimen/plain_text"
+ app:backgroundTint="@android:color/transparent" />
-
+ android:textColor="#FF6200EE"
+ android:textSize="@dimen/plain_text"
+ app:backgroundTint="@android:color/transparent" />
+
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_group_info.xml b/app/src/main/res/layout/fragment_group_info.xml
index f124ee9..1c82d71 100644
--- a/app/src/main/res/layout/fragment_group_info.xml
+++ b/app/src/main/res/layout/fragment_group_info.xml
@@ -6,112 +6,110 @@
android:layout_height="match_parent"
tools:context=".fragments.GroupInfoFragment">
-
-
+ android:fontFamily="@font/roboto"
+ android:textSize="@dimen/plain_text"
+ android:textStyle="italic"
+ app:layout_constraintBottom_toTopOf="@+id/buttonMembers"
+ app:layout_constraintEnd_toEndOf="@+id/buttonMembers"
+ app:layout_constraintTop_toBottomOf="@+id/imageView10" />
-
+ app:layout_constraintTop_toBottomOf="@+id/imageView10"
+ app:strokeColor="#8ABBD9"
+ app:strokeWidth="3dp" />
-
-
-
-
-
+ app:backgroundTint="@color/white"
+ app:cornerRadius="5dp"
+ app:icon="@drawable/balloons"
+ app:iconGravity="textStart"
+ app:iconPadding="20dp"
+ app:iconSize="30dp"
+ app:iconTint="@color/purple_500"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/buttonMembers"
+ app:strokeColor="#8ABBD9"
+ app:strokeWidth="3dp" />
-
-
+ app:backgroundTint="@color/white"
+ app:cornerRadius="5dp"
+ app:icon="@drawable/baseline_info_24"
+ app:iconGravity="textStart"
+ app:iconPadding="20dp"
+ app:iconSize="30dp"
+ app:iconTint="@color/bottom_menu"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.505"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/buttonGroupExpenses"
+ app:strokeColor="#8ABBD9"
+ app:strokeWidth="3dp" />
-
+ app:backgroundTint="@color/white"
+ app:cornerRadius="5dp"
+ app:icon="@drawable/baseline_warning_24"
+ app:iconGravity="textStart"
+ app:iconPadding="20dp"
+ app:iconSize="30dp"
+ app:iconTint="#F44336"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/groupInformation"
+ app:strokeColor="#8ABBD9"
+ app:strokeWidth="3dp" />
-
+ app:layout_constraintTop_toTopOf="parent"/>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_group_information.xml b/app/src/main/res/layout/fragment_group_information.xml
index cd5f945..40d4847 100644
--- a/app/src/main/res/layout/fragment_group_information.xml
+++ b/app/src/main/res/layout/fragment_group_information.xml
@@ -10,6 +10,7 @@
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginTop="-5dp"
android:contentDescription="@string/info_group"
android:src="@drawable/group_information_head"
app:layout_constraintEnd_toEndOf="parent"
@@ -20,6 +21,7 @@
android:id="@+id/information_title"
android:layout_width="200dp"
android:layout_height="40dp"
+ android:layout_marginTop="16dp"
android:background="@color/white"
android:fontFamily="@font/roboto_slab_bold"
android:gravity="center"
@@ -72,8 +74,7 @@
android:fontFamily="@font/roboto"
android:text="@string/date_of_creation"
android:textColor="@color/black"
- android:textSize="@dimen/subtitle"
- android:visibility="gone" />
+ android:textSize="@dimen/subtitle" />
+ android:textSize="@dimen/subtitle" />
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_group_members.xml b/app/src/main/res/layout/fragment_group_members.xml
index 7066ef0..05f3c89 100644
--- a/app/src/main/res/layout/fragment_group_members.xml
+++ b/app/src/main/res/layout/fragment_group_members.xml
@@ -6,19 +6,30 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".fragments.GroupMembersFragment">
-
+ app:layout_constraintStart_toStartOf="parent"
+ app:cornerRadius="10dp"
+ app:strokeWidth="2dp"
+ app:strokeColor="@color/gray"/>
+
+
-
+ app:cornerRadius="10dp"
+ app:strokeWidth="2dp"
+ app:strokeColor="@color/gray"/>
-
-
-
-
-
-
-
-
-
+ app:layout_constraintStart_toStartOf="parent" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_see_details.xml b/app/src/main/res/layout/fragment_see_details.xml
index 129fa76..ab86b50 100644
--- a/app/src/main/res/layout/fragment_see_details.xml
+++ b/app/src/main/res/layout/fragment_see_details.xml
@@ -7,30 +7,57 @@
android:layout_height="match_parent"
tools:context=".fragments.SeeDetailsFragment">
-
+ app:layout_constraintTop_toBottomOf="@+id/textConfirm2" />
-
+
+
+
+ android:fontFamily="@font/roboto"
+ android:text="@string/deleteEvent"
+ android:textColor="#F44336"
+ android:textSize="@dimen/plain_text"
+ android:visibility="gone"
+ android:layout_marginBottom="30dp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent" />
+
@@ -61,13 +89,12 @@
android:id="@+id/cost"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="32dp"
+ android:layout_marginTop="20dp"
android:fontFamily="@font/roboto"
android:text="@string/cost"
android:textColor="#515151"
android:textSize="@dimen/subtitle"
- app:layout_constraintEnd_toStartOf="@+id/expenseName"
- app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintStart_toStartOf="@+id/whoParticipatedRecycler"
app:layout_constraintTop_toBottomOf="@+id/expenseName" />
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_select_second_participant.xml b/app/src/main/res/layout/fragment_select_second_participant.xml
index 7494443..1d189eb 100644
--- a/app/src/main/res/layout/fragment_select_second_participant.xml
+++ b/app/src/main/res/layout/fragment_select_second_participant.xml
@@ -23,13 +23,18 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
-
-
+ app:strokeColor="#8ABBD9"
+ app:strokeWidth="3dp" />
+
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/group_item.xml b/app/src/main/res/layout/group_item.xml
index c890b4d..75924b5 100644
--- a/app/src/main/res/layout/group_item.xml
+++ b/app/src/main/res/layout/group_item.xml
@@ -1,32 +1,37 @@
-
-
+
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/group_item_archive.xml b/app/src/main/res/layout/group_item_archive.xml
new file mode 100644
index 0000000..7675355
--- /dev/null
+++ b/app/src/main/res/layout/group_item_archive.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/notification_item.xml b/app/src/main/res/layout/notification_item.xml
index bae251c..4a56fda 100644
--- a/app/src/main/res/layout/notification_item.xml
+++ b/app/src/main/res/layout/notification_item.xml
@@ -1,144 +1,99 @@
+ android:layout_height="wrap_content">
-
+ app:strokeColor="#FF2196F3"
+ app:strokeWidth="3dp" />
-
+ app:layout_constraintBottom_toBottomOf="@+id/nameNewFriend"
+ app:layout_constraintStart_toStartOf="@+id/nameNewFriend"
+ app:layout_constraintTop_toTopOf="@+id/nameNewFriend" />
-
-
-
-
-
-
+ app:layout_constraintTop_toTopOf="parent"
+ app:strokeColor="#FF2196F3"
+ app:strokeWidth="3dp" />
+
+ app:layout_constraintBottom_toBottomOf="@+id/nameNewGroup"
+ app:layout_constraintStart_toStartOf="@+id/nameNewGroup"
+ app:layout_constraintTop_toTopOf="@+id/nameNewGroup" />
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/pop_up_window_data_conf.xml b/app/src/main/res/layout/pop_up_window_data_conf.xml
index d7e27a1..49ea6b7 100644
--- a/app/src/main/res/layout/pop_up_window_data_conf.xml
+++ b/app/src/main/res/layout/pop_up_window_data_conf.xml
@@ -1,7 +1,6 @@
@@ -76,10 +75,9 @@
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="20dp"
+ android:layout_marginTop="16dp"
android:fontFamily="@font/inter_light"
android:text="@string/see_details"
- android:textAllCaps="false"
android:textColor="#4556AF"
android:textSize="@dimen/small"
app:layout_constraintEnd_toEndOf="parent"
@@ -98,30 +96,36 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/buttonDetails" />
-
+ app:layout_constraintTop_toBottomOf="@+id/textConfirm" />
-
+ app:layout_constraintTop_toBottomOf="@+id/textConfirm" />
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/transfer_item.xml b/app/src/main/res/layout/transfer_item.xml
new file mode 100644
index 0000000..427e192
--- /dev/null
+++ b/app/src/main/res/layout/transfer_item.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/bottom_menu.xml b/app/src/main/res/menu/bottom_menu.xml
index a36c097..48aac37 100644
--- a/app/src/main/res/menu/bottom_menu.xml
+++ b/app/src/main/res/menu/bottom_menu.xml
@@ -7,7 +7,7 @@
android:id="@+id/profile_fragment"/>
-
-
+ tools:layout="@layout/fragment_expense_who_spent" />
\ No newline at end of file
diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml
index 66969ec..52809fd 100644
--- a/app/src/main/res/navigation/nav_graph.xml
+++ b/app/src/main/res/navigation/nav_graph.xml
@@ -107,6 +107,11 @@
+
+
+
+
+
-