Курсовая: Вроде готово

This commit is contained in:
Amon 2023-12-27 20:15:34 +04:00
parent 7b3fcfa792
commit 50f3d5bf55
61 changed files with 795 additions and 293 deletions

View File

@ -2,11 +2,22 @@ package com.example.dtf
import android.app.Application import android.app.Application
import androidx.room.* import androidx.room.*
import com.example.dtf.api.ServerService import com.example.dtf.data.api.ServerService
import com.example.dtf.db.AppDatabase import com.example.dtf.data.db.AppDatabase
import com.example.dtf.repositories.* import com.example.dtf.data.repositories.ICategoryRepository
import com.example.dtf.repositories.offline.* import com.example.dtf.data.repositories.ICommentRepository
import com.example.dtf.repositories.online.* import com.example.dtf.data.repositories.ILikeRepository
import com.example.dtf.data.repositories.IPostRepository
import com.example.dtf.data.repositories.IUserRepository
import com.example.dtf.data.repositories.offline.OfflineCategoryRepository
import com.example.dtf.data.repositories.offline.OfflineCommentRepository
import com.example.dtf.data.repositories.offline.OfflineLikeRepository
import com.example.dtf.data.repositories.offline.OfflinePostRepository
import com.example.dtf.data.repositories.offline.OfflineUserRepository
import com.example.dtf.data.repositories.online.RestCommentRepository
import com.example.dtf.data.repositories.online.RestLikeRepository
import com.example.dtf.data.repositories.online.RestPostRepository
import com.example.dtf.data.repositories.online.RestUserRepository
import com.example.dtf.repositories.online.mediator.RestCategoryRepository import com.example.dtf.repositories.online.mediator.RestCategoryRepository
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides

View File

@ -1,15 +1,16 @@
package com.example.dtf package com.example.dtf
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.os.Build
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.annotation.RequiresApi
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.material.Icon import androidx.compose.material.Icon
import androidx.compose.material.IconButton import androidx.compose.material.IconButton
import androidx.compose.material.Scaffold import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
@ -24,19 +25,21 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.navigation.navigation import androidx.navigation.navigation
import com.example.dtf.screens.EditPostScreen import com.example.dtf.ui.screens.EditPostScreen
import com.example.dtf.screens.LoginScreen import com.example.dtf.ui.screens.LoginScreen
import com.example.dtf.screens.NewPostScreen import com.example.dtf.ui.screens.NewPostScreen
import com.example.dtf.screens.PostScreen import com.example.dtf.ui.screens.PostScreen
import com.example.dtf.screens.PostsScreen import com.example.dtf.ui.screens.PostsScreen
import com.example.dtf.screens.ProfileScreen import com.example.dtf.ui.screens.ProfileScreen
import com.example.dtf.screens.RegisterScreen import com.example.dtf.ui.screens.RegisterScreen
import com.example.dtf.utils.ScreenPaths import com.example.dtf.ui.screens.TopPostsScreen
import com.example.dtf.widgets.BottomNavBar import com.example.dtf.ui.utils.ScreenPaths
import com.example.dtf.ui.widgets.BottomNavBar
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint @AndroidEntryPoint
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
@RequiresApi(Build.VERSION_CODES.O)
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter",
"UnusedMaterialScaffoldPaddingParameter" "UnusedMaterialScaffoldPaddingParameter"
) )
@ -100,6 +103,10 @@ class MainActivity : ComponentActivity() {
includeBackButton.value = false includeBackButton.value = false
PostsScreen(navController) PostsScreen(navController)
} }
composable(ScreenPaths.TopPosts.route) {
includeBackButton.value = false
TopPostsScreen(navController)
}
composable(ScreenPaths.NewPost.route) { composable(ScreenPaths.NewPost.route) {
includeBackButton.value = true includeBackButton.value = true
NewPostScreen(navController) NewPostScreen(navController)

View File

@ -1,30 +1,28 @@
package com.example.dtf.api package com.example.dtf.data.api
import com.example.dtf.dto.Credentials import com.example.dtf.data.dto.Credentials
import com.example.dtf.dto.EditPostDto import com.example.dtf.data.dto.EditPostDto
import com.example.dtf.dto.MeUser import com.example.dtf.data.dto.MeUser
import com.example.dtf.dto.NewCommentDto import com.example.dtf.data.dto.NewCommentDto
import com.example.dtf.dto.NewPostDto import com.example.dtf.data.dto.NewPostDto
import com.example.dtf.dto.Token import com.example.dtf.data.dto.Token
import com.example.dtf.dto.remote.CategoriesResponse import com.example.dtf.data.dto.remote.CategoriesResponse
import com.example.dtf.dto.remote.CommentsResponse import com.example.dtf.data.dto.remote.CommentsResponse
import com.example.dtf.dto.remote.PostsResponse import com.example.dtf.data.dto.remote.PostsResponse
import com.example.dtf.models.Category import com.example.dtf.data.models.Comment
import com.example.dtf.models.Comment import com.example.dtf.data.models.Post
import com.example.dtf.models.Post import com.example.dtf.data.models.User
import com.example.dtf.models.User
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.http.POST
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path import retrofit2.http.Path
import retrofit2.http.Query import retrofit2.http.Query
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import retrofit2.http.Header
interface ServerService { interface ServerService {
@POST("auth/login") @POST("auth/login")
@ -53,6 +51,13 @@ interface ServerService {
@Query("limit") limit: Int? @Query("limit") limit: Int?
): PostsResponse ): PostsResponse
@GET("post/top")
suspend fun getTopPosts(
@Query("category") categoryId: Int,
@Query("from_date") fromDate: String?,
@Query("to_date") toDate: String?
): List<Post>
@GET("post/{postId}") @GET("post/{postId}")
suspend fun getPost( suspend fun getPost(
@Path("postId") postId: Int @Path("postId") postId: Int
@ -107,7 +112,7 @@ interface ServerService {
): User ): User
companion object { companion object {
private const val BASE_URL = "http://192.168.1.9:8000/" private const val BASE_URL = "http://192.168.0.103:8000/"
private var _token: String = "" private var _token: String = ""

View File

@ -1,8 +1,13 @@
package com.example.dtf.dao package com.example.dtf.data.dao
import androidx.paging.PagingSource import androidx.paging.PagingSource
import androidx.room.* import androidx.room.Dao
import com.example.dtf.models.* import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.example.dtf.data.models.Category
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View File

@ -1,8 +1,13 @@
package com.example.dtf.dao package com.example.dtf.data.dao
import androidx.paging.PagingSource import androidx.paging.PagingSource
import androidx.room.* import androidx.room.Dao
import com.example.dtf.models.* import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.example.dtf.data.models.Comment
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View File

@ -1,7 +1,11 @@
package com.example.dtf.dao package com.example.dtf.data.dao
import androidx.room.* import androidx.room.Dao
import com.example.dtf.models.Like import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.dtf.data.models.Like
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View File

@ -1,8 +1,13 @@
package com.example.dtf.dao package com.example.dtf.data.dao
import androidx.paging.PagingSource import androidx.paging.PagingSource
import androidx.room.* import androidx.room.Dao
import com.example.dtf.models.* import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.example.dtf.data.models.Post
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View File

@ -1,7 +1,12 @@
package com.example.dtf.dao package com.example.dtf.data.dao
import androidx.room.* import androidx.room.Dao
import com.example.dtf.models.User import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.example.dtf.data.models.User
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View File

@ -1,18 +1,18 @@
package com.example.dtf.db package com.example.dtf.data.db
import android.content.Context import androidx.room.Database
import androidx.room.* import androidx.room.RoomDatabase
import com.example.dtf.models.Category import androidx.room.TypeConverters
import com.example.dtf.models.Comment import com.example.dtf.data.dao.CategoryDao
import com.example.dtf.models.Post import com.example.dtf.data.dao.CommentDao
import com.example.dtf.models.User import com.example.dtf.data.dao.LikeDao
import kotlinx.coroutines.CoroutineScope import com.example.dtf.data.dao.PostDao
import kotlinx.coroutines.Dispatchers import com.example.dtf.data.dao.UserDao
import kotlinx.coroutines.launch import com.example.dtf.data.models.Category
import androidx.sqlite.db.SupportSQLiteDatabase import com.example.dtf.data.models.Comment
import com.example.dtf.dao.* import com.example.dtf.data.models.Like
import com.example.dtf.models.Like import com.example.dtf.data.models.Post
import java.util.Date import com.example.dtf.data.models.User
@Database( @Database(
entities = [ entities = [

View File

@ -1,4 +1,4 @@
package com.example.dtf.db package com.example.dtf.data.db
import androidx.room.TypeConverter import androidx.room.TypeConverter
import java.util.Date import java.util.Date

View File

@ -1,4 +1,4 @@
package com.example.dtf.dto package com.example.dtf.data.dto
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,4 +1,4 @@
package com.example.dtf.dto package com.example.dtf.data.dto
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,4 +1,4 @@
package com.example.dtf.dto package com.example.dtf.data.dto
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,4 +1,4 @@
package com.example.dtf.dto package com.example.dtf.data.dto
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,4 +1,4 @@
package com.example.dtf.dto package com.example.dtf.data.dto
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,4 +1,4 @@
package com.example.dtf.dto package com.example.dtf.data.dto
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,6 +1,6 @@
package com.example.dtf.dto.remote package com.example.dtf.data.dto.remote
import com.example.dtf.models.Category import com.example.dtf.data.models.Category
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable

View File

@ -1,6 +1,6 @@
package com.example.dtf.dto.remote package com.example.dtf.data.dto.remote
import com.example.dtf.models.Comment import com.example.dtf.data.models.Comment
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable

View File

@ -1,6 +1,6 @@
package com.example.dtf.dto.remote package com.example.dtf.data.dto.remote
import com.example.dtf.models.Post import com.example.dtf.data.models.Post
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable

View File

@ -1,6 +1,8 @@
package com.example.dtf.models package com.example.dtf.data.models
import androidx.room.* import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Entity(tableName = "category") @Entity(tableName = "category")

View File

@ -1,6 +1,8 @@
package com.example.dtf.models package com.example.dtf.data.models
import androidx.room.* import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Entity(tableName = "comment") @Entity(tableName = "comment")

View File

@ -1,6 +1,7 @@
package com.example.dtf.models package com.example.dtf.data.models
import androidx.room.* import androidx.room.ColumnInfo
import androidx.room.Entity
@Entity(tableName = "likes", primaryKeys = ["user_id", "post_id"]) @Entity(tableName = "likes", primaryKeys = ["user_id", "post_id"])
data class Like ( data class Like (

View File

@ -1,6 +1,8 @@
package com.example.dtf.models package com.example.dtf.data.models
import androidx.room.* import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
//private val posts = listOf( //private val posts = listOf(

View File

@ -1,6 +1,8 @@
package com.example.dtf.models package com.example.dtf.data.models
import androidx.room.* import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Entity(tableName = "user") @Entity(tableName = "user")

View File

@ -1,7 +1,7 @@
package com.example.dtf.repositories package com.example.dtf.data.repositories
import androidx.paging.PagingData import androidx.paging.PagingData
import com.example.dtf.models.Category import com.example.dtf.data.models.Category
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
interface ICategoryRepository { interface ICategoryRepository {

View File

@ -1,7 +1,7 @@
package com.example.dtf.repositories package com.example.dtf.data.repositories
import androidx.paging.PagingData import androidx.paging.PagingData
import com.example.dtf.models.Comment import com.example.dtf.data.models.Comment
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
interface ICommentRepository { interface ICommentRepository {

View File

@ -1,6 +1,6 @@
package com.example.dtf.repositories package com.example.dtf.data.repositories
import com.example.dtf.models.Like import com.example.dtf.data.models.Like
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
interface ILikeRepository { interface ILikeRepository {

View File

@ -1,8 +1,9 @@
package com.example.dtf.repositories package com.example.dtf.data.repositories
import androidx.paging.PagingData import androidx.paging.PagingData
import com.example.dtf.models.Post import com.example.dtf.data.models.Post
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import java.time.LocalDate
interface IPostRepository { interface IPostRepository {
suspend fun insert(post: Post) suspend fun insert(post: Post)
@ -10,4 +11,6 @@ interface IPostRepository {
fun getById(id: Int): Flow<Post> fun getById(id: Int): Flow<Post>
fun getByCategory(categoryId: Int): Flow<PagingData<Post>> fun getByCategory(categoryId: Int): Flow<PagingData<Post>>
fun getTopTen(categoryId: Int, fromDate: LocalDate, toDate: LocalDate): Flow<List<Post>>
} }

View File

@ -1,6 +1,6 @@
package com.example.dtf.repositories package com.example.dtf.data.repositories
import com.example.dtf.models.User import com.example.dtf.data.models.User
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
interface IUserRepository { interface IUserRepository {

View File

@ -1,10 +1,10 @@
package com.example.dtf.repositories.offline package com.example.dtf.data.repositories.offline
import androidx.paging.Pager import androidx.paging.Pager
import androidx.paging.PagingConfig import androidx.paging.PagingConfig
import com.example.dtf.dao.CategoryDao import com.example.dtf.data.dao.CategoryDao
import com.example.dtf.models.Category import com.example.dtf.data.models.Category
import com.example.dtf.repositories.ICategoryRepository import com.example.dtf.data.repositories.ICategoryRepository
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import javax.inject.Inject import javax.inject.Inject

View File

@ -1,9 +1,10 @@
package com.example.dtf.repositories.offline package com.example.dtf.data.repositories.offline
import androidx.paging.* import androidx.paging.Pager
import com.example.dtf.dao.CommentDao import androidx.paging.PagingConfig
import com.example.dtf.models.Comment import com.example.dtf.data.dao.CommentDao
import com.example.dtf.repositories.ICommentRepository import com.example.dtf.data.models.Comment
import com.example.dtf.data.repositories.ICommentRepository
import javax.inject.Inject import javax.inject.Inject
class OfflineCommentRepository @Inject constructor( class OfflineCommentRepository @Inject constructor(

View File

@ -1,8 +1,8 @@
package com.example.dtf.repositories.offline package com.example.dtf.data.repositories.offline
import com.example.dtf.dao.LikeDao import com.example.dtf.data.dao.LikeDao
import com.example.dtf.models.Like import com.example.dtf.data.models.Like
import com.example.dtf.repositories.ILikeRepository import com.example.dtf.data.repositories.ILikeRepository
import javax.inject.Inject import javax.inject.Inject
class OfflineLikeRepository @Inject constructor( class OfflineLikeRepository @Inject constructor(

View File

@ -1,9 +1,12 @@
package com.example.dtf.repositories.offline package com.example.dtf.data.repositories.offline
import androidx.paging.* import androidx.paging.Pager
import com.example.dtf.dao.PostDao import androidx.paging.PagingConfig
import com.example.dtf.models.Post import com.example.dtf.data.dao.PostDao
import com.example.dtf.repositories.IPostRepository import com.example.dtf.data.models.Post
import com.example.dtf.data.repositories.IPostRepository
import kotlinx.coroutines.flow.Flow
import java.time.LocalDate
import javax.inject.Inject import javax.inject.Inject
class OfflinePostRepository @Inject constructor( class OfflinePostRepository @Inject constructor(
@ -22,4 +25,8 @@ class OfflinePostRepository @Inject constructor(
), ),
pagingSourceFactory = { postDao.getByCategory(categoryId.toString()) } pagingSourceFactory = { postDao.getByCategory(categoryId.toString()) }
).flow ).flow
override fun getTopTen(categoryId: Int, fromDate: LocalDate, toDate: LocalDate): Flow<List<Post>> {
throw NotImplementedError("Cannot access top without internet connection")
}
} }

View File

@ -1,8 +1,7 @@
package com.example.dtf.repositories.offline package com.example.dtf.data.repositories.offline
import com.example.dtf.dao.UserDao import com.example.dtf.data.dao.UserDao
import com.example.dtf.models.User import com.example.dtf.data.repositories.IUserRepository
import com.example.dtf.repositories.IUserRepository
import javax.inject.Inject import javax.inject.Inject
class OfflineUserRepository @Inject constructor( class OfflineUserRepository @Inject constructor(

View File

@ -4,12 +4,12 @@ import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager import androidx.paging.Pager
import androidx.paging.PagingConfig import androidx.paging.PagingConfig
import androidx.paging.PagingData import androidx.paging.PagingData
import com.example.dtf.api.ServerService import com.example.dtf.data.api.ServerService
import com.example.dtf.db.AppDatabase import com.example.dtf.data.db.AppDatabase
import com.example.dtf.models.Category import com.example.dtf.data.models.Category
import com.example.dtf.repositories.ICategoryRepository import com.example.dtf.data.repositories.ICategoryRepository
import com.example.dtf.data.repositories.online.mediator.CategoryMediator
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import javax.inject.Inject import javax.inject.Inject
class RestCategoryRepository @Inject constructor( class RestCategoryRepository @Inject constructor(

View File

@ -1,15 +1,15 @@
package com.example.dtf.repositories.online package com.example.dtf.data.repositories.online
import androidx.paging.ExperimentalPagingApi import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager import androidx.paging.Pager
import androidx.paging.PagingConfig import androidx.paging.PagingConfig
import androidx.paging.PagingData import androidx.paging.PagingData
import com.example.dtf.api.ServerService import com.example.dtf.data.api.ServerService
import com.example.dtf.db.AppDatabase import com.example.dtf.data.db.AppDatabase
import com.example.dtf.dto.NewCommentDto import com.example.dtf.data.dto.NewCommentDto
import com.example.dtf.models.Comment import com.example.dtf.data.models.Comment
import com.example.dtf.repositories.ICommentRepository import com.example.dtf.data.repositories.ICommentRepository
import com.example.dtf.repositories.online.mediator.CommentMediator import com.example.dtf.data.repositories.online.mediator.CommentMediator
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import javax.inject.Inject import javax.inject.Inject

View File

@ -1,9 +1,9 @@
package com.example.dtf.repositories.online package com.example.dtf.data.repositories.online
import com.example.dtf.api.ServerService import com.example.dtf.data.api.ServerService
import com.example.dtf.db.AppDatabase import com.example.dtf.data.db.AppDatabase
import com.example.dtf.models.Like import com.example.dtf.data.models.Like
import com.example.dtf.repositories.ILikeRepository import com.example.dtf.data.repositories.ILikeRepository
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import javax.inject.Inject import javax.inject.Inject

View File

@ -1,18 +1,21 @@
package com.example.dtf.repositories.online package com.example.dtf.data.repositories.online
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.paging.ExperimentalPagingApi import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager import androidx.paging.Pager
import androidx.paging.PagingConfig import androidx.paging.PagingConfig
import androidx.paging.PagingData import androidx.paging.PagingData
import com.example.dtf.api.ServerService import com.example.dtf.data.api.ServerService
import com.example.dtf.db.AppDatabase import com.example.dtf.data.db.AppDatabase
import com.example.dtf.dto.EditPostDto import com.example.dtf.data.dto.EditPostDto
import com.example.dtf.dto.NewPostDto import com.example.dtf.data.dto.NewPostDto
import com.example.dtf.models.Post import com.example.dtf.data.models.Post
import com.example.dtf.repositories.IPostRepository import com.example.dtf.data.repositories.IPostRepository
import com.example.dtf.repositories.online.mediator.PostMediator import com.example.dtf.data.repositories.online.mediator.PostMediator
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import java.time.LocalDate
import javax.inject.Inject import javax.inject.Inject
class RestPostRepository @Inject constructor( class RestPostRepository @Inject constructor(
@ -46,4 +49,17 @@ class RestPostRepository @Inject constructor(
remoteMediator = PostMediator(appDatabase, serverService, categoryId.toString()), remoteMediator = PostMediator(appDatabase, serverService, categoryId.toString()),
pagingSourceFactory = { appDatabase.postDao().getByCategory(categoryId.toString()) } pagingSourceFactory = { appDatabase.postDao().getByCategory(categoryId.toString()) }
).flow ).flow
@RequiresApi(Build.VERSION_CODES.O)
override fun getTopTen(categoryId: Int, fromDate: LocalDate, toDate: LocalDate): Flow<List<Post>> {
return flow {
emit(
serverService.getTopPosts(
categoryId,
"${fromDate.year}-${fromDate.monthValue}-${fromDate.dayOfMonth}",
"${toDate.year}-${toDate.monthValue}-${toDate.dayOfMonth}"
)
)
}
}
} }

View File

@ -1,9 +1,9 @@
package com.example.dtf.repositories.online package com.example.dtf.data.repositories.online
import com.example.dtf.api.ServerService import com.example.dtf.data.api.ServerService
import com.example.dtf.db.AppDatabase import com.example.dtf.data.db.AppDatabase
import com.example.dtf.models.User import com.example.dtf.data.models.User
import com.example.dtf.repositories.IUserRepository import com.example.dtf.data.repositories.IUserRepository
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import javax.inject.Inject import javax.inject.Inject

View File

@ -1,13 +1,13 @@
package com.example.dtf.repositories.online.mediator package com.example.dtf.data.repositories.online.mediator
import androidx.paging.ExperimentalPagingApi import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType import androidx.paging.LoadType
import androidx.paging.PagingState import androidx.paging.PagingState
import androidx.paging.RemoteMediator import androidx.paging.RemoteMediator
import androidx.room.withTransaction import androidx.room.withTransaction
import com.example.dtf.api.ServerService import com.example.dtf.data.api.ServerService
import com.example.dtf.db.AppDatabase import com.example.dtf.data.db.AppDatabase
import com.example.dtf.models.Category import com.example.dtf.data.models.Category
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import java.io.IOException import java.io.IOException

View File

@ -1,13 +1,13 @@
package com.example.dtf.repositories.online.mediator package com.example.dtf.data.repositories.online.mediator
import androidx.paging.ExperimentalPagingApi import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType import androidx.paging.LoadType
import androidx.paging.PagingState import androidx.paging.PagingState
import androidx.paging.RemoteMediator import androidx.paging.RemoteMediator
import androidx.room.withTransaction import androidx.room.withTransaction
import com.example.dtf.api.ServerService import com.example.dtf.data.api.ServerService
import com.example.dtf.db.AppDatabase import com.example.dtf.data.db.AppDatabase
import com.example.dtf.models.Comment import com.example.dtf.data.models.Comment
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import java.io.IOException import java.io.IOException

View File

@ -1,13 +1,13 @@
package com.example.dtf.repositories.online.mediator package com.example.dtf.data.repositories.online.mediator
import androidx.paging.ExperimentalPagingApi import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType import androidx.paging.LoadType
import androidx.paging.PagingState import androidx.paging.PagingState
import androidx.paging.RemoteMediator import androidx.paging.RemoteMediator
import androidx.room.withTransaction import androidx.room.withTransaction
import com.example.dtf.api.ServerService import com.example.dtf.data.api.ServerService
import com.example.dtf.db.AppDatabase import com.example.dtf.data.db.AppDatabase
import com.example.dtf.models.Post import com.example.dtf.data.models.Post
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import java.io.IOException import java.io.IOException

View File

@ -1,26 +1,40 @@
package com.example.dtf.screens package com.example.dtf.ui.screens
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.* import androidx.compose.material.AlertDialog
import androidx.compose.runtime.* import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.* import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.* import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.utils.ScreenPaths import com.example.dtf.ui.utils.ScreenPaths
import com.example.dtf.viewmodels.EditPostViewModel import com.example.dtf.ui.viewmodels.EditPostViewModel
import com.example.dtf.widgets.MyTextField import com.example.dtf.ui.widgets.MyTextField
@Composable @Composable
fun EditPostScreen(navController: NavHostController, postId: Int) { fun EditPostScreen(navController: NavHostController, postId: Int) {

View File

@ -1,25 +1,40 @@
package com.example.dtf.screens package com.example.dtf.ui.screens
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.* import androidx.compose.material.AlertDialog
import androidx.compose.runtime.* import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.* import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.* import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.utils.ScreenPaths import com.example.dtf.ui.utils.ScreenPaths
import com.example.dtf.viewmodels.LoginViewModel import com.example.dtf.ui.viewmodels.LoginViewModel
import com.example.dtf.widgets.MyTextField import com.example.dtf.ui.widgets.MyTextField
@Composable @Composable
fun LoginScreen(navController: NavHostController) { fun LoginScreen(navController: NavHostController) {

View File

@ -1,29 +1,45 @@
package com.example.dtf.screens package com.example.dtf.ui.screens
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.* import androidx.compose.material.AlertDialog
import androidx.compose.runtime.* import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.DropdownMenu
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.* import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.* import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.paging.compose.collectAsLazyPagingItems
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.models.Category import com.example.dtf.data.models.Category
import com.example.dtf.utils.ScreenPaths import com.example.dtf.ui.utils.ScreenPaths
import com.example.dtf.viewmodels.NewPostViewModel import com.example.dtf.ui.viewmodels.NewPostViewModel
import com.example.dtf.widgets.MyTextField import com.example.dtf.ui.widgets.MyTextField
@Composable @Composable
fun NewPostScreen(navController: NavHostController) { fun NewPostScreen(navController: NavHostController) {

View File

@ -1,32 +1,51 @@
package com.example.dtf.screens package com.example.dtf.ui.screens
import androidx.compose.foundation.layout.* import androidx.compose.foundation.background
import androidx.compose.foundation.* import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.* import androidx.compose.material.Divider
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddCircle import androidx.compose.material.icons.filled.AddCircle
import androidx.compose.material.icons.filled.ThumbUp import androidx.compose.material.icons.filled.ThumbUp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.* import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.* import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.ui.draw.* import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.* import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.* import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey import androidx.paging.compose.itemKey
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.models.Comment import com.example.dtf.data.models.Comment
import com.example.dtf.utils.ScreenPaths import com.example.dtf.ui.utils.ScreenPaths
import com.example.dtf.viewmodels.PostViewModel import com.example.dtf.ui.viewmodels.PostViewModel
import com.example.dtf.widgets.MyTextField import com.example.dtf.ui.widgets.MyTextField
@Composable @Composable
fun PostScreen(postId: Int, navController: NavHostController) { fun PostScreen(postId: Int, navController: NavHostController) {

View File

@ -1,31 +1,49 @@
package com.example.dtf.screens package com.example.dtf.ui.screens
import androidx.compose.foundation.layout.* import androidx.compose.foundation.background
import androidx.compose.foundation.* import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.material.* import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ThumbUp import androidx.compose.material.icons.filled.ThumbUp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.* import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.* import androidx.compose.runtime.MutableState
import androidx.compose.ui.draw.* import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.ui.geometry.* import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.* import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.* import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.paging.PagingData import androidx.paging.PagingData
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey import androidx.paging.compose.itemKey
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.models.Category import com.example.dtf.data.models.Category
import com.example.dtf.models.Post import com.example.dtf.data.models.Post
import com.example.dtf.utils.ScreenPaths import com.example.dtf.ui.utils.ScreenPaths
import com.example.dtf.viewmodels.PostsViewModel import com.example.dtf.ui.viewmodels.PostsViewModel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Composable @Composable

View File

@ -1,20 +1,33 @@
package com.example.dtf.screens package com.example.dtf.ui.screens
import androidx.compose.foundation.* import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.* import androidx.compose.material.Card
import androidx.compose.material.Divider
import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.* import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.* import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.* import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.utils.ScreenPaths import com.example.dtf.ui.utils.ScreenPaths
import com.example.dtf.viewmodels.ProfileViewModel import com.example.dtf.ui.viewmodels.ProfileViewModel
@Composable @Composable
fun ProfileScreen(navController: NavHostController) { fun ProfileScreen(navController: NavHostController) {

View File

@ -1,11 +1,15 @@
package com.example.dtf.screens package com.example.dtf.ui.screens
import android.graphics.drawable.shapes.Shape
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.AlertDialog import androidx.compose.material.AlertDialog
import androidx.compose.material.Button import androidx.compose.material.Button
@ -16,22 +20,19 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.* import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.example.dtf.utils.ScreenPaths import com.example.dtf.ui.utils.ScreenPaths
import com.example.dtf.viewmodels.RegisterViewModel import com.example.dtf.ui.viewmodels.RegisterViewModel
import com.example.dtf.widgets.MyTextField import com.example.dtf.ui.widgets.MyTextField
@Composable @Composable
fun RegisterScreen(navController: NavHostController) { fun RegisterScreen(navController: NavHostController) {

View File

@ -0,0 +1,279 @@
package com.example.dtf.ui.screens
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ThumbUp
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey
import com.example.dtf.PreferencesManager
import com.example.dtf.data.models.Category
import com.example.dtf.data.models.Post
import com.example.dtf.ui.utils.ScreenPaths
import com.example.dtf.ui.viewmodels.TopPostsViewModel
import java.time.LocalDate
import java.time.Period
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun TopPostsScreen(navController: NavHostController) {
val viewModel = hiltViewModel<TopPostsViewModel>()
val currentCategory = remember { mutableStateOf<Category?>(null) }
val categories = viewModel.getCategoriesListUiState().collectAsLazyPagingItems()
val dateFrom = remember { mutableStateOf(LocalDate.now()) }
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(15.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(modifier = Modifier.height(15.dp))
Text(
text = "Топ 10 новостей",
fontSize = 36.sp
)
DateSelect(viewModel, dateFrom, currentCategory)
Categories(viewModel, currentCategory, categories, dateFrom)
Posts(viewModel, navController)
Spacer(modifier = Modifier.height(60.dp))
}
}
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun DateSelect(
viewModel: TopPostsViewModel,
dateFrom: MutableState<LocalDate>,
currentCategory: MutableState<Category?>
) {
val week = Pair(LocalDate.now() - Period.ofWeeks(1), "Неделя")
val month = Pair(LocalDate.now() - Period.ofMonths(1), "Месяц")
val year = Pair(LocalDate.now() - Period.ofYears(1), "Год")
dateFrom.value = week.first
Row(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.1f)
.background(Color.White),
horizontalArrangement = Arrangement.spacedBy(25.dp),
verticalAlignment = Alignment.CenterVertically
) {
Spacer(modifier = Modifier)
listOf(week, month, year).forEach { (date, name) ->
Text(
modifier = Modifier
.clickable {
dateFrom.value = date
if (currentCategory.value != null) {
viewModel.retrievePosts(currentCategory.value!!.id!!, dateFrom.value, LocalDate.now())
}
}
.drawBehind {
if (dateFrom.value == date) {
val strokeWidthPx = 2.dp.toPx()
val verticalOffset = size.height + 2.sp.toPx()
drawLine(
color = Color(0xFF319CFF),
strokeWidth = strokeWidthPx,
start = Offset(0f, verticalOffset),
end = Offset(size.width, verticalOffset)
)
}
},
text = name,
fontSize = 22.sp
)
}
}
}
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun Categories(
viewModel: TopPostsViewModel,
currentCategory: MutableState<Category?>,
categories: LazyPagingItems<Category>,
dateFrom: MutableState<LocalDate>) {
LazyRow(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.1f)
.background(Color.White),
horizontalArrangement = Arrangement.spacedBy(25.dp),
verticalAlignment = Alignment.CenterVertically
) {
item {
Spacer(modifier = Modifier)
}
items(
count = categories.itemCount,
key = categories.itemKey()
) {
if (currentCategory.value == null) {
currentCategory.value = categories[0]
viewModel.retrievePosts(currentCategory.value!!.id!!, dateFrom.value, LocalDate.now())
}
Text(
modifier = Modifier
.clickable {
currentCategory.value = categories[it]!!
viewModel.retrievePosts(
currentCategory.value!!.id!!,
dateFrom.value,
LocalDate.now()
)
}
.drawBehind {
if (categories[it]!!.name == currentCategory.value?.name) {
val strokeWidthPx = 2.dp.toPx()
val verticalOffset = size.height + 2.sp.toPx()
drawLine(
color = Color(0xFF319CFF),
strokeWidth = strokeWidthPx,
start = Offset(0f, verticalOffset),
end = Offset(size.width, verticalOffset)
)
}
},
text = categories[it]!!.name,
fontSize = 22.sp
)
}
}
}
@Composable
fun Posts(viewModel: TopPostsViewModel, navController: NavHostController) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
for (post in viewModel.posts.observeAsState(listOf()).value) {
Post(viewModel, navController, post)
}
}
}
@Composable
fun Post(viewModel: TopPostsViewModel, navController: NavHostController, post: Post) {
val sharedPref = PreferencesManager(LocalContext.current)
val likes = remember { mutableIntStateOf(post.likes) }
val isLiked = remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
viewModel.isLiked(sharedPref, post.id!!).collect {
isLiked.value = it
}
}
Column(
modifier = Modifier
.heightIn(min = 250.dp, max = 300.dp)
.fillMaxWidth()
.background(Color.White)
.clickable {
navController.navigate(ScreenPaths.Post.route.replace("{post}", post.id.toString()))
},
verticalArrangement = Arrangement.spacedBy(5.dp),
horizontalAlignment = Alignment.Start
) {
Text(
modifier = Modifier.padding(10.dp),
text = post.title,
fontSize = 26.sp
)
Text(
modifier = Modifier
.fillMaxHeight(0.6f)
.padding(10.dp, 0.dp, 10.dp, 0.dp),
text = post.content,
fontSize = 20.sp,
overflow = TextOverflow.Ellipsis
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = post.date,
fontSize = 14.sp,
color = Color(0xFFCECCCC)
)
Row (
modifier = Modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.End
) {
Text(
text = likes.intValue.toString(),
fontSize = 16.sp,
color = Color.Green
)
Icon(
modifier = Modifier
.padding(start = 8.dp)
.clickable {
if (isLiked.value) {
viewModel.unlikePost(sharedPref, post.id!!)
likes.intValue--
} else {
viewModel.likePost(sharedPref, post.id!!)
likes.intValue++
}
isLiked.value = !isLiked.value
},
imageVector = Icons.Default.ThumbUp,
contentDescription = null,
tint = if (isLiked.value) { Color(40, 200, 40, 255) } else {
Color.Black}
)
}
}
}
}

View File

@ -1,4 +1,4 @@
package com.example.dtf.utils package com.example.dtf.ui.utils
sealed class ScreenPaths (val route: String){ sealed class ScreenPaths (val route: String){
object Auth: ScreenPaths("auth") object Auth: ScreenPaths("auth")
@ -6,6 +6,7 @@ sealed class ScreenPaths (val route: String){
object Register: ScreenPaths("auth/register") object Register: ScreenPaths("auth/register")
object Post: ScreenPaths("posts/{post}") object Post: ScreenPaths("posts/{post}")
object Posts: ScreenPaths("posts") object Posts: ScreenPaths("posts")
object TopPosts: ScreenPaths("posts/top")
object NewPost: ScreenPaths("posts/new") object NewPost: ScreenPaths("posts/new")
object EditPost: ScreenPaths("posts/{post}/edit") object EditPost: ScreenPaths("posts/{post}/edit")
object Profile: ScreenPaths("profile") object Profile: ScreenPaths("profile")

View File

@ -1,12 +1,12 @@
package com.example.dtf.viewmodels package com.example.dtf.ui.viewmodels
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.models.Post import com.example.dtf.data.models.Post
import com.example.dtf.repositories.IPostRepository import com.example.dtf.data.repositories.IPostRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject

View File

@ -1,13 +1,12 @@
package com.example.dtf.viewmodels package com.example.dtf.ui.viewmodels
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.api.ServerService import com.example.dtf.data.api.ServerService
import com.example.dtf.dto.Credentials import com.example.dtf.data.dto.Credentials
import com.example.dtf.repositories.IUserRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject

View File

@ -1,13 +1,13 @@
package com.example.dtf.viewmodels package com.example.dtf.ui.viewmodels
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.models.Post import com.example.dtf.data.models.Post
import com.example.dtf.repositories.ICategoryRepository import com.example.dtf.data.repositories.ICategoryRepository
import com.example.dtf.repositories.IPostRepository import com.example.dtf.data.repositories.IPostRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.Date import java.util.Date

View File

@ -1,4 +1,4 @@
package com.example.dtf.viewmodels package com.example.dtf.ui.viewmodels
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
@ -6,13 +6,13 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData import androidx.paging.PagingData
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.models.Comment import com.example.dtf.data.models.Comment
import com.example.dtf.models.Like import com.example.dtf.data.models.Like
import com.example.dtf.models.Post import com.example.dtf.data.models.Post
import com.example.dtf.repositories.ICommentRepository import com.example.dtf.data.repositories.ICommentRepository
import com.example.dtf.repositories.ILikeRepository import com.example.dtf.data.repositories.ILikeRepository
import com.example.dtf.repositories.IPostRepository import com.example.dtf.data.repositories.IPostRepository
import com.example.dtf.repositories.IUserRepository import com.example.dtf.data.repositories.IUserRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

View File

@ -1,12 +1,12 @@
package com.example.dtf.viewmodels package com.example.dtf.ui.viewmodels
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.models.Like import com.example.dtf.data.models.Like
import com.example.dtf.repositories.ICategoryRepository import com.example.dtf.data.repositories.ICategoryRepository
import com.example.dtf.repositories.ILikeRepository import com.example.dtf.data.repositories.ILikeRepository
import com.example.dtf.repositories.IPostRepository import com.example.dtf.data.repositories.IPostRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@ -47,7 +47,5 @@ class PostsViewModel @Inject constructor(
fun getCategoriesListUiState() = categoryRepository.getAll() fun getCategoriesListUiState() = categoryRepository.getAll()
fun getInitialCategory() = categoryRepository.getFirst()
fun getPostsListUiState(categoryId: Int) = postRepository.getByCategory(categoryId) fun getPostsListUiState(categoryId: Int) = postRepository.getByCategory(categoryId)
} }

View File

@ -1,14 +1,12 @@
package com.example.dtf.viewmodels package com.example.dtf.ui.viewmodels
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.models.User import com.example.dtf.data.models.User
import com.example.dtf.repositories.offline.OfflineUserRepository import com.example.dtf.data.repositories.offline.OfflineUserRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel

View File

@ -1,12 +1,11 @@
package com.example.dtf.viewmodels package com.example.dtf.ui.viewmodels
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.dtf.api.ServerService import com.example.dtf.data.api.ServerService
import com.example.dtf.dto.Credentials import com.example.dtf.data.dto.Credentials
import com.example.dtf.repositories.offline.OfflineUserRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject

View File

@ -0,0 +1,63 @@
package com.example.dtf.ui.viewmodels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.dtf.PreferencesManager
import com.example.dtf.data.models.Like
import com.example.dtf.data.models.Post
import com.example.dtf.data.repositories.ICategoryRepository
import com.example.dtf.data.repositories.ILikeRepository
import com.example.dtf.data.repositories.IPostRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import java.time.LocalDate
import javax.inject.Inject
@HiltViewModel
class TopPostsViewModel @Inject constructor(
private val postRepository: IPostRepository,
private val categoryRepository: ICategoryRepository,
private val likeRepository: ILikeRepository
) : ViewModel() {
private val _posts = MutableLiveData<List<Post>>()
val posts: LiveData<List<Post>>
get() = _posts
fun getCategoriesListUiState() = categoryRepository.getAll()
fun retrievePosts(categoryId: Int, fromDate: LocalDate, toDate: LocalDate) {
viewModelScope.launch {
postRepository.getTopTen(categoryId, fromDate, toDate).collect {
_posts.value = it
}
}
}
fun likePost(sharedPref: PreferencesManager, postId: Int) {
val userId = sharedPref.getData("userId", "-1").toInt()
if (userId == -1) return
viewModelScope.launch {
likeRepository.insert(Like(userId, postId))
}
}
fun unlikePost(sharedPref: PreferencesManager, postId: Int) {
val userId = sharedPref.getData("userId", "-1").toInt()
if (userId == -1) return
viewModelScope.launch {
likeRepository.delete(Like(userId, postId))
}
}
fun isLiked(sharedPref: PreferencesManager, postId: Int)
= likeRepository.isLikedByUser(
sharedPref.getData("userId", "-1").toInt(),
postId
)
}

View File

@ -1,9 +1,5 @@
package com.example.dtf.widgets package com.example.dtf.ui.widgets
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material.BottomNavigation import androidx.compose.material.BottomNavigation
@ -14,27 +10,17 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.Home import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Person import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.filled.Star
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.navigation.NavController
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.navigation.NavController
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import com.example.dtf.PreferencesManager import com.example.dtf.PreferencesManager
import com.example.dtf.db.AppDatabase import com.example.dtf.ui.utils.ScreenPaths
import com.example.dtf.models.User
import com.example.dtf.utils.ScreenPaths
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable @Composable
fun BottomNavBar(navController: NavController) { fun BottomNavBar(navController: NavController) {
@ -49,6 +35,7 @@ fun BottomNavBar(navController: NavController) {
val currentRoute = navBackStackEntry?.destination?.route val currentRoute = navBackStackEntry?.destination?.route
listOfNotNull( listOfNotNull(
Triple(ScreenPaths.Posts.route, Icons.Default.Home, "Новости"), Triple(ScreenPaths.Posts.route, Icons.Default.Home, "Новости"),
Triple(ScreenPaths.TopPosts.route, Icons.Default.Star, "Топ"),
if (sharedPref.getData("isModerator", "false").toBooleanStrict()) { if (sharedPref.getData("isModerator", "false").toBooleanStrict()) {
Triple(ScreenPaths.NewPost.route, Icons.Default.Edit, "Создать") Triple(ScreenPaths.NewPost.route, Icons.Default.Edit, "Создать")
} else { null }, } else { null },

View File

@ -1,4 +1,4 @@
package com.example.dtf.widgets package com.example.dtf.ui.widgets
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border