Лабораторная работа №5: Как будто бы готова
This commit is contained in:
parent
0f8abfbb99
commit
87332767e7
@ -2,6 +2,7 @@ plugins {
|
||||
id 'com.android.application'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
id 'kotlin-kapt'
|
||||
id 'org.jetbrains.kotlin.plugin.serialization'
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
@ -86,4 +87,9 @@ dependencies {
|
||||
implementation "androidx.paging:paging-runtime-ktx:$paging_version"
|
||||
implementation "androidx.paging:paging-compose:$paging_version"
|
||||
implementation("androidx.room:room-paging:2.5.0")
|
||||
|
||||
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
|
||||
implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
|
||||
}
|
@ -2,6 +2,9 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<application
|
||||
android:name=".DTFApp"
|
||||
android:allowBackup="true"
|
||||
@ -11,6 +14,7 @@
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.DTF"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
|
@ -2,13 +2,12 @@ package com.example.dtf
|
||||
|
||||
import android.app.Application
|
||||
import androidx.room.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.example.dtf.api.ServerService
|
||||
import com.example.dtf.db.AppDatabase
|
||||
import com.example.dtf.models.User
|
||||
import com.example.dtf.repositories.*
|
||||
import com.example.dtf.repositories.offline.*
|
||||
import com.example.dtf.repositories.online.*
|
||||
import com.example.dtf.repositories.online.mediator.RestCategoryRepository
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
@ -32,21 +31,65 @@ object AppModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideCategoryRepository(db: AppDatabase) = CategoryRepository(db.categoryDao())
|
||||
fun provideServerService(): ServerService = ServerService.getInstance()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideCommentRepository(db: AppDatabase) = CommentRepository(db.commentDao())
|
||||
fun provideICategoryRepository(db: AppDatabase, serverService: ServerService): ICategoryRepository = RestCategoryRepository(db, serverService)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideLikeRepository(db: AppDatabase) = LikeRepository(db.likeDao())
|
||||
fun provideICommentRepository(db: AppDatabase, serverService: ServerService): ICommentRepository = RestCommentRepository(db, serverService)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providePostRepository(db: AppDatabase) = PostRepository(db.postDao())
|
||||
fun provideILikeRepository(db: AppDatabase, serverService: ServerService): ILikeRepository = RestLikeRepository(db, serverService)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun proviveUserRepository(db: AppDatabase) = UserRepository(db.userDao())
|
||||
fun provideIPostRepository(db: AppDatabase, serverService: ServerService): IPostRepository = RestPostRepository(db, serverService)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideIUserRepository(db: AppDatabase, serverService: ServerService): IUserRepository = RestUserRepository(db, serverService)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOfflineCategoryRepository(db: AppDatabase): OfflineCategoryRepository = OfflineCategoryRepository(db.categoryDao())
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOfflineCommentRepository(db: AppDatabase): OfflineCommentRepository = OfflineCommentRepository(db.commentDao())
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOfflineLikeRepository(db: AppDatabase): OfflineLikeRepository = OfflineLikeRepository(db.likeDao())
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOfflinePostRepository(db: AppDatabase): OfflinePostRepository = OfflinePostRepository(db.postDao())
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOfflineUserRepository(db: AppDatabase): OfflineUserRepository = OfflineUserRepository(db.userDao())
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRestCategoryRepository(db: AppDatabase, serverService: ServerService): RestCategoryRepository = RestCategoryRepository(db, serverService)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRestCommentRepository(db: AppDatabase, serverService: ServerService): RestCommentRepository = RestCommentRepository(db, serverService)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRestLikeRepository(db: AppDatabase, serverService: ServerService): RestLikeRepository = RestLikeRepository(db, serverService)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRestPostRepository(db: AppDatabase, serverService: ServerService): RestPostRepository = RestPostRepository(db, serverService)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRestUserRepository(db: AppDatabase, serverService: ServerService): RestUserRepository = RestUserRepository(db, serverService)
|
||||
}
|
152
app/src/main/java/com/example/dtf/api/ServerService.kt
Normal file
152
app/src/main/java/com/example/dtf/api/ServerService.kt
Normal file
@ -0,0 +1,152 @@
|
||||
package com.example.dtf.api
|
||||
|
||||
import com.example.dtf.dto.Credentials
|
||||
import com.example.dtf.dto.EditPostDto
|
||||
import com.example.dtf.dto.MeUser
|
||||
import com.example.dtf.dto.NewCommentDto
|
||||
import com.example.dtf.dto.NewPostDto
|
||||
import com.example.dtf.dto.Token
|
||||
import com.example.dtf.dto.remote.CategoriesResponse
|
||||
import com.example.dtf.dto.remote.CommentsResponse
|
||||
import com.example.dtf.dto.remote.PostsResponse
|
||||
import com.example.dtf.models.Category
|
||||
import com.example.dtf.models.Comment
|
||||
import com.example.dtf.models.Post
|
||||
import com.example.dtf.models.User
|
||||
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import retrofit2.http.Header
|
||||
|
||||
interface ServerService {
|
||||
@POST("auth/login")
|
||||
suspend fun login(
|
||||
@Body credentials: Credentials
|
||||
): Token
|
||||
|
||||
@POST("auth/register")
|
||||
suspend fun register(
|
||||
@Body credentials: Credentials
|
||||
): String
|
||||
|
||||
@GET("user/me")
|
||||
suspend fun getCurrentUser(): MeUser
|
||||
|
||||
@GET("category")
|
||||
suspend fun getCategories(
|
||||
@Query("offset") offset: Int?,
|
||||
@Query("limit") limit: Int?
|
||||
): CategoriesResponse
|
||||
|
||||
@GET("post")
|
||||
suspend fun getPosts(
|
||||
@Query("category") category: Int?,
|
||||
@Query("offset") offset: Int?,
|
||||
@Query("limit") limit: Int?
|
||||
): PostsResponse
|
||||
|
||||
@GET("post/{postId}")
|
||||
suspend fun getPost(
|
||||
@Path("postId") postId: Int
|
||||
): Post
|
||||
|
||||
@POST("post")
|
||||
suspend fun createPost(
|
||||
@Body post: NewPostDto
|
||||
)
|
||||
|
||||
@POST("post/{postId}")
|
||||
suspend fun updatePost(
|
||||
@Path("postId") postId: Int,
|
||||
@Body post: EditPostDto
|
||||
)
|
||||
|
||||
@GET("comment")
|
||||
suspend fun getComments(
|
||||
@Query("postId") postId: Int?,
|
||||
@Query("offset") offset: Int?,
|
||||
@Query("limit") limit: Int?
|
||||
): CommentsResponse
|
||||
|
||||
@GET("comment/{commentId}")
|
||||
suspend fun getComment(
|
||||
@Path("commentId") commentId: Int
|
||||
): Comment
|
||||
|
||||
@POST("comment")
|
||||
suspend fun createComment(
|
||||
@Body comment: NewCommentDto
|
||||
)
|
||||
|
||||
@POST("post/{postId}/like")
|
||||
suspend fun likePost(
|
||||
@Path("postId") postId: Int
|
||||
)
|
||||
|
||||
@GET("post/{postId}/liked")
|
||||
suspend fun postIsLiked(
|
||||
@Path("postId") postId: Int
|
||||
): Boolean
|
||||
|
||||
@GET("post/{postId}/likes")
|
||||
suspend fun getPostLikes(
|
||||
@Path("postId") postId: Int
|
||||
): Int
|
||||
|
||||
@GET("user/{userId}")
|
||||
suspend fun getUser(
|
||||
@Path("userId") userId: Int
|
||||
): User
|
||||
|
||||
companion object {
|
||||
private const val BASE_URL = "http://192.168.1.9:8000/"
|
||||
|
||||
private var _token: String = ""
|
||||
|
||||
@Volatile
|
||||
private var INSTANCE: ServerService? = null
|
||||
|
||||
fun getInstance(): ServerService {
|
||||
return INSTANCE ?: synchronized(this) {
|
||||
val logger = HttpLoggingInterceptor()
|
||||
logger.level = HttpLoggingInterceptor.Level.BASIC
|
||||
val client = OkHttpClient.Builder()
|
||||
.addInterceptor(logger)
|
||||
.addInterceptor {
|
||||
val originalRequest = it.request()
|
||||
if (_token.isEmpty()) {
|
||||
it.proceed(originalRequest)
|
||||
} else {
|
||||
it.proceed(
|
||||
originalRequest
|
||||
.newBuilder()
|
||||
.header("Authorization", "Bearer $_token")
|
||||
.method(originalRequest.method, originalRequest.body)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
.build()
|
||||
return Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.client(client)
|
||||
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
|
||||
.build()
|
||||
.create(ServerService::class.java)
|
||||
.also { INSTANCE = it }
|
||||
}
|
||||
}
|
||||
|
||||
fun setToken(token: String) {
|
||||
_token = token
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
package com.example.dtf.dao
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.room.*
|
||||
import com.example.dtf.models.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface CategoryDao {
|
||||
@Insert
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(category: Category)
|
||||
|
||||
@Update
|
||||
@ -16,8 +17,14 @@ interface CategoryDao {
|
||||
suspend fun delete(category: Category)
|
||||
|
||||
@Query("select * from category")
|
||||
fun getAll() : Flow<List<Category>>
|
||||
fun getAll() : PagingSource<Int, Category>
|
||||
|
||||
@Query("select * from category")
|
||||
fun getAllCached() : Flow<List<Category>>
|
||||
|
||||
@Query("select * from category where category.id = :id")
|
||||
fun getById(id: Int) : Flow<Category>
|
||||
|
||||
@Query("select * from category limit 1")
|
||||
fun getFirst() : Flow<Category>
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface CommentDao {
|
||||
@Insert
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(comment: Comment)
|
||||
|
||||
@Update
|
||||
@ -16,12 +16,12 @@ interface CommentDao {
|
||||
@Delete
|
||||
suspend fun delete(comment: Comment)
|
||||
|
||||
@Query("select * from comment")
|
||||
fun getAll() : Flow<List<Comment>>
|
||||
|
||||
@Query("select * from comment where comment.id = :id")
|
||||
fun getById(id: Int) : Flow<Comment>
|
||||
|
||||
@Query("select * from comment where comment.post_id = :postId ORDER BY date DESC")
|
||||
@Query("select * from comment where comment.post_id = :postId ORDER BY id DESC")
|
||||
fun getByPost(postId: Int) : PagingSource<Int, Comment>
|
||||
|
||||
@Query("delete from comment where post_id = :query")
|
||||
fun deleteByQuery(query: String)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface LikeDao {
|
||||
@Insert
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(like: Like)
|
||||
|
||||
@Delete
|
||||
|
@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface PostDao {
|
||||
@Insert
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(post: Post)
|
||||
|
||||
@Update
|
||||
@ -16,12 +16,12 @@ interface PostDao {
|
||||
@Delete
|
||||
suspend fun delete(post: Post)
|
||||
|
||||
@Query("select * from post")
|
||||
fun getAll() : Flow<List<Post>>
|
||||
|
||||
@Query("select * from post where post.id = :id")
|
||||
fun getById(id: Int) : Flow<Post>
|
||||
|
||||
@Query("select * from post where post.category_id = :categoryId ORDER BY date DESC")
|
||||
fun getByCategory(categoryId: String) : PagingSource<Int, Post>
|
||||
|
||||
@Query("delete from post where category_id = :query")
|
||||
fun deleteByQuery(query: String)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface UserDao {
|
||||
@Insert
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(user: User)
|
||||
|
||||
@Update
|
||||
@ -15,12 +15,6 @@ interface UserDao {
|
||||
@Delete
|
||||
suspend fun delete(user: User)
|
||||
|
||||
@Query("select * from user order by username collate nocase asc")
|
||||
fun getAll() : Flow<List<User>>
|
||||
|
||||
@Query("select * from user where user.id = :id")
|
||||
fun getById(id: Int): Flow<User>
|
||||
|
||||
@Query("select * from user where user.username = :username and user.password = :password")
|
||||
fun getByUsernameAndPassword(username: String, password: String): Flow<User?>
|
||||
}
|
@ -22,7 +22,7 @@ import java.util.Date
|
||||
Like::class,
|
||||
Comment::class
|
||||
],
|
||||
version = 2,
|
||||
version = 4,
|
||||
exportSchema = false
|
||||
)
|
||||
@TypeConverters(Converter::class)
|
||||
|
9
app/src/main/java/com/example/dtf/dto/Credentials.kt
Normal file
9
app/src/main/java/com/example/dtf/dto/Credentials.kt
Normal file
@ -0,0 +1,9 @@
|
||||
package com.example.dtf.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Credentials(
|
||||
val username: String = "",
|
||||
val password: String = ""
|
||||
)
|
9
app/src/main/java/com/example/dtf/dto/EditPostDto.kt
Normal file
9
app/src/main/java/com/example/dtf/dto/EditPostDto.kt
Normal file
@ -0,0 +1,9 @@
|
||||
package com.example.dtf.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class EditPostDto(
|
||||
val title: String,
|
||||
val content: String
|
||||
)
|
10
app/src/main/java/com/example/dtf/dto/MeUser.kt
Normal file
10
app/src/main/java/com/example/dtf/dto/MeUser.kt
Normal file
@ -0,0 +1,10 @@
|
||||
package com.example.dtf.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class MeUser(
|
||||
val id: Int,
|
||||
val username: String,
|
||||
val is_moderator: Boolean
|
||||
)
|
9
app/src/main/java/com/example/dtf/dto/NewCommentDto.kt
Normal file
9
app/src/main/java/com/example/dtf/dto/NewCommentDto.kt
Normal file
@ -0,0 +1,9 @@
|
||||
package com.example.dtf.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class NewCommentDto(
|
||||
val post_id: Int,
|
||||
val content: String
|
||||
)
|
10
app/src/main/java/com/example/dtf/dto/NewPostDto.kt
Normal file
10
app/src/main/java/com/example/dtf/dto/NewPostDto.kt
Normal file
@ -0,0 +1,10 @@
|
||||
package com.example.dtf.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class NewPostDto(
|
||||
val title: String,
|
||||
val content: String,
|
||||
val category_id: Int
|
||||
)
|
8
app/src/main/java/com/example/dtf/dto/Token.kt
Normal file
8
app/src/main/java/com/example/dtf/dto/Token.kt
Normal file
@ -0,0 +1,8 @@
|
||||
package com.example.dtf.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Token(
|
||||
val token: String
|
||||
)
|
@ -0,0 +1,10 @@
|
||||
package com.example.dtf.dto.remote
|
||||
|
||||
import com.example.dtf.models.Category
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class CategoriesResponse(
|
||||
val categories: List<Category>,
|
||||
val nextKey: Int?
|
||||
)
|
@ -0,0 +1,10 @@
|
||||
package com.example.dtf.dto.remote
|
||||
|
||||
import com.example.dtf.models.Comment
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class CommentsResponse(
|
||||
val comments: List<Comment>,
|
||||
val nextKey: Int?
|
||||
)
|
@ -0,0 +1,10 @@
|
||||
package com.example.dtf.dto.remote
|
||||
|
||||
import com.example.dtf.models.Post
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class PostsResponse(
|
||||
val posts: List<Post>,
|
||||
val nextKey: Int?
|
||||
)
|
@ -1,8 +1,10 @@
|
||||
package com.example.dtf.models
|
||||
|
||||
import androidx.room.*
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Entity(tableName = "category")
|
||||
@Serializable
|
||||
data class Category(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo
|
||||
|
@ -1,10 +0,0 @@
|
||||
package com.example.dtf.models
|
||||
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Relation
|
||||
|
||||
data class CategoryWithPosts(
|
||||
@Embedded val category: Category,
|
||||
@Relation(parentColumn = "id", entityColumn = "category_id")
|
||||
val posts: List<Post>
|
||||
)
|
@ -1,21 +1,24 @@
|
||||
package com.example.dtf.models
|
||||
|
||||
import androidx.room.*
|
||||
import java.util.Date
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Entity(tableName = "comment")
|
||||
@Serializable
|
||||
data class Comment(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo
|
||||
val id: Int?,
|
||||
@ColumnInfo(name = "user_id")
|
||||
val userId: Int,
|
||||
val user_id: Int,
|
||||
@ColumnInfo(name = "post_id")
|
||||
val postId: Int,
|
||||
val post_id: Int,
|
||||
@ColumnInfo
|
||||
val content: String,
|
||||
@ColumnInfo
|
||||
val date: Date
|
||||
val date: String,
|
||||
@ColumnInfo
|
||||
val author: String = ""
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
@ -1,9 +1,7 @@
|
||||
package com.example.dtf.models
|
||||
|
||||
import androidx.compose.runtime.collection.MutableVector
|
||||
import androidx.compose.runtime.collection.mutableVectorOf
|
||||
import androidx.room.*
|
||||
import java.util.Date
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
//private val posts = listOf(
|
||||
// Post(
|
||||
@ -60,11 +58,9 @@ import java.util.Date
|
||||
//)
|
||||
|
||||
@Entity(
|
||||
tableName = "post",
|
||||
foreignKeys = [
|
||||
ForeignKey(User::class, ["id"], ["user_id"])
|
||||
]
|
||||
tableName = "post"
|
||||
)
|
||||
@Serializable
|
||||
data class Post(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo
|
||||
@ -74,11 +70,13 @@ data class Post(
|
||||
@ColumnInfo
|
||||
val content: String,
|
||||
@ColumnInfo
|
||||
val date: Date,
|
||||
val date: String,
|
||||
@ColumnInfo(name = "user_id")
|
||||
val userId: Int,
|
||||
val user_id: Int,
|
||||
@ColumnInfo(name = "category_id")
|
||||
val categoryId: Int
|
||||
val category_id: Int,
|
||||
@ColumnInfo
|
||||
val likes: Int = 0,
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
@ -1,10 +0,0 @@
|
||||
package com.example.dtf.models
|
||||
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Relation
|
||||
|
||||
data class PostWithComments(
|
||||
@Embedded val post: Post,
|
||||
@Relation(parentColumn = "id", entityColumn = "post_id")
|
||||
val comments: List<Comment>
|
||||
)
|
@ -1,18 +1,16 @@
|
||||
package com.example.dtf.models
|
||||
|
||||
import androidx.room.*
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Entity(tableName = "user")
|
||||
@Serializable
|
||||
data class User(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo
|
||||
val id: Int?,
|
||||
@ColumnInfo
|
||||
val username: String,
|
||||
@ColumnInfo
|
||||
val password: String,
|
||||
@ColumnInfo
|
||||
val isModerator: Boolean
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
@ -1,19 +0,0 @@
|
||||
package com.example.dtf.repositories
|
||||
|
||||
import com.example.dtf.dao.CategoryDao
|
||||
import com.example.dtf.models.Category
|
||||
import javax.inject.Inject
|
||||
|
||||
class CategoryRepository @Inject constructor(
|
||||
private val categoryDao: CategoryDao
|
||||
) {
|
||||
suspend fun insert(category: Category) = categoryDao.insert(category)
|
||||
|
||||
suspend fun update(category: Category) = categoryDao.update(category)
|
||||
|
||||
suspend fun delete(category: Category) = categoryDao.delete(category)
|
||||
|
||||
fun getAll() = categoryDao.getAll()
|
||||
|
||||
fun getById(id: Int) = categoryDao.getById(id)
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package com.example.dtf.repositories
|
||||
|
||||
import androidx.paging.*
|
||||
import com.example.dtf.dao.CommentDao
|
||||
import com.example.dtf.models.Comment
|
||||
import javax.inject.Inject
|
||||
|
||||
class CommentRepository @Inject constructor(
|
||||
private val commentDao: CommentDao
|
||||
) {
|
||||
suspend fun insert(comment: Comment) = commentDao.insert(comment)
|
||||
|
||||
suspend fun update(comment: Comment) = commentDao.update(comment)
|
||||
|
||||
suspend fun delete(comment: Comment) = commentDao.delete(comment)
|
||||
|
||||
fun getAll() = commentDao.getAll()
|
||||
|
||||
fun getById(id: Int) = commentDao.getById(id)
|
||||
|
||||
fun getByPost(postId: Int) = Pager(
|
||||
PagingConfig(
|
||||
pageSize = 5,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = { commentDao.getByPost(postId) }
|
||||
).flow
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.example.dtf.repositories
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import com.example.dtf.models.Category
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ICategoryRepository {
|
||||
fun getAll(): Flow<PagingData<Category>>
|
||||
fun getAllCached(): Flow<List<Category>>
|
||||
|
||||
fun getFirst(): Flow<Category?>
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.example.dtf.repositories
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import com.example.dtf.models.Comment
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ICommentRepository {
|
||||
suspend fun insert(comment: Comment)
|
||||
|
||||
fun getById(id: Int): Flow<Comment>
|
||||
fun getByPost(postId: Int): Flow<PagingData<Comment>>
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.example.dtf.repositories
|
||||
|
||||
import com.example.dtf.models.Like
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ILikeRepository {
|
||||
suspend fun insert(like: Like)
|
||||
suspend fun delete(like: Like)
|
||||
|
||||
fun countByPost(postId: Int): Flow<Int>
|
||||
fun isLikedByUser(userId: Int, postId: Int): Flow<Boolean>
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.example.dtf.repositories
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import com.example.dtf.models.Post
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface IPostRepository {
|
||||
suspend fun insert(post: Post)
|
||||
suspend fun update(post: Post)
|
||||
|
||||
fun getById(id: Int): Flow<Post>
|
||||
fun getByCategory(categoryId: Int): Flow<PagingData<Post>>
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.example.dtf.repositories
|
||||
|
||||
import com.example.dtf.models.User
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface IUserRepository {
|
||||
fun getById(id: Int) : Flow<User>
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package com.example.dtf.repositories
|
||||
|
||||
import com.example.dtf.dao.LikeDao
|
||||
import com.example.dtf.models.Like
|
||||
import javax.inject.Inject
|
||||
|
||||
class LikeRepository @Inject constructor(
|
||||
private val likeDao: LikeDao
|
||||
) {
|
||||
suspend fun insert(like: Like) = likeDao.insert(like)
|
||||
|
||||
suspend fun delete(like: Like) = likeDao.delete(like)
|
||||
|
||||
fun countByPost(postId: Int) = likeDao.countByPost(postId)
|
||||
|
||||
fun isLikedByUser(userId: Int, postId: Int) = likeDao.isLikedByUser(userId, postId)
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package com.example.dtf.repositories
|
||||
|
||||
import androidx.paging.*
|
||||
import com.example.dtf.dao.PostDao
|
||||
import com.example.dtf.models.Post
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class PostRepository @Inject constructor(
|
||||
private val postDao: PostDao
|
||||
) {
|
||||
suspend fun insert(post: Post) = postDao.insert(post)
|
||||
|
||||
suspend fun update(post: Post) = postDao.update(post)
|
||||
|
||||
suspend fun delete(post: Post) = postDao.delete(post)
|
||||
|
||||
fun getAll() = postDao.getAll()
|
||||
|
||||
fun getById(id: Int) = postDao.getById(id)
|
||||
|
||||
fun getByCategory(categoryId: Int) = Pager(
|
||||
PagingConfig(
|
||||
pageSize = 3,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = { postDao.getByCategory(categoryId.toString()) }
|
||||
).flow
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package com.example.dtf.repositories
|
||||
|
||||
import com.example.dtf.dao.UserDao
|
||||
import com.example.dtf.models.User
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class UserRepository @Inject constructor(
|
||||
private val userDao: UserDao
|
||||
) {
|
||||
suspend fun insert(user: User) = userDao.insert(user)
|
||||
|
||||
suspend fun update(user: User) = userDao.update(user)
|
||||
|
||||
suspend fun delete(user: User) = userDao.delete(user)
|
||||
|
||||
fun getAll() = userDao.getAll()
|
||||
|
||||
fun getById(id: Int) = userDao.getById(id)
|
||||
|
||||
fun getByUsernameAndPassword(username: String, password: String) = userDao.getByUsernameAndPassword(username, password)
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.example.dtf.repositories.offline
|
||||
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import com.example.dtf.dao.CategoryDao
|
||||
import com.example.dtf.models.Category
|
||||
import com.example.dtf.repositories.ICategoryRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class OfflineCategoryRepository @Inject constructor(
|
||||
private val categoryDao: CategoryDao
|
||||
) : ICategoryRepository {
|
||||
|
||||
override fun getAll() = Pager(
|
||||
PagingConfig(
|
||||
pageSize = 5,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = { categoryDao.getAll() }
|
||||
).flow
|
||||
|
||||
override fun getAllCached(): Flow<List<Category>> {
|
||||
return categoryDao.getAllCached()
|
||||
}
|
||||
|
||||
override fun getFirst(): Flow<Category?> {
|
||||
return categoryDao.getFirst()
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.example.dtf.repositories.offline
|
||||
|
||||
import androidx.paging.*
|
||||
import com.example.dtf.dao.CommentDao
|
||||
import com.example.dtf.models.Comment
|
||||
import com.example.dtf.repositories.ICommentRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class OfflineCommentRepository @Inject constructor(
|
||||
private val commentDao: CommentDao
|
||||
) : ICommentRepository {
|
||||
override suspend fun insert(comment: Comment) = commentDao.insert(comment)
|
||||
|
||||
override fun getById(id: Int) = commentDao.getById(id)
|
||||
|
||||
override fun getByPost(postId: Int) = Pager(
|
||||
PagingConfig(
|
||||
pageSize = 5,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = { commentDao.getByPost(postId) }
|
||||
).flow
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.example.dtf.repositories.offline
|
||||
|
||||
import com.example.dtf.dao.LikeDao
|
||||
import com.example.dtf.models.Like
|
||||
import com.example.dtf.repositories.ILikeRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class OfflineLikeRepository @Inject constructor(
|
||||
private val likeDao: LikeDao
|
||||
) : ILikeRepository {
|
||||
override suspend fun insert(like: Like) = likeDao.insert(like)
|
||||
|
||||
override suspend fun delete(like: Like) = likeDao.delete(like)
|
||||
|
||||
override fun countByPost(postId: Int) = likeDao.countByPost(postId)
|
||||
|
||||
override fun isLikedByUser(userId: Int, postId: Int) = likeDao.isLikedByUser(userId, postId)
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.example.dtf.repositories.offline
|
||||
|
||||
import androidx.paging.*
|
||||
import com.example.dtf.dao.PostDao
|
||||
import com.example.dtf.models.Post
|
||||
import com.example.dtf.repositories.IPostRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class OfflinePostRepository @Inject constructor(
|
||||
private val postDao: PostDao
|
||||
) : IPostRepository {
|
||||
override suspend fun insert(post: Post) = postDao.insert(post)
|
||||
|
||||
override suspend fun update(post: Post) = postDao.update(post)
|
||||
|
||||
override fun getById(id: Int) = postDao.getById(id)
|
||||
|
||||
override fun getByCategory(categoryId: Int) = Pager(
|
||||
PagingConfig(
|
||||
pageSize = 3,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = { postDao.getByCategory(categoryId.toString()) }
|
||||
).flow
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.example.dtf.repositories.offline
|
||||
|
||||
import com.example.dtf.dao.UserDao
|
||||
import com.example.dtf.models.User
|
||||
import com.example.dtf.repositories.IUserRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class OfflineUserRepository @Inject constructor(
|
||||
private val userDao: UserDao
|
||||
) : IUserRepository {
|
||||
override fun getById(id: Int) = userDao.getById(id)
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.example.dtf.repositories.online.mediator
|
||||
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import com.example.dtf.api.ServerService
|
||||
import com.example.dtf.db.AppDatabase
|
||||
import com.example.dtf.models.Category
|
||||
import com.example.dtf.repositories.ICategoryRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class RestCategoryRepository @Inject constructor(
|
||||
private val appDatabase: AppDatabase,
|
||||
private val serverService: ServerService
|
||||
) : ICategoryRepository {
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
override fun getAll(): Flow<PagingData<Category>> = Pager(
|
||||
PagingConfig(
|
||||
pageSize = 3,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
remoteMediator = CategoryMediator(appDatabase, serverService),
|
||||
pagingSourceFactory = { appDatabase.categoryDao().getAll() }
|
||||
).flow
|
||||
|
||||
override fun getAllCached(): Flow<List<Category>> {
|
||||
return appDatabase.categoryDao().getAllCached()
|
||||
}
|
||||
|
||||
override fun getFirst(): Flow<Category?> {
|
||||
return appDatabase.categoryDao().getFirst()
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.example.dtf.repositories.online
|
||||
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import com.example.dtf.api.ServerService
|
||||
import com.example.dtf.db.AppDatabase
|
||||
import com.example.dtf.dto.NewCommentDto
|
||||
import com.example.dtf.models.Comment
|
||||
import com.example.dtf.repositories.ICommentRepository
|
||||
import com.example.dtf.repositories.online.mediator.CommentMediator
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class RestCommentRepository @Inject constructor(
|
||||
private val appDatabase: AppDatabase,
|
||||
private val serverService: ServerService
|
||||
) : ICommentRepository {
|
||||
override suspend fun insert(comment: Comment) {
|
||||
serverService.createComment(
|
||||
comment = NewCommentDto(post_id = comment.post_id, content = comment.content)
|
||||
)
|
||||
appDatabase.commentDao().insert(comment)
|
||||
}
|
||||
|
||||
override fun getById(id: Int): Flow<Comment> {
|
||||
return flow { emit(serverService.getComment(id)) }
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
override fun getByPost(postId: Int): Flow<PagingData<Comment>> = Pager(
|
||||
PagingConfig(
|
||||
pageSize = 5,
|
||||
enablePlaceholders = false,
|
||||
),
|
||||
remoteMediator = CommentMediator(appDatabase, serverService, postId.toString()),
|
||||
pagingSourceFactory = { appDatabase.commentDao().getByPost(postId) }
|
||||
).flow
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.example.dtf.repositories.online
|
||||
|
||||
import com.example.dtf.api.ServerService
|
||||
import com.example.dtf.db.AppDatabase
|
||||
import com.example.dtf.models.Like
|
||||
import com.example.dtf.repositories.ILikeRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class RestLikeRepository @Inject constructor(
|
||||
private val appDatabase: AppDatabase,
|
||||
private val serverService: ServerService
|
||||
) : ILikeRepository {
|
||||
override suspend fun insert(like: Like) {
|
||||
serverService.likePost(like.postId)
|
||||
}
|
||||
|
||||
override suspend fun delete(like: Like) {
|
||||
serverService.likePost(like.postId)
|
||||
}
|
||||
|
||||
override fun countByPost(postId: Int): Flow<Int> {
|
||||
return flow { emit(serverService.getPostLikes(postId)) }
|
||||
}
|
||||
|
||||
override fun isLikedByUser(userId: Int, postId: Int): Flow<Boolean> {
|
||||
return flow { emit(serverService.postIsLiked(postId)) }
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.example.dtf.repositories.online
|
||||
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import com.example.dtf.api.ServerService
|
||||
import com.example.dtf.db.AppDatabase
|
||||
import com.example.dtf.dto.EditPostDto
|
||||
import com.example.dtf.dto.NewPostDto
|
||||
import com.example.dtf.models.Post
|
||||
import com.example.dtf.repositories.IPostRepository
|
||||
import com.example.dtf.repositories.online.mediator.PostMediator
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class RestPostRepository @Inject constructor(
|
||||
private val appDatabase: AppDatabase,
|
||||
private val serverService: ServerService
|
||||
) : IPostRepository {
|
||||
override suspend fun insert(post: Post) {
|
||||
serverService.createPost(
|
||||
post = NewPostDto(post.title, post.content, post.category_id)
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun update(post: Post) {
|
||||
serverService.updatePost(
|
||||
postId = post.id!!,
|
||||
post = EditPostDto(post.title, post.content)
|
||||
)
|
||||
appDatabase.postDao().update(post)
|
||||
}
|
||||
|
||||
override fun getById(id: Int): Flow<Post> {
|
||||
return flow { emit(serverService.getPost(id)) }
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
override fun getByCategory(categoryId: Int): Flow<PagingData<Post>> = Pager(
|
||||
PagingConfig(
|
||||
pageSize = 4,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
remoteMediator = PostMediator(appDatabase, serverService, categoryId.toString()),
|
||||
pagingSourceFactory = { appDatabase.postDao().getByCategory(categoryId.toString()) }
|
||||
).flow
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.example.dtf.repositories.online
|
||||
|
||||
import com.example.dtf.api.ServerService
|
||||
import com.example.dtf.db.AppDatabase
|
||||
import com.example.dtf.models.User
|
||||
import com.example.dtf.repositories.IUserRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class RestUserRepository @Inject constructor(
|
||||
private val appDatabase: AppDatabase,
|
||||
private val serverService: ServerService
|
||||
) : IUserRepository {
|
||||
override fun getById(id: Int): Flow<User> {
|
||||
return flow { emit(serverService.getUser(id)) }
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.example.dtf.repositories.online.mediator
|
||||
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.LoadType
|
||||
import androidx.paging.PagingState
|
||||
import androidx.paging.RemoteMediator
|
||||
import androidx.room.withTransaction
|
||||
import com.example.dtf.api.ServerService
|
||||
import com.example.dtf.db.AppDatabase
|
||||
import com.example.dtf.models.Category
|
||||
import java.io.IOException
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
class CategoryMediator (
|
||||
private val database: AppDatabase,
|
||||
private val serverService: ServerService
|
||||
) : RemoteMediator<Int, Category>(){
|
||||
|
||||
private val categoryDao = database.categoryDao()
|
||||
|
||||
override suspend fun load(
|
||||
loadType: LoadType,
|
||||
state: PagingState<Int, Category>
|
||||
): MediatorResult {
|
||||
return try {
|
||||
var loadKey = when (loadType) {
|
||||
LoadType.REFRESH -> null
|
||||
LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
|
||||
LoadType.APPEND -> {
|
||||
val lastItem = state.lastItemOrNull()
|
||||
?: return MediatorResult.Success(endOfPaginationReached = true)
|
||||
|
||||
lastItem.id
|
||||
}
|
||||
}
|
||||
|
||||
if (loadKey == null) {
|
||||
loadKey = 0
|
||||
}
|
||||
val response = serverService.getCategories(
|
||||
offset = loadKey,
|
||||
limit = state.config.pageSize
|
||||
)
|
||||
|
||||
|
||||
database.withTransaction {
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
for (category in response.categories) {
|
||||
categoryDao.delete(category)
|
||||
}
|
||||
}
|
||||
|
||||
for (category in response.categories) {
|
||||
categoryDao.insert(category)
|
||||
}
|
||||
}
|
||||
|
||||
MediatorResult.Success(endOfPaginationReached = response.nextKey == null)
|
||||
} catch (e: IOException) {
|
||||
MediatorResult.Error(e)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.example.dtf.repositories.online.mediator
|
||||
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.LoadType
|
||||
import androidx.paging.PagingState
|
||||
import androidx.paging.RemoteMediator
|
||||
import androidx.room.withTransaction
|
||||
import com.example.dtf.api.ServerService
|
||||
import com.example.dtf.db.AppDatabase
|
||||
import com.example.dtf.models.Comment
|
||||
import java.io.IOException
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
class CommentMediator (
|
||||
private val database: AppDatabase,
|
||||
private val serverService: ServerService,
|
||||
private val query: String
|
||||
) : RemoteMediator<Int, Comment>(){
|
||||
|
||||
private val commentDao = database.commentDao()
|
||||
|
||||
override suspend fun load(
|
||||
loadType: LoadType,
|
||||
state: PagingState<Int, Comment>
|
||||
): MediatorResult {
|
||||
return try {
|
||||
var loadKey = when (loadType) {
|
||||
LoadType.REFRESH -> null
|
||||
LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
|
||||
LoadType.APPEND -> {
|
||||
val lastItem = state.lastItemOrNull()
|
||||
?: return MediatorResult.Success(endOfPaginationReached = true)
|
||||
|
||||
lastItem.id
|
||||
}
|
||||
}
|
||||
|
||||
if (loadKey == null) {
|
||||
loadKey = 0
|
||||
}
|
||||
val response = serverService.getComments(
|
||||
postId = query.toInt(),
|
||||
offset = loadKey,
|
||||
limit = state.config.pageSize
|
||||
)
|
||||
|
||||
|
||||
database.withTransaction {
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
commentDao.deleteByQuery(query)
|
||||
}
|
||||
|
||||
for (comment in response.comments) {
|
||||
commentDao.insert(comment)
|
||||
}
|
||||
}
|
||||
|
||||
MediatorResult.Success(endOfPaginationReached = response.nextKey == null)
|
||||
} catch (e: IOException) {
|
||||
MediatorResult.Error(e)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.example.dtf.repositories.online.mediator
|
||||
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.LoadType
|
||||
import androidx.paging.PagingState
|
||||
import androidx.paging.RemoteMediator
|
||||
import androidx.room.withTransaction
|
||||
import com.example.dtf.api.ServerService
|
||||
import com.example.dtf.db.AppDatabase
|
||||
import com.example.dtf.models.Post
|
||||
import java.io.IOException
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
class PostMediator (
|
||||
private val database: AppDatabase,
|
||||
private val serverService: ServerService,
|
||||
private val query: String
|
||||
) : RemoteMediator<Int, Post>(){
|
||||
|
||||
private val postDao = database.postDao()
|
||||
|
||||
override suspend fun load(
|
||||
loadType: LoadType,
|
||||
state: PagingState<Int, Post>
|
||||
): MediatorResult {
|
||||
return try {
|
||||
var loadKey = when (loadType) {
|
||||
LoadType.REFRESH -> null
|
||||
LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
|
||||
LoadType.APPEND -> {
|
||||
val lastItem = state.lastItemOrNull()
|
||||
?: return MediatorResult.Success(endOfPaginationReached = true)
|
||||
|
||||
lastItem.id
|
||||
}
|
||||
}
|
||||
|
||||
if (loadKey == null) {
|
||||
loadKey = 0
|
||||
}
|
||||
val response = serverService.getPosts(
|
||||
category = query.toInt(),
|
||||
offset = loadKey,
|
||||
limit = state.config.pageSize
|
||||
)
|
||||
|
||||
|
||||
database.withTransaction {
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
postDao.deleteByQuery(query)
|
||||
}
|
||||
|
||||
for (comment in response.posts) {
|
||||
postDao.insert(comment)
|
||||
}
|
||||
}
|
||||
|
||||
MediatorResult.Success(endOfPaginationReached = response.nextKey == null)
|
||||
} catch (e: IOException) {
|
||||
MediatorResult.Error(e)
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.*
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.example.dtf.PreferencesManager
|
||||
import com.example.dtf.models.Category
|
||||
import com.example.dtf.utils.ScreenPaths
|
||||
@ -36,9 +37,7 @@ fun NewPostScreen(navController: NavHostController) {
|
||||
|
||||
val viewModel = hiltViewModel<NewPostViewModel>()
|
||||
val success = viewModel.addingPostState.observeAsState().value
|
||||
val categories = viewModel.categories.observeAsState().value
|
||||
|
||||
viewModel.retrieveCategories()
|
||||
val categories = viewModel.getCategories().collectAsState(initial = listOf())
|
||||
|
||||
if (success == true) {
|
||||
navController.navigate(ScreenPaths.Posts.route) {
|
||||
@ -91,7 +90,9 @@ fun NewPostScreen(navController: NavHostController) {
|
||||
colors = ButtonDefaults.buttonColors(Color(0xFFFFFFFF)),
|
||||
border = BorderStroke(1.dp, Color(0xFF0085FF)),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
modifier = Modifier.fillMaxWidth().padding(15.dp, 10.dp, 15.dp, 0.dp)
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(15.dp, 10.dp, 15.dp, 0.dp)
|
||||
) {
|
||||
Text(
|
||||
text = selectedCategory.value.name,
|
||||
@ -102,11 +103,13 @@ fun NewPostScreen(navController: NavHostController) {
|
||||
)
|
||||
)
|
||||
DropdownMenu(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 15.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 15.dp),
|
||||
expanded = expanded.value,
|
||||
onDismissRequest = {expanded.value = false}
|
||||
) {
|
||||
categories?.forEach { category ->
|
||||
categories.value.forEach { category ->
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
selectedCategory.value = category
|
||||
@ -126,17 +129,23 @@ fun NewPostScreen(navController: NavHostController) {
|
||||
value = title,
|
||||
"Заголовок",
|
||||
onChanged = {title.value = it},
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 15.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 15.dp),
|
||||
backgroundColor = Color(0xFFFEFEFE)
|
||||
)
|
||||
MyTextField(
|
||||
value = content,
|
||||
"Содержимое",
|
||||
onChanged = {content.value = it},
|
||||
modifier = Modifier.fillMaxWidth().heightIn(min = 500.dp).padding(horizontal = 15.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 400.dp)
|
||||
.padding(horizontal = 15.dp),
|
||||
backgroundColor = Color(0xFFFEFEFE),
|
||||
false
|
||||
)
|
||||
|
||||
Button(
|
||||
{
|
||||
if (selectedCategory.value.id != null) {
|
||||
|
@ -19,23 +19,14 @@ import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.*
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.compose.itemKey
|
||||
import com.example.dtf.PreferencesManager
|
||||
import com.example.dtf.db.AppDatabase
|
||||
import com.example.dtf.models.Comment
|
||||
import com.example.dtf.models.Post
|
||||
import com.example.dtf.models.PostWithComments
|
||||
import com.example.dtf.models.User
|
||||
import com.example.dtf.utils.ScreenPaths
|
||||
import com.example.dtf.viewmodels.PostViewModel
|
||||
import com.example.dtf.widgets.MyTextField
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.Date
|
||||
|
||||
@Composable
|
||||
fun PostScreen(postId: Int, navController: NavHostController) {
|
||||
@ -89,16 +80,7 @@ fun PostScreen(postId: Int, navController: NavHostController) {
|
||||
) {
|
||||
if (post != null) {
|
||||
Text(
|
||||
text = "day.month.year".replace(
|
||||
"day",
|
||||
post.date.day.toString()
|
||||
).replace(
|
||||
"month",
|
||||
post.date.month.toString()
|
||||
).replace(
|
||||
"year",
|
||||
post.date.year.toString()
|
||||
),
|
||||
text = post.date,
|
||||
fontSize = 14.sp,
|
||||
color = Color(0xFFCECCCC)
|
||||
)
|
||||
@ -115,16 +97,7 @@ fun PostScreen(postId: Int, navController: NavHostController) {
|
||||
)
|
||||
}
|
||||
Row (
|
||||
modifier = Modifier.clickable {
|
||||
if (isLiked.value) {
|
||||
viewModel.unlikePost(sharedPref, postId)
|
||||
likes.intValue--
|
||||
} else {
|
||||
viewModel.likePost(sharedPref, postId)
|
||||
likes.intValue++
|
||||
}
|
||||
isLiked.value = !isLiked.value
|
||||
},
|
||||
modifier = Modifier,
|
||||
horizontalArrangement = Arrangement.End
|
||||
) {
|
||||
Text(
|
||||
@ -133,7 +106,16 @@ fun PostScreen(postId: Int, navController: NavHostController) {
|
||||
color = Color.Green
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
modifier = Modifier.padding(start = 8.dp).clickable {
|
||||
if (isLiked.value) {
|
||||
viewModel.unlikePost(sharedPref, postId)
|
||||
likes.intValue--
|
||||
} else {
|
||||
viewModel.likePost(sharedPref, postId)
|
||||
likes.intValue++
|
||||
}
|
||||
isLiked.value = !isLiked.value
|
||||
},
|
||||
imageVector = Icons.Default.ThumbUp,
|
||||
contentDescription = null,
|
||||
tint = if (isLiked.value) { Color(40, 200, 40, 255) } else {Color.Black}
|
||||
@ -202,20 +184,11 @@ private fun Comment(comment: Comment) {
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = user?.username ?: "Loading...",
|
||||
text = comment.author.ifEmpty { user?.username ?: "Loading..." },
|
||||
fontSize = 20.sp
|
||||
)
|
||||
Text(
|
||||
text = "day.month.year".replace(
|
||||
"day",
|
||||
comment.date.day.toString()
|
||||
).replace(
|
||||
"month",
|
||||
comment.date.month.toString()
|
||||
).replace(
|
||||
"year",
|
||||
comment.date.year.toString()
|
||||
),
|
||||
text = comment.date,
|
||||
fontSize = 14.sp,
|
||||
color = Color(0xFFCECCCC)
|
||||
)
|
||||
|
@ -3,6 +3,7 @@ package com.example.dtf.screens
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ThumbUp
|
||||
@ -18,21 +19,14 @@ import androidx.compose.ui.unit.*
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.compose.itemKey
|
||||
import com.example.dtf.PreferencesManager
|
||||
import com.example.dtf.db.AppDatabase
|
||||
import com.example.dtf.models.Category
|
||||
import com.example.dtf.models.CategoryWithPosts
|
||||
import com.example.dtf.models.Post
|
||||
import com.example.dtf.utils.ScreenPaths
|
||||
import com.example.dtf.viewmodels.PostsViewModel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@Composable
|
||||
fun PostsScreen(navController: NavHostController) {
|
||||
@ -47,19 +41,8 @@ fun PostsScreen(navController: NavHostController) {
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight(0.1f)
|
||||
.horizontalScroll(
|
||||
rememberScrollState()
|
||||
)
|
||||
.background(Color.White),
|
||||
horizontalArrangement = Arrangement.spacedBy(25.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Categories(viewModel, currentCategory, posts)
|
||||
}
|
||||
|
||||
Categories(viewModel, currentCategory, posts)
|
||||
Row(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
@ -72,36 +55,50 @@ fun PostsScreen(navController: NavHostController) {
|
||||
|
||||
@Composable
|
||||
private fun Categories(viewModel: PostsViewModel, currentCategory: MutableState<Category?>, posts: MutableState<Flow<PagingData<Post>>?>) {
|
||||
val categories = viewModel.getCategories().collectAsState(listOf()).value
|
||||
val categories = viewModel.getCategoriesListUiState().collectAsLazyPagingItems()
|
||||
|
||||
if (categories.isNotEmpty() && currentCategory.value == null) {
|
||||
currentCategory.value = categories[0]
|
||||
posts.value = viewModel.getPostsListUiState(currentCategory.value!!.id!!)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.width(5.dp))
|
||||
categories.forEach {category ->
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
currentCategory.value = category
|
||||
posts.value = viewModel.getPostsListUiState(category.id!!)
|
||||
}
|
||||
.drawBehind {
|
||||
if (category.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)
|
||||
)
|
||||
LazyRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight(0.1f)
|
||||
.background(Color.White),
|
||||
horizontalArrangement = Arrangement.spacedBy(25.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.width(5.dp))
|
||||
}
|
||||
items(
|
||||
count = categories.itemCount,
|
||||
key = categories.itemKey()
|
||||
) {
|
||||
if (currentCategory.value == null) {
|
||||
currentCategory.value = categories[0]
|
||||
posts.value = viewModel.getPostsListUiState(currentCategory.value!!.id!!)
|
||||
}
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
currentCategory.value = categories[it]!!
|
||||
posts.value = viewModel.getPostsListUiState(categories[it]!!.id!!)
|
||||
}
|
||||
},
|
||||
text = category.name,
|
||||
fontSize = 22.sp
|
||||
)
|
||||
.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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,7 +126,7 @@ private fun PostsByCategory(viewModel: PostsViewModel, navController: NavHostCon
|
||||
private fun Post(viewModel: PostsViewModel, navController: NavHostController, post: Post) {
|
||||
val sharedPref = PreferencesManager(LocalContext.current)
|
||||
|
||||
val likes = remember { mutableIntStateOf(0) }
|
||||
val likes = remember { mutableIntStateOf(post.likes) }
|
||||
val isLiked = remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
@ -162,41 +159,28 @@ private fun Post(viewModel: PostsViewModel, navController: NavHostController, po
|
||||
fontSize = 26.sp
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.fillMaxHeight(0.6f).padding(10.dp, 0.dp, 10.dp, 0.dp),
|
||||
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),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(10.dp),
|
||||
verticalAlignment = Alignment.Bottom,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = "day.month.year".replace(
|
||||
"day",
|
||||
post.date.day.toString()
|
||||
).replace(
|
||||
"month",
|
||||
post.date.month.toString()
|
||||
).replace(
|
||||
"year",
|
||||
post.date.year.toString()
|
||||
),
|
||||
text = post.date,
|
||||
fontSize = 14.sp,
|
||||
color = Color(0xFFCECCCC)
|
||||
)
|
||||
Row (
|
||||
modifier = Modifier.fillMaxWidth().clickable {
|
||||
if (isLiked.value) {
|
||||
viewModel.unlikePost(sharedPref, post.id!!)
|
||||
likes.intValue--
|
||||
} else {
|
||||
viewModel.likePost(sharedPref, post.id!!)
|
||||
likes.intValue++
|
||||
}
|
||||
isLiked.value = !isLiked.value
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.End
|
||||
) {
|
||||
Text(
|
||||
@ -205,7 +189,18 @@ private fun Post(viewModel: PostsViewModel, navController: NavHostController, po
|
||||
color = Color.Green
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
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}
|
||||
|
@ -6,14 +6,14 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.dtf.PreferencesManager
|
||||
import com.example.dtf.models.Post
|
||||
import com.example.dtf.repositories.PostRepository
|
||||
import com.example.dtf.repositories.IPostRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class EditPostViewModel @Inject constructor(
|
||||
private val postRepository: PostRepository
|
||||
private val postRepository: IPostRepository
|
||||
) : ViewModel() {
|
||||
private val _editingPostState = MutableLiveData<Boolean?>(null)
|
||||
val editingPostState: LiveData<Boolean?>
|
||||
@ -41,7 +41,7 @@ class EditPostViewModel @Inject constructor(
|
||||
viewModelScope.launch {
|
||||
if (title.isNotEmpty() && content.isNotEmpty()) {
|
||||
postRepository.getById(postId).collect {
|
||||
postRepository.update(Post(postId, title, content, it.date, it.userId, it.categoryId))
|
||||
postRepository.update(Post(postId, title, content, it.date, it.user_id, it.category_id))
|
||||
_editingPostState.postValue(true)
|
||||
}
|
||||
} else {
|
||||
|
@ -5,55 +5,44 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.dtf.PreferencesManager
|
||||
import com.example.dtf.models.Category
|
||||
import com.example.dtf.models.User
|
||||
import com.example.dtf.repositories.CategoryRepository
|
||||
import com.example.dtf.repositories.UserRepository
|
||||
import com.example.dtf.api.ServerService
|
||||
import com.example.dtf.dto.Credentials
|
||||
import com.example.dtf.repositories.IUserRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class LoginViewModel @Inject constructor(
|
||||
private val userRepository: UserRepository,
|
||||
private val categoryRepository: CategoryRepository
|
||||
private val serverService: ServerService,
|
||||
) : ViewModel() {
|
||||
private val _successState = MutableLiveData<Boolean?>()
|
||||
val successState: LiveData<Boolean?>
|
||||
get() = _successState
|
||||
|
||||
init {
|
||||
addAdmin()
|
||||
}
|
||||
|
||||
fun calmSuccessState() {
|
||||
_successState.postValue(null)
|
||||
}
|
||||
|
||||
fun login(sharedPref: PreferencesManager, username: String, password: String) {
|
||||
viewModelScope.launch {
|
||||
userRepository.getByUsernameAndPassword(username, password).collect {
|
||||
if (it == null) {
|
||||
_successState.postValue(false)
|
||||
} else {
|
||||
sharedPref.saveData("userId", it.id.toString())
|
||||
sharedPref.saveData("isModerator", it.isModerator.toString())
|
||||
_successState.postValue(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val token = serverService.login(Credentials(username, password))
|
||||
|
||||
private fun addAdmin() {
|
||||
viewModelScope.launch {
|
||||
userRepository.getAll().collect {
|
||||
if (it.size == 0) {
|
||||
userRepository.insert(User(1, "admin", "admin", true))
|
||||
categoryRepository.insert(Category(1, "Аниме"))
|
||||
categoryRepository.insert(Category(2, "Игры"))
|
||||
categoryRepository.insert(Category(3, "Фильмы"))
|
||||
}
|
||||
if (token.token.isEmpty()) {
|
||||
_successState.postValue(false)
|
||||
return@launch
|
||||
}
|
||||
|
||||
ServerService.setToken(token.token)
|
||||
|
||||
val user = serverService.getCurrentUser()
|
||||
|
||||
sharedPref.saveData("token", token.token)
|
||||
sharedPref.saveData("username", user.username)
|
||||
sharedPref.saveData("isModerator", user.is_moderator.toString())
|
||||
sharedPref.saveData("userId", user.id.toString())
|
||||
|
||||
_successState.postValue(true)
|
||||
}
|
||||
}
|
||||
}
|
@ -5,36 +5,24 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.dtf.PreferencesManager
|
||||
import com.example.dtf.models.Category
|
||||
import com.example.dtf.models.Post
|
||||
import com.example.dtf.repositories.CategoryRepository
|
||||
import com.example.dtf.repositories.PostRepository
|
||||
import com.example.dtf.repositories.ICategoryRepository
|
||||
import com.example.dtf.repositories.IPostRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import java.time.LocalDate
|
||||
import java.util.Date
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class NewPostViewModel @Inject constructor(
|
||||
private val postRepository: PostRepository,
|
||||
private val categoryRepository: CategoryRepository
|
||||
private val postRepository: IPostRepository,
|
||||
private val categoryRepository: ICategoryRepository
|
||||
) : ViewModel() {
|
||||
private val _addingPostState = MutableLiveData<Boolean?>(null)
|
||||
val addingPostState: LiveData<Boolean?>
|
||||
get() = _addingPostState
|
||||
|
||||
private val _categories = MutableLiveData<List<Category>>(listOf())
|
||||
val categories: LiveData<List<Category>>
|
||||
get() = _categories
|
||||
|
||||
fun retrieveCategories() {
|
||||
viewModelScope.launch {
|
||||
categoryRepository.getAll().collect {
|
||||
_categories.postValue(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
fun getCategories() = categoryRepository.getAllCached()
|
||||
|
||||
fun calmAddingState() {
|
||||
_addingPostState.value = null
|
||||
@ -50,7 +38,7 @@ class NewPostViewModel @Inject constructor(
|
||||
null,
|
||||
title,
|
||||
content,
|
||||
Date(),
|
||||
"${Date().year + 1900}-${Date().month + 1}-${Date().date}",
|
||||
sharedPref.getData("userId", "0").toInt(),
|
||||
categoryId
|
||||
)
|
||||
|
@ -4,16 +4,15 @@ import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.paging.PagingData
|
||||
import com.example.dtf.PreferencesManager
|
||||
import com.example.dtf.models.Comment
|
||||
import com.example.dtf.models.Like
|
||||
import com.example.dtf.models.Post
|
||||
import com.example.dtf.repositories.CommentRepository
|
||||
import com.example.dtf.repositories.LikeRepository
|
||||
import com.example.dtf.repositories.PostRepository
|
||||
import com.example.dtf.repositories.UserRepository
|
||||
import com.example.dtf.repositories.ICommentRepository
|
||||
import com.example.dtf.repositories.ILikeRepository
|
||||
import com.example.dtf.repositories.IPostRepository
|
||||
import com.example.dtf.repositories.IUserRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
@ -22,10 +21,10 @@ import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class PostViewModel @Inject constructor(
|
||||
private val postRepository: PostRepository,
|
||||
private val commentRepository: CommentRepository,
|
||||
private val likeRepository: LikeRepository,
|
||||
private val userRepository: UserRepository
|
||||
private val postRepository: IPostRepository,
|
||||
private val commentRepository: ICommentRepository,
|
||||
private val likeRepository: ILikeRepository,
|
||||
private val userRepository: IUserRepository
|
||||
) : ViewModel() {
|
||||
private val _post = MutableLiveData<Post>()
|
||||
val post: LiveData<Post>
|
||||
@ -79,13 +78,14 @@ class PostViewModel @Inject constructor(
|
||||
userId,
|
||||
postId,
|
||||
content,
|
||||
Date()
|
||||
"${Date().year + 1900}-${Date().month + 1}-${Date().date}",
|
||||
sharedPref.getData("username", "Unknown")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getCommentsAuthor(comment: Comment) = userRepository.getById(comment.userId)
|
||||
fun getCommentsAuthor(comment: Comment) = userRepository.getById(comment.user_id)
|
||||
|
||||
fun getCommentsListUiState(postId: Int): Flow<PagingData<Comment>> = commentRepository.getByPost(postId)
|
||||
}
|
@ -4,18 +4,18 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.dtf.PreferencesManager
|
||||
import com.example.dtf.models.Like
|
||||
import com.example.dtf.repositories.CategoryRepository
|
||||
import com.example.dtf.repositories.LikeRepository
|
||||
import com.example.dtf.repositories.PostRepository
|
||||
import com.example.dtf.repositories.ICategoryRepository
|
||||
import com.example.dtf.repositories.ILikeRepository
|
||||
import com.example.dtf.repositories.IPostRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class PostsViewModel @Inject constructor(
|
||||
private val postRepository: PostRepository,
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val likeRepository: LikeRepository
|
||||
private val postRepository: IPostRepository,
|
||||
private val categoryRepository: ICategoryRepository,
|
||||
private val likeRepository: ILikeRepository
|
||||
) : ViewModel() {
|
||||
fun getLikes(postId: Int) = likeRepository.countByPost(postId)
|
||||
|
||||
@ -45,7 +45,9 @@ class PostsViewModel @Inject constructor(
|
||||
postId
|
||||
)
|
||||
|
||||
fun getCategories() = categoryRepository.getAll()
|
||||
fun getCategoriesListUiState() = categoryRepository.getAll()
|
||||
|
||||
fun getInitialCategory() = categoryRepository.getFirst()
|
||||
|
||||
fun getPostsListUiState(categoryId: Int) = postRepository.getByCategory(categoryId)
|
||||
}
|
@ -6,33 +6,26 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.dtf.PreferencesManager
|
||||
import com.example.dtf.models.User
|
||||
import com.example.dtf.repositories.UserRepository
|
||||
import com.example.dtf.repositories.offline.OfflineUserRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class ProfileViewModel @Inject constructor(
|
||||
private val userRepository: UserRepository
|
||||
private val userRepository: OfflineUserRepository
|
||||
) : ViewModel() {
|
||||
private val _user = MutableLiveData<User>()
|
||||
val user: LiveData<User>
|
||||
get() = _user
|
||||
|
||||
fun retrieveUser(sharedPref: PreferencesManager) {
|
||||
val userId = sharedPref.getData("userId", "-1").toInt()
|
||||
|
||||
if (userId == -1) return
|
||||
|
||||
viewModelScope.launch {
|
||||
userRepository.getById(userId).collect {
|
||||
_user.postValue(it)
|
||||
}
|
||||
}
|
||||
_user.postValue(User(null, sharedPref.getData("username", "Nickname")))
|
||||
}
|
||||
|
||||
fun logout(sharedPref: PreferencesManager) {
|
||||
sharedPref.deleteData("userId")
|
||||
sharedPref.deleteData("token")
|
||||
sharedPref.deleteData("username")
|
||||
sharedPref.deleteData("isModerator")
|
||||
}
|
||||
}
|
@ -4,16 +4,16 @@ 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.models.User
|
||||
import com.example.dtf.repositories.UserRepository
|
||||
import com.example.dtf.api.ServerService
|
||||
import com.example.dtf.dto.Credentials
|
||||
import com.example.dtf.repositories.offline.OfflineUserRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class RegisterViewModel @Inject constructor(
|
||||
private val userRepository: UserRepository
|
||||
private val serverService: ServerService
|
||||
) : ViewModel() {
|
||||
private val _successState = MutableLiveData<Boolean?>()
|
||||
val successState: LiveData<Boolean?>
|
||||
@ -38,15 +38,11 @@ class RegisterViewModel @Inject constructor(
|
||||
_successState.postValue(false)
|
||||
return
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
userRepository.getByUsernameAndPassword(username, password).collect {
|
||||
if (it != null) {
|
||||
_successState.postValue(false)
|
||||
} else {
|
||||
userRepository.insert(User(null, username, password, false))
|
||||
_successState.postValue(true)
|
||||
}
|
||||
if (serverService.register(Credentials(username, password)) == "NOT OK") {
|
||||
_successState.postValue(false)
|
||||
} else {
|
||||
_successState.postValue(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,4 +14,6 @@ plugins {
|
||||
id 'com.android.application' version '7.4.2' apply false
|
||||
id 'com.android.library' version '7.4.2' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version '1.7.0' apply false
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.7.0' apply false
|
||||
}
|
@ -4,5 +4,5 @@
|
||||
# Location of the SDK. This is only used by Gradle.
|
||||
# For customization when using a Version Control System, please read the
|
||||
# header note.
|
||||
#Tue Nov 07 09:36:13 SAMT 2023
|
||||
sdk.dir=C\:\\Users\\Aqua\\AppData\\Local\\Android\\Sdk
|
||||
#Fri Dec 22 01:26:17 GMT+04:00 2023
|
||||
sdk.dir=D\:\\Programs\\Android
|
||||
|
Loading…
Reference in New Issue
Block a user