diff --git a/app/schemas/com.paulcoding.hviewer.database.AppDatabase/4.json b/app/schemas/com.paulcoding.hviewer.database.AppDatabase/4.json index 2d73f01..0aeda7e 100644 --- a/app/schemas/com.paulcoding.hviewer.database.AppDatabase/4.json +++ b/app/schemas/com.paulcoding.hviewer.database.AppDatabase/4.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 4, - "identityHash": "9cae14220c3b54c73ec622e03a0d6f08", + "identityHash": "d30eb7c5c1c1735782bd48febc6f9594", "entities": [ { "tableName": "favorite_posts", @@ -71,12 +71,80 @@ }, "indices": [], "foreignKeys": [] + }, + { + "tableName": "history", + "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, `tags` TEXT, `size` INTEGER, `views` INTEGER, `quantity` INTEGER, 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 + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "size", + "columnName": "size", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "views", + "columnName": "views", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "quantity", + "columnName": "quantity", + "affinity": "INTEGER", + "notNull": false + } + ], + "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, '9cae14220c3b54c73ec622e03a0d6f08')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd30eb7c5c1c1735782bd48febc6f9594')" ] } } \ No newline at end of file diff --git a/app/schemas/com.paulcoding.hviewer.database.AppDatabase/5.json b/app/schemas/com.paulcoding.hviewer.database.AppDatabase/5.json new file mode 100644 index 0000000..9d561f8 --- /dev/null +++ b/app/schemas/com.paulcoding.hviewer.database.AppDatabase/5.json @@ -0,0 +1,150 @@ +{ + "formatVersion": 1, + "database": { + "version": 5, + "identityHash": "d30eb7c5c1c1735782bd48febc6f9594", + "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, `tags` TEXT, `size` INTEGER, `views` INTEGER, `quantity` INTEGER, 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 + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "size", + "columnName": "size", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "views", + "columnName": "views", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "quantity", + "columnName": "quantity", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "url" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "history", + "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, `tags` TEXT, `size` INTEGER, `views` INTEGER, `quantity` INTEGER, 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 + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "size", + "columnName": "size", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "views", + "columnName": "views", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "quantity", + "columnName": "quantity", + "affinity": "INTEGER", + "notNull": false + } + ], + "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, 'd30eb7c5c1c1735782bd48febc6f9594')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/com/paulcoding/hviewer/database/AppDatabase.kt b/app/src/main/java/com/paulcoding/hviewer/database/AppDatabase.kt index 55de46e..aa9eeb0 100644 --- a/app/src/main/java/com/paulcoding/hviewer/database/AppDatabase.kt +++ b/app/src/main/java/com/paulcoding/hviewer/database/AppDatabase.kt @@ -3,10 +3,12 @@ package com.paulcoding.hviewer.database import androidx.room.Database import androidx.room.RoomDatabase import androidx.room.TypeConverters +import com.paulcoding.hviewer.model.PostHistory import com.paulcoding.hviewer.model.PostItem -@Database(entities = [PostItem::class], version = 4, exportSchema = true) +@Database(entities = [PostItem::class, PostHistory::class], version = 5, exportSchema = true) @TypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { abstract fun favoritePostDao(): FavoritePostDao + abstract fun historyDao(): HistoryDao } \ No newline at end of file diff --git a/app/src/main/java/com/paulcoding/hviewer/database/DatabaseProvider.kt b/app/src/main/java/com/paulcoding/hviewer/database/DatabaseProvider.kt index 234dff2..e0ea7c0 100644 --- a/app/src/main/java/com/paulcoding/hviewer/database/DatabaseProvider.kt +++ b/app/src/main/java/com/paulcoding/hviewer/database/DatabaseProvider.kt @@ -12,7 +12,7 @@ object DatabaseProvider { appContext, AppDatabase::class.java, "hviewer_db" ) - .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4) + .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5) .build() } return db!! diff --git a/app/src/main/java/com/paulcoding/hviewer/database/HistoryDao.kt b/app/src/main/java/com/paulcoding/hviewer/database/HistoryDao.kt new file mode 100644 index 0000000..02aa2c6 --- /dev/null +++ b/app/src/main/java/com/paulcoding/hviewer/database/HistoryDao.kt @@ -0,0 +1,24 @@ +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.PostHistory +import kotlinx.coroutines.flow.Flow + +@Dao +interface HistoryDao { + @Query("SELECT * FROM history ORDER BY createdAt DESC") + fun getAll(): Flow> + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insert(history: PostHistory) + + @Delete + suspend fun delete(history: PostHistory) + + @Query("DELETE FROM history WHERE url = (SELECT url FROM history ORDER BY createdAt ASC LIMIT 1)") + suspend fun deleteOldest() +} \ No newline at end of file diff --git a/app/src/main/java/com/paulcoding/hviewer/database/Migrations.kt b/app/src/main/java/com/paulcoding/hviewer/database/Migrations.kt index cc2565a..e985b37 100644 --- a/app/src/main/java/com/paulcoding/hviewer/database/Migrations.kt +++ b/app/src/main/java/com/paulcoding/hviewer/database/Migrations.kt @@ -22,4 +22,12 @@ val MIGRATION_3_4 = object : Migration(3, 4) { db.execSQL("ALTER TABLE favorite_posts ADD COLUMN views INTEGER") db.execSQL("ALTER TABLE favorite_posts ADD COLUMN quantity INTEGER") } +} + +val MIGRATION_4_5 = object : Migration(4, 5) { + override fun migrate(db: SupportSQLiteDatabase) { + db.execSQL( + "CREATE TABLE IF NOT EXISTS `history` (`url` TEXT NOT NULL, `name` TEXT NOT NULL, `thumbnail` TEXT NOT NULL, `site` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `tags` TEXT, `size` INTEGER, `views` INTEGER, `quantity` INTEGER, PRIMARY KEY(`url`))" + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/paulcoding/hviewer/model/PostModel.kt b/app/src/main/java/com/paulcoding/hviewer/model/PostModel.kt index f91ea9b..d8bca57 100644 --- a/app/src/main/java/com/paulcoding/hviewer/model/PostModel.kt +++ b/app/src/main/java/com/paulcoding/hviewer/model/PostModel.kt @@ -24,6 +24,34 @@ data class PostItem( val quantity: Int? = null, ) +// duplicated? +@Entity(tableName = "history") +data class PostHistory( + @PrimaryKey + val url: String = "", + val name: String = "", + val thumbnail: String = "", + val site: String = "", + val createdAt: Long = 0, + val tags: List? = null, + val size: Int? = null, + val views: Int? = null, + val quantity: Int? = null, +) { + fun toPostItem():PostItem { + return PostItem( + url = url, + name = name, + thumbnail = thumbnail, + site = site, + createdAt = createdAt, + tags = tags, + size = size, + views = views + ) + } +} + data class Tag( val name: String = "", val url: String = "", diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/favorite/FavoritePage.kt b/app/src/main/java/com/paulcoding/hviewer/ui/favorite/FavoritePage.kt index 3ea7e22..bbda5db 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/favorite/FavoritePage.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/favorite/FavoritePage.kt @@ -24,7 +24,7 @@ import com.paulcoding.hviewer.model.Tag import com.paulcoding.hviewer.ui.component.HBackIcon import com.paulcoding.hviewer.ui.component.HEmpty import com.paulcoding.hviewer.ui.page.AppViewModel -import com.paulcoding.hviewer.ui.page.posts.PostCard +import com.paulcoding.hviewer.ui.page.posts.FavoriteCard import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @@ -90,7 +90,7 @@ fun FavoriteItem( onTagClick: (Tag) -> Unit, deleteFavorite: () -> Unit ) { - PostCard( + FavoriteCard( post, isFavorite = true, setFavorite = { deleteFavorite() diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/AppEntry.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/AppEntry.kt index 1f09147..7dfb75c 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/page/AppEntry.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/AppEntry.kt @@ -26,6 +26,7 @@ import com.paulcoding.hviewer.preference.Preferences import com.paulcoding.hviewer.ui.favorite.FavoritePage import com.paulcoding.hviewer.ui.page.editor.EditorPage import com.paulcoding.hviewer.ui.page.editor.ListScriptPage +import com.paulcoding.hviewer.ui.page.history.HistoryPage import com.paulcoding.hviewer.ui.page.lock.LockPage import com.paulcoding.hviewer.ui.page.post.PostPage import com.paulcoding.hviewer.ui.page.posts.CustomTagPage @@ -45,6 +46,7 @@ fun AppEntry() { fun navToImages(post: PostItem) { appViewModel.setCurrentPost(post) + appViewModel.addHistory(post) navController.navigate(Route.POST) } @@ -77,6 +79,9 @@ fun AppEntry() { navToListCrashLog = { navController.navigate(Route.LIST_SCRIPT + "/crash_log") }, + navToHistory = { + navController.navigate(Route.HISTORY) + }, goBack = { navController.popBackStack() }) } animatedComposable(Route.SETTINGS) { @@ -170,6 +175,20 @@ fun AppEntry() { } }) } + animatedComposable(Route.HISTORY) { + HistoryPage( + goBack = { navController.popBackStack() }, appViewModel = appViewModel, + navToImages = { post: PostItem -> + appViewModel.setSiteConfig(post.site, siteConfigs.sites[post.site]!!) + navToImages(post) + }, + navToCustomTag = { post, tag -> + appViewModel.setSiteConfig(post.site, siteConfigs.sites[post.site]!!) + navToCustomTag(tag) + }, + deleteHistory = appViewModel::deleteHistory + ) + } } } diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/AppViewModel.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/AppViewModel.kt index e98c1c6..a7e248e 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/page/AppViewModel.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/AppViewModel.kt @@ -7,11 +7,13 @@ import com.paulcoding.hviewer.MainApp.Companion.appContext import com.paulcoding.hviewer.database.DatabaseProvider import com.paulcoding.hviewer.helper.crashLogDir import com.paulcoding.hviewer.helper.scriptsDir +import com.paulcoding.hviewer.model.PostHistory import com.paulcoding.hviewer.model.PostItem import com.paulcoding.hviewer.model.SiteConfig import com.paulcoding.hviewer.model.Tag import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import java.io.File @@ -27,6 +29,7 @@ class AppViewModel : ViewModel() { val stateFlow = _stateFlow.asStateFlow() val favoritePosts = DatabaseProvider.getInstance().favoritePostDao().getAll() + val historyPosts = DatabaseProvider.getInstance().historyDao().getAll() fun setCurrentPost(post: PostItem) { _stateFlow.update { it.copy(post = post) } @@ -69,4 +72,32 @@ class AppViewModel : ViewModel() { DatabaseProvider.getInstance().favoritePostDao().delete(postItem) } } + + fun addHistory(postItem: PostItem) { + val item = PostHistory( + site = _stateFlow.value.site.first, + createdAt = System.currentTimeMillis(), + url = postItem.url, + views = postItem.views, + thumbnail = postItem.thumbnail, + name = postItem.name, + size = postItem.size, + tags = postItem.tags, + quantity = postItem.quantity + ) + viewModelScope.launch { + // limit to 25 items in history + if (historyPosts.first().size >= 25) { + DatabaseProvider.getInstance().historyDao().deleteOldest() + } + DatabaseProvider.getInstance().historyDao() + .insert(item) + } + } + + fun deleteHistory(history: PostHistory) { + viewModelScope.launch { + DatabaseProvider.getInstance().historyDao().delete(history) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/Route.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/Route.kt index 8a630ef..b6ec0df 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/page/Route.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/Route.kt @@ -13,4 +13,5 @@ object Route { const val EDITOR = "editor" const val LIST_SCRIPT = "list_script" const val LOCK = "lock" + const val HISTORY = "history" } \ No newline at end of file diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/history/HistoryPage.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/history/HistoryPage.kt new file mode 100644 index 0000000..81c6898 --- /dev/null +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/history/HistoryPage.kt @@ -0,0 +1,81 @@ +package com.paulcoding.hviewer.ui.page.history + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid +import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells +import androidx.compose.foundation.lazy.staggeredgrid.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Delete +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.paulcoding.hviewer.model.PostHistory +import com.paulcoding.hviewer.model.PostItem +import com.paulcoding.hviewer.model.Tag +import com.paulcoding.hviewer.ui.component.HBackIcon +import com.paulcoding.hviewer.ui.component.HEmpty +import com.paulcoding.hviewer.ui.component.HIcon +import com.paulcoding.hviewer.ui.page.AppViewModel +import com.paulcoding.hviewer.ui.page.posts.PostCard + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun HistoryPage( + goBack: () -> Unit, appViewModel: AppViewModel, + navToImages: (PostItem) -> Unit, + navToCustomTag: (PostItem, Tag) -> Unit, + deleteHistory: (post: PostHistory) -> Unit +) { + val historyPosts by appViewModel.historyPosts.collectAsState(initial = listOf()) + + Scaffold( + modifier = Modifier.fillMaxSize(), + topBar = { + TopAppBar( + title = { Text("History") }, + navigationIcon = { + HBackIcon { goBack() } + }, + ) + } + ) { paddings -> + Column(modifier = Modifier.padding(paddings)) { + LazyVerticalStaggeredGrid( + columns = StaggeredGridCells.Fixed(2), + ) { + items(historyPosts) { + PostCard( + postItem = it.toPostItem(), + onTagClick = { tag -> + navToCustomTag(it.toPostItem(), tag) + }, + onClick = { + navToImages(it.toPostItem()) + }) { + HIcon( + Icons.Outlined.Delete, + "Delete", + modifier = Modifier.align(Alignment.TopEnd) + ) { + deleteHistory(it) + } + } + } + } + if (historyPosts.isEmpty()) + HEmpty( + title = "Wow", + message = "Such empty" + ) + } + } +} + diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/posts/PostCard.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/posts/PostCard.kt index 084c517..b583b71 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/page/posts/PostCard.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/posts/PostCard.kt @@ -4,6 +4,7 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.tween import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -36,15 +37,35 @@ import com.paulcoding.hviewer.ui.component.HFavoriteIcon import com.paulcoding.hviewer.ui.component.HIcon import com.paulcoding.hviewer.ui.component.HImage +@Composable +fun FavoriteCard( + postItem: PostItem, + isFavorite: Boolean = false, + setFavorite: (Boolean) -> Unit = {}, + onTagClick: (Tag) -> Unit = {}, + onClick: () -> Unit, +) { + PostCard( + postItem = postItem, + onTagClick = onTagClick, + onClick = onClick + ) { + HFavoriteIcon( + modifier = Modifier.align(Alignment.TopEnd), + isFavorite = isFavorite + ) { + setFavorite(!isFavorite) + } + } +} @OptIn(ExperimentalMaterial3Api::class) @Composable fun PostCard( postItem: PostItem, - isFavorite: Boolean = false, - setFavorite: (Boolean) -> Unit = {}, onTagClick: (Tag) -> Unit = {}, - viewPost: () -> Unit, + onClick: () -> Unit, + content: @Composable BoxScope.() -> Unit = {}, ) { var isBottomSheetVisible by remember { mutableStateOf(false) } val bottomSheetState = rememberModalBottomSheetState() @@ -63,7 +84,7 @@ fun PostCard( .padding(horizontal = 16.dp, vertical = 12.dp), border = CardDefaults.outlinedCardBorder(), shape = CardDefaults.outlinedShape, - onClick = { viewPost() }, + onClick = { onClick() }, ) { Box( modifier = Modifier @@ -78,15 +99,10 @@ fun PostCard( ) Text(postItem.name, fontSize = 12.sp) } - HFavoriteIcon( - modifier = Modifier.align(Alignment.TopEnd), - isFavorite = isFavorite - ) { - setFavorite(!isFavorite) - } HIcon(Icons.Outlined.Info) { isBottomSheetVisible = true } + content() } } diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/posts/PostsPage.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/posts/PostsPage.kt index 808bb59..5572d28 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/page/posts/PostsPage.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/posts/PostsPage.kt @@ -34,7 +34,6 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.paulcoding.hviewer.MainApp.Companion.appContext import com.paulcoding.hviewer.extensions.isScrolledToEnd import com.paulcoding.hviewer.extensions.toCapital -import com.paulcoding.hviewer.helper.log import com.paulcoding.hviewer.model.PostItem import com.paulcoding.hviewer.model.SiteConfig import com.paulcoding.hviewer.model.Tag @@ -161,7 +160,7 @@ fun PageContent( state = listState ) { items(uiState.postItems, key = { it.url }) { post -> - PostCard( + FavoriteCard( post, isFavorite = listFavorite.find { it.url == post.url } != null, onTagClick = { diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/search/SearchPage.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/search/SearchPage.kt index 5062c65..0bbc66a 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/page/search/SearchPage.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/search/SearchPage.kt @@ -46,7 +46,7 @@ import com.paulcoding.hviewer.ui.component.HIcon import com.paulcoding.hviewer.ui.component.HLoading import com.paulcoding.hviewer.ui.component.HPageProgress import com.paulcoding.hviewer.ui.page.AppViewModel -import com.paulcoding.hviewer.ui.page.posts.PostCard +import com.paulcoding.hviewer.ui.page.posts.FavoriteCard @OptIn(ExperimentalMaterial3Api::class) @@ -151,7 +151,7 @@ fun PageContent( state = listState ) { items(uiState.postItems, key = { it.url }) { post -> - PostCard(post, + FavoriteCard(post, isFavorite = listFavorite.find { it.url == post.url } != null, setFavorite = { isFavorite -> if (isFavorite) diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/sites/SitesPage.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/sites/SitesPage.kt index 12632a7..65a4f08 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/page/sites/SitesPage.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/sites/SitesPage.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.BugReport import androidx.compose.material.icons.outlined.Edit +import androidx.compose.material.icons.outlined.History import androidx.compose.material.icons.outlined.Settings import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Scaffold @@ -45,6 +46,7 @@ fun SitesPage( goBack: () -> Unit, siteConfigs: SiteConfigs, navToSettings: () -> Unit, + navToHistory: () -> Unit, navToListCrashLog: () -> Unit, navToListScript: () -> Unit, refresh: () -> Unit, @@ -68,6 +70,9 @@ fun SitesPage( navToListScript() } } + HIcon(Icons.Outlined.History) { + navToHistory() + } HFavoriteIcon(isFavorite = false) { navToFavorite() }