Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement favorite feature #7

Merged
merged 6 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
id("com.google.devtools.ksp")
}

android {
Expand Down Expand Up @@ -81,11 +82,19 @@ dependencies {
implementation(libs.ktor.client.content.negotiation)
implementation(libs.ktor.client.logging)

implementation(libs.androidx.room.runtime)
ksp(libs.androidx.room.compiler)
implementation(libs.androidx.room.ktx)

testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
}

ksp {
arg("room.schemaLocation", "$projectDir/schemas")
}
52 changes: 52 additions & 0 deletions app/schemas/com.paulcoding.hviewer.database.AppDatabase/1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "f8c3310b39b34e0c6c9c004f8557d416",
"entities": [
{
"tableName": "favorite_posts",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `name` TEXT NOT NULL, `thumbnail` TEXT NOT NULL, `site` TEXT NOT NULL, PRIMARY KEY(`url`))",
"fields": [
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "thumbnail",
"columnName": "thumbnail",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "site",
"columnName": "site",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"url"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f8c3310b39b34e0c6c9c004f8557d416')"
]
}
}
52 changes: 52 additions & 0 deletions app/schemas/com.paulcoding.hviewer.database.AppDatabase/2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "f8c3310b39b34e0c6c9c004f8557d416",
"entities": [
{
"tableName": "favorite_posts",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `name` TEXT NOT NULL, `thumbnail` TEXT NOT NULL, `site` TEXT NOT NULL, PRIMARY KEY(`url`))",
"fields": [
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "thumbnail",
"columnName": "thumbnail",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "site",
"columnName": "site",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"url"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f8c3310b39b34e0c6c9c004f8557d416')"
]
}
}
58 changes: 58 additions & 0 deletions app/schemas/com.paulcoding.hviewer.database.AppDatabase/3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"formatVersion": 1,
"database": {
"version": 3,
"identityHash": "40109ede6ba29fdee1d23735114a2981",
"entities": [
{
"tableName": "favorite_posts",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `name` TEXT NOT NULL, `thumbnail` TEXT NOT NULL, `site` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, PRIMARY KEY(`url`))",
"fields": [
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "thumbnail",
"columnName": "thumbnail",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "site",
"columnName": "site",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "createdAt",
"columnName": "createdAt",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"url"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '40109ede6ba29fdee1d23735114a2981')"
]
}
}
10 changes: 10 additions & 0 deletions app/src/main/java/com/paulcoding/hviewer/database/AppDatabase.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.paulcoding.hviewer.database

import androidx.room.Database
import androidx.room.RoomDatabase
import com.paulcoding.hviewer.model.PostItem

@Database(entities = [PostItem::class], version = 3, exportSchema = true)
abstract class AppDatabase : RoomDatabase() {
abstract fun favoritePostDao(): FavoritePostDao
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.paulcoding.hviewer.database

import androidx.room.Room
import com.paulcoding.hviewer.MainApp.Companion.appContext

object DatabaseProvider {
private var db: AppDatabase? = null

fun getInstance(): AppDatabase {
if (db == null) {
db = Room.databaseBuilder(
appContext,
AppDatabase::class.java, "hviewer_db"
)
.addMigrations(MIGRATION_1_2, MIGRATION_2_3)
.build()
}
return db!!
}
}
21 changes: 21 additions & 0 deletions app/src/main/java/com/paulcoding/hviewer/database/FavoriteDao.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.paulcoding.hviewer.database

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.paulcoding.hviewer.model.PostItem
import kotlinx.coroutines.flow.Flow

@Dao
interface FavoritePostDao {
@Query("SELECT * FROM favorite_posts ORDER BY createdAt DESC")
fun getAll(): Flow<List<PostItem>>

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(post: PostItem)

@Delete
suspend fun delete(post: PostItem)
}
16 changes: 16 additions & 0 deletions app/src/main/java/com/paulcoding/hviewer/database/Migrations.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.paulcoding.hviewer.database

import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase

val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE favorite_posts ADD COLUMN site TEXT NOT NULL DEFAULT \"\"")
}
}

val MIGRATION_2_3 = object : Migration(2, 3) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE favorite_posts ADD COLUMN createdAt INTEGER NOT NULL DEFAULT 0")
}
}
9 changes: 8 additions & 1 deletion app/src/main/java/com/paulcoding/hviewer/model/PostModel.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
package com.paulcoding.hviewer.model

import androidx.room.Entity
import androidx.room.PrimaryKey

data class PostData(
val images: List<String>,
val total: Int,
val next: String? = null
)


@Entity(tableName = "favorite_posts")
data class PostItem(
val name: String = "",
@PrimaryKey
val url: String = "",
val name: String = "",
val thumbnail: String = "",
val site: String = "",
val createdAt: Long = 0,
)

data class Posts(
Expand Down
14 changes: 13 additions & 1 deletion app/src/main/java/com/paulcoding/hviewer/ui/component/HIcon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ package com.paulcoding.hviewer.ui.component

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalContentColor
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import com.paulcoding.hviewer.ui.icon.SettingsIcon

Expand All @@ -16,14 +20,22 @@ fun HBackIcon(onClick: () -> Unit) {
}
}

@Composable
fun HFavoriteIcon(modifier: Modifier = Modifier, isFavorite: Boolean, onClick: () -> Unit) {
val icon = if (isFavorite) Icons.Filled.Favorite else Icons.Filled.FavoriteBorder
val tint: Color = if (isFavorite) Color.Red else Color.Gray
HIcon(modifier = modifier, imageVector = icon, tint = tint, onClick = onClick)
}

@Composable
fun HIcon(
modifier: Modifier = Modifier,
imageVector: ImageVector = SettingsIcon,
description: String = "",
tint: Color = LocalContentColor.current,
onClick: () -> Unit
) {
IconButton(onClick = { onClick() }, modifier = modifier) {
Icon(imageVector, description)
Icon(imageVector, description, tint = tint)
}
}
Loading
Loading