diff --git a/app/schemas/com.jerboa.db.AppDB/24.json b/app/schemas/com.jerboa.db.AppDB/24.json new file mode 100644 index 000000000..a412ae3e6 --- /dev/null +++ b/app/schemas/com.jerboa.db.AppDB/24.json @@ -0,0 +1,239 @@ +{ + "formatVersion": 1, + "database": { + "version": 24, + "identityHash": "f14512333b67d7575d8f9a47507b8e9b", + "entities": [ + { + "tableName": "Account", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `current` INTEGER NOT NULL, `instance` TEXT NOT NULL, `name` TEXT NOT NULL, `jwt` TEXT NOT NULL, `default_listing_type` INTEGER NOT NULL DEFAULT 0, `default_sort_type` INTEGER NOT NULL DEFAULT 0, `verification_state` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "current", + "columnName": "current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "instance", + "columnName": "instance", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "jwt", + "columnName": "jwt", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "defaultListingType", + "columnName": "default_listing_type", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "defaultSortType", + "columnName": "default_sort_type", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "verificationState", + "columnName": "verification_state", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "AppSettings", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `font_size` INTEGER NOT NULL DEFAULT 16, `theme` INTEGER NOT NULL DEFAULT 0, `theme_color` INTEGER NOT NULL DEFAULT 0, `viewed_changelog` INTEGER NOT NULL DEFAULT 0, `post_view_mode` INTEGER NOT NULL DEFAULT 0, `show_bottom_nav` INTEGER NOT NULL DEFAULT 1, `show_collapsed_comment_content` INTEGER NOT NULL DEFAULT 0, `show_comment_action_bar_by_default` INTEGER NOT NULL DEFAULT 1, `show_voting_arrows_in_list_view` INTEGER NOT NULL DEFAULT 1, `show_parent_comment_navigation_buttons` INTEGER NOT NULL DEFAULT 0, `navigate_parent_comments_with_volume_buttons` INTEGER NOT NULL DEFAULT 0, `use_custom_tabs` INTEGER NOT NULL DEFAULT 1, `use_private_tabs` INTEGER NOT NULL DEFAULT 0, `secure_window` INTEGER NOT NULL DEFAULT 0, `blur_nsfw` INTEGER NOT NULL DEFAULT 1, `show_text_descriptions_in_navbar` INTEGER NOT NULL DEFAULT 1, `markAsReadOnScroll` INTEGER NOT NULL DEFAULT 0, `backConfirmationMode` INTEGER NOT NULL DEFAULT 1, `show_post_link_previews` INTEGER NOT NULL DEFAULT 1, `post_actionbar_mode` INTEGER NOT NULL DEFAULT 0)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "fontSize", + "columnName": "font_size", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "16" + }, + { + "fieldPath": "theme", + "columnName": "theme", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "themeColor", + "columnName": "theme_color", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "viewedChangelog", + "columnName": "viewed_changelog", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "postViewMode", + "columnName": "post_view_mode", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "showBottomNav", + "columnName": "show_bottom_nav", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "showCollapsedCommentContent", + "columnName": "show_collapsed_comment_content", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "showCommentActionBarByDefault", + "columnName": "show_comment_action_bar_by_default", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "showVotingArrowsInListView", + "columnName": "show_voting_arrows_in_list_view", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "showParentCommentNavigationButtons", + "columnName": "show_parent_comment_navigation_buttons", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "navigateParentCommentsWithVolumeButtons", + "columnName": "navigate_parent_comments_with_volume_buttons", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "useCustomTabs", + "columnName": "use_custom_tabs", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "usePrivateTabs", + "columnName": "use_private_tabs", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "secureWindow", + "columnName": "secure_window", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "blurNSFW", + "columnName": "blur_nsfw", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "showTextDescriptionsInNavbar", + "columnName": "show_text_descriptions_in_navbar", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "markAsReadOnScroll", + "columnName": "markAsReadOnScroll", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "backConfirmationMode", + "columnName": "backConfirmationMode", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "showPostLinkPreviews", + "columnName": "show_post_link_previews", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "postActionbarMode", + "columnName": "post_actionbar_mode", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "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, 'f14512333b67d7575d8f9a47507b8e9b')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jerboa/MainActivity.kt b/app/src/main/java/com/jerboa/MainActivity.kt index b156c5ce3..211a46aed 100644 --- a/app/src/main/java/com/jerboa/MainActivity.kt +++ b/app/src/main/java/com/jerboa/MainActivity.kt @@ -35,6 +35,11 @@ import com.jerboa.api.ApiState import com.jerboa.api.MINIMUM_API_VERSION import com.jerboa.datatypes.types.Community import com.jerboa.db.APP_SETTINGS_DEFAULT +import com.jerboa.feat.BackConfirmation.addConfirmationDialog +import com.jerboa.feat.BackConfirmation.addConfirmationToast +import com.jerboa.feat.BackConfirmation.disposeConfirmation +import com.jerboa.feat.BackConfirmationMode +import com.jerboa.feat.ShowConfirmationDialog import com.jerboa.model.AccountSettingsViewModel import com.jerboa.model.AccountSettingsViewModelFactory import com.jerboa.model.AccountViewModel @@ -75,11 +80,6 @@ import com.jerboa.ui.components.settings.account.AccountSettingsActivity import com.jerboa.ui.components.settings.crashlogs.CrashLogsActivity import com.jerboa.ui.components.settings.lookandfeel.LookAndFeelActivity import com.jerboa.ui.theme.JerboaTheme -import com.jerboa.util.BackConfirmation.addConfirmationDialog -import com.jerboa.util.BackConfirmation.addConfirmationToast -import com.jerboa.util.BackConfirmation.disposeConfirmation -import com.jerboa.util.BackConfirmationMode -import com.jerboa.util.ShowConfirmationDialog class MainActivity : AppCompatActivity() { val siteViewModel by viewModels() @@ -256,6 +256,7 @@ class MainActivity : AppCompatActivity() { blurNSFW = appSettings.blurNSFW, showPostLinkPreviews = appSettings.showPostLinkPreviews, markAsReadOnScroll = appSettings.markAsReadOnScroll, + postActionbarMode = appSettings.postActionbarMode, ) } @@ -297,6 +298,7 @@ class MainActivity : AppCompatActivity() { blurNSFW = appSettings.blurNSFW, showPostLinkPreviews = appSettings.showPostLinkPreviews, markAsReadOnScroll = appSettings.markAsReadOnScroll, + postActionbarMode = appSettings.postActionbarMode, ) } @@ -369,6 +371,7 @@ class MainActivity : AppCompatActivity() { drawerState = drawerState, onBack = appState::popBackStack, markAsReadOnScroll = appSettings.markAsReadOnScroll, + postActionbarMode = appSettings.postActionbarMode, ) } @@ -403,6 +406,7 @@ class MainActivity : AppCompatActivity() { showPostLinkPreviews = appSettings.showPostLinkPreviews, drawerState = drawerState, markAsReadOnScroll = appSettings.markAsReadOnScroll, + postActionbarMode = appSettings.postActionbarMode, ) } @@ -508,6 +512,7 @@ class MainActivity : AppCompatActivity() { usePrivateTabs = appSettings.usePrivateTabs, blurNSFW = appSettings.blurNSFW, showPostLinkPreview = appSettings.showPostLinkPreviews, + postActionbarMode = appSettings.postActionbarMode, ) } } @@ -538,6 +543,7 @@ class MainActivity : AppCompatActivity() { siteViewModel = siteViewModel, blurNSFW = appSettings.blurNSFW, showPostLinkPreview = appSettings.showPostLinkPreviews, + postActionbarMode = appSettings.postActionbarMode, ) } diff --git a/app/src/main/java/com/jerboa/datatypes/SampleData.kt b/app/src/main/java/com/jerboa/datatypes/SampleData.kt index d7f5c6da7..8a43769da 100644 --- a/app/src/main/java/com/jerboa/datatypes/SampleData.kt +++ b/app/src/main/java/com/jerboa/datatypes/SampleData.kt @@ -230,7 +230,7 @@ val samplePostView = PostView( read = false, creator_blocked = false, my_vote = null, - unread_comments = 0, + unread_comments = 2, ) val sampleLinkPostView = PostView( diff --git a/app/src/main/java/com/jerboa/db/AppDB.kt b/app/src/main/java/com/jerboa/db/AppDB.kt index 1f23eabb6..a14a88821 100644 --- a/app/src/main/java/com/jerboa/db/AppDB.kt +++ b/app/src/main/java/com/jerboa/db/AppDB.kt @@ -36,10 +36,11 @@ val APP_SETTINGS_DEFAULT = AppSettings( backConfirmationMode = 1, markAsReadOnScroll = false, showPostLinkPreviews = true, + postActionbarMode = 0, ) @Database( - version = 23, + version = 24, entities = [Account::class, AppSettings::class], exportSchema = true, ) diff --git a/app/src/main/java/com/jerboa/db/AppDBMigrations.kt b/app/src/main/java/com/jerboa/db/AppDBMigrations.kt index 2af65d5c2..30e67d488 100644 --- a/app/src/main/java/com/jerboa/db/AppDBMigrations.kt +++ b/app/src/main/java/com/jerboa/db/AppDBMigrations.kt @@ -296,6 +296,31 @@ val MIGRATION_22_23 = object : Migration(22, 23) { } } +val MIGRATION_23_22 = object : Migration(23, 22) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( + "ALTER TABLE AppSettings DROP COLUMN markAsReadOnScroll", + ) + } +} + +val MIGRATION_23_24 = object : Migration(23, 24) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(UPDATE_APP_CHANGELOG_UNVIEWED) + database.execSQL( + "ALTER TABLE AppSettings ADD COLUMN post_actionbar_mode INTEGER NOT NULL DEFAULT 0", + ) + } +} + +val MIGRATION_24_23 = object : Migration(24, 23) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( + "ALTER TABLE AppSettings DROP COLUMN post_actionbar_mode", + ) + } +} + // Don't forget to test your migration with `./gradlew app:connectAndroidTest` val MIGRATIONS_LIST = arrayOf( MIGRATION_1_2, @@ -321,4 +346,7 @@ val MIGRATIONS_LIST = arrayOf( MIGRATION_21_22, MIGRATION_22_21, MIGRATION_22_23, + MIGRATION_23_22, + MIGRATION_23_24, + MIGRATION_24_23, ) diff --git a/app/src/main/java/com/jerboa/db/entity/Account.kt b/app/src/main/java/com/jerboa/db/entity/Account.kt index ed66d558b..eee3eee86 100644 --- a/app/src/main/java/com/jerboa/db/entity/Account.kt +++ b/app/src/main/java/com/jerboa/db/entity/Account.kt @@ -3,7 +3,7 @@ package com.jerboa.db.entity import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey -import com.jerboa.util.AccountVerificationState +import com.jerboa.feat.AccountVerificationState @Entity data class Account( diff --git a/app/src/main/java/com/jerboa/db/entity/AppSettings.kt b/app/src/main/java/com/jerboa/db/entity/AppSettings.kt index 6df88c736..138ee58e2 100644 --- a/app/src/main/java/com/jerboa/db/entity/AppSettings.kt +++ b/app/src/main/java/com/jerboa/db/entity/AppSettings.kt @@ -103,4 +103,9 @@ data class AppSettings( defaultValue = "1", ) val showPostLinkPreviews: Boolean, + @ColumnInfo( + name = "post_actionbar_mode", + defaultValue = "0", + ) + val postActionbarMode: Int, ) diff --git a/app/src/main/java/com/jerboa/util/AccountVerificationState.kt b/app/src/main/java/com/jerboa/feat/AccountVerificationState.kt similarity index 99% rename from app/src/main/java/com/jerboa/util/AccountVerificationState.kt rename to app/src/main/java/com/jerboa/feat/AccountVerificationState.kt index 253c634b1..62fe40a92 100644 --- a/app/src/main/java/com/jerboa/util/AccountVerificationState.kt +++ b/app/src/main/java/com/jerboa/feat/AccountVerificationState.kt @@ -1,4 +1,4 @@ -package com.jerboa.util +package com.jerboa.feat import android.content.Context import android.net.ConnectivityManager @@ -260,7 +260,9 @@ suspend fun Account.checkAccountVerification( checkIfSiteRetrievalSucceeded(siteViewModel, this).first } - AccountVerificationState.CHECKS_COMPLETE -> { CheckState.Passed } + AccountVerificationState.CHECKS_COMPLETE -> { + CheckState.Passed + } } Log.d("verification", "Verified ${verifyState.name} with ${checkState::class.simpleName}") diff --git a/app/src/main/java/com/jerboa/util/BackConfirmation.kt b/app/src/main/java/com/jerboa/feat/BackConfirmation.kt similarity index 99% rename from app/src/main/java/com/jerboa/util/BackConfirmation.kt rename to app/src/main/java/com/jerboa/feat/BackConfirmation.kt index ce7e80392..0544e6656 100644 --- a/app/src/main/java/com/jerboa/util/BackConfirmation.kt +++ b/app/src/main/java/com/jerboa/feat/BackConfirmation.kt @@ -1,4 +1,4 @@ -package com.jerboa.util +package com.jerboa.feat import android.content.Context import android.widget.Toast diff --git a/app/src/main/java/com/jerboa/feat/PostActionbarMode.kt b/app/src/main/java/com/jerboa/feat/PostActionbarMode.kt new file mode 100644 index 000000000..0bea1d762 --- /dev/null +++ b/app/src/main/java/com/jerboa/feat/PostActionbarMode.kt @@ -0,0 +1,10 @@ +package com.jerboa.feat + +import androidx.annotation.StringRes +import com.jerboa.R + +enum class PostActionbarMode(@StringRes val resId: Int) { + RightHandShort(R.string.post_actionbar_mode_short_right), + LeftHandShort(R.string.post_actionbar_mode_short_left), + Long(R.string.post_actionbar_mode_long), +} diff --git a/app/src/main/java/com/jerboa/model/AccountViewModel.kt b/app/src/main/java/com/jerboa/model/AccountViewModel.kt index f8aa1b86e..042207d55 100644 --- a/app/src/main/java/com/jerboa/model/AccountViewModel.kt +++ b/app/src/main/java/com/jerboa/model/AccountViewModel.kt @@ -10,10 +10,10 @@ import com.jerboa.db.entity.AnonAccount import com.jerboa.db.entity.isAnon import com.jerboa.db.entity.isReady import com.jerboa.db.repository.AccountRepository +import com.jerboa.feat.AccountVerificationState import com.jerboa.fetchHomePosts import com.jerboa.fetchInitialData import com.jerboa.jerboaApplication -import com.jerboa.util.AccountVerificationState import kotlinx.coroutines.launch @Stable diff --git a/app/src/main/java/com/jerboa/ui/components/comment/CommentNode.kt b/app/src/main/java/com/jerboa/ui/components/comment/CommentNode.kt index 60682e1a6..4ca4ef6fb 100644 --- a/app/src/main/java/com/jerboa/ui/components/comment/CommentNode.kt +++ b/app/src/main/java/com/jerboa/ui/components/comment/CommentNode.kt @@ -22,6 +22,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Bookmark import androidx.compose.material.icons.outlined.Block import androidx.compose.material.icons.outlined.BookmarkBorder +import androidx.compose.material.icons.outlined.Comment import androidx.compose.material.icons.outlined.ContentCopy import androidx.compose.material.icons.outlined.Delete import androidx.compose.material.icons.outlined.Description @@ -32,7 +33,6 @@ import androidx.compose.material.icons.outlined.Link import androidx.compose.material.icons.outlined.MoreVert import androidx.compose.material.icons.outlined.Person import androidx.compose.material.icons.outlined.Restore -import androidx.compose.material.icons.outlined.Textsms import androidx.compose.material3.AlertDialog import androidx.compose.material3.Divider import androidx.compose.material3.MaterialTheme @@ -607,6 +607,12 @@ fun CommentFooterLine( account = account, ) } + ActionBarButton( + icon = Icons.Outlined.Comment, + onClick = { onReplyClick(commentView) }, + contentDescription = stringResource(R.string.commentFooter_reply), + account = account, + ) ActionBarButton( icon = if (commentView.saved) { Icons.Filled.Bookmark } else { Icons.Outlined.BookmarkBorder @@ -624,12 +630,6 @@ fun CommentFooterLine( }, account = account, ) - ActionBarButton( - icon = Icons.Outlined.Textsms, - onClick = { onReplyClick(commentView) }, - contentDescription = stringResource(R.string.commentFooter_reply), - account = account, - ) ActionBarButton( icon = Icons.Outlined.MoreVert, contentDescription = stringResource(R.string.moreOptions), diff --git a/app/src/main/java/com/jerboa/ui/components/comment/edit/CommentEditActivity.kt b/app/src/main/java/com/jerboa/ui/components/comment/edit/CommentEditActivity.kt index 5467db0cb..e61e0a560 100644 --- a/app/src/main/java/com/jerboa/ui/components/comment/edit/CommentEditActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/comment/edit/CommentEditActivity.kt @@ -19,12 +19,12 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.jerboa.JerboaAppState import com.jerboa.api.ApiState import com.jerboa.datatypes.types.CommentView +import com.jerboa.feat.doIfReadyElseDisplayInfo import com.jerboa.model.AccountViewModel import com.jerboa.model.CommentEditViewModel import com.jerboa.ui.components.common.JerboaSnackbarHost import com.jerboa.ui.components.common.getCurrentAccount import com.jerboa.util.InitializeRoute -import com.jerboa.util.doIfReadyElseDisplayInfo object CommentEditReturn { const val COMMENT_VIEW = "comment-edit::return(comment-view)" diff --git a/app/src/main/java/com/jerboa/ui/components/comment/mentionnode/CommentMentionNode.kt b/app/src/main/java/com/jerboa/ui/components/comment/mentionnode/CommentMentionNode.kt index e5b0d56bc..51a0932fa 100644 --- a/app/src/main/java/com/jerboa/ui/components/comment/mentionnode/CommentMentionNode.kt +++ b/app/src/main/java/com/jerboa/ui/components/comment/mentionnode/CommentMentionNode.kt @@ -13,6 +13,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Bookmark import androidx.compose.material.icons.outlined.Block import androidx.compose.material.icons.outlined.BookmarkBorder +import androidx.compose.material.icons.outlined.Comment import androidx.compose.material.icons.outlined.ContentCopy import androidx.compose.material.icons.outlined.Description import androidx.compose.material.icons.outlined.Flag @@ -21,7 +22,6 @@ import androidx.compose.material.icons.outlined.MarkChatRead import androidx.compose.material.icons.outlined.MarkChatUnread import androidx.compose.material.icons.outlined.MoreVert import androidx.compose.material.icons.outlined.Person -import androidx.compose.material.icons.outlined.Textsms import androidx.compose.material3.AlertDialog import androidx.compose.material3.Divider import androidx.compose.material3.MaterialTheme @@ -197,6 +197,15 @@ fun CommentMentionNodeFooterLine( }, account = account, ) + // Don't let you respond to your own comment. + if (personMentionView.creator.id != account.id) { + ActionBarButton( + icon = Icons.Outlined.Comment, + contentDescription = stringResource(R.string.commentFooter_reply), + onClick = { onReplyClick(personMentionView) }, + account = account, + ) + } ActionBarButton( icon = if (personMentionView.saved) { Icons.Filled.Bookmark @@ -216,15 +225,6 @@ fun CommentMentionNodeFooterLine( }, account = account, ) - // Don't let you respond to your own comment. - if (personMentionView.creator.id != account.id) { - ActionBarButton( - icon = Icons.Outlined.Textsms, - contentDescription = stringResource(R.string.commentFooter_reply), - onClick = { onReplyClick(personMentionView) }, - account = account, - ) - } ActionBarButton( icon = Icons.Outlined.MoreVert, contentDescription = stringResource(R.string.moreOptions), diff --git a/app/src/main/java/com/jerboa/ui/components/comment/replynode/CommentReplyNode.kt b/app/src/main/java/com/jerboa/ui/components/comment/replynode/CommentReplyNode.kt index e5c444789..42b5431b1 100644 --- a/app/src/main/java/com/jerboa/ui/components/comment/replynode/CommentReplyNode.kt +++ b/app/src/main/java/com/jerboa/ui/components/comment/replynode/CommentReplyNode.kt @@ -13,6 +13,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Bookmark import androidx.compose.material.icons.outlined.Block import androidx.compose.material.icons.outlined.BookmarkBorder +import androidx.compose.material.icons.outlined.Comment import androidx.compose.material.icons.outlined.Description import androidx.compose.material.icons.outlined.Flag import androidx.compose.material.icons.outlined.Link @@ -20,7 +21,6 @@ import androidx.compose.material.icons.outlined.MarkChatRead import androidx.compose.material.icons.outlined.MarkChatUnread import androidx.compose.material.icons.outlined.MoreVert import androidx.compose.material.icons.outlined.Person -import androidx.compose.material.icons.outlined.Textsms import androidx.compose.material3.AlertDialog import androidx.compose.material3.Divider import androidx.compose.material3.MaterialTheme @@ -98,7 +98,7 @@ fun CommentReplyNodeHeaderPreview() { } @Composable -fun CommentReplyNodeFooterLine( +fun CommentReplyNodeInboxFooterLine( commentReplyView: CommentReplyView, onUpvoteClick: () -> Unit, onDownvoteClick: () -> Unit, @@ -215,7 +215,7 @@ fun CommentReplyNodeFooterLine( // Don't let you respond to your own comment. if (commentReplyView.creator.id != account.id) { ActionBarButton( - icon = Icons.Outlined.Textsms, + icon = Icons.Outlined.Comment, contentDescription = stringResource(R.string.commentFooter_reply), onClick = { onReplyClick(commentReplyView) }, account = account, @@ -298,7 +298,7 @@ fun CommentReplyNodeOptionsDialog( } @Composable -fun CommentReplyNode( +fun CommentReplyNodeInbox( commentReplyView: CommentReplyView, onUpvoteClick: (commentReplyView: CommentReplyView) -> Unit, onDownvoteClick: (commentReplyView: CommentReplyView) -> Unit, @@ -372,7 +372,7 @@ fun CommentReplyNode( enter = expandVertically(), exit = shrinkVertically(), ) { - CommentReplyNodeFooterLine( + CommentReplyNodeInboxFooterLine( commentReplyView = commentReplyView, onUpvoteClick = { onUpvoteClick(commentReplyView) diff --git a/app/src/main/java/com/jerboa/ui/components/common/AppBars.kt b/app/src/main/java/com/jerboa/ui/components/common/AppBars.kt index 923b6918d..58f7bed1e 100644 --- a/app/src/main/java/com/jerboa/ui/components/common/AppBars.kt +++ b/app/src/main/java/com/jerboa/ui/components/common/AppBars.kt @@ -36,6 +36,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -44,13 +45,14 @@ import com.jerboa.datatypes.samplePerson import com.jerboa.datatypes.samplePost import com.jerboa.datatypes.types.Person import com.jerboa.db.entity.Account +import com.jerboa.db.entity.AnonAccount +import com.jerboa.feat.isReadyAndIfNotShowSimplifiedInfoToast import com.jerboa.scrollToNextParentComment import com.jerboa.scrollToPreviousParentComment import com.jerboa.siFormat import com.jerboa.ui.components.home.NavTab import com.jerboa.ui.components.person.PersonProfileLink import com.jerboa.ui.theme.* -import com.jerboa.util.isReadyAndIfNotShowSimplifiedInfoToast import kotlinx.coroutines.CoroutineScope @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @@ -283,6 +285,65 @@ fun ActionBarButton( onClick: () -> Unit, icon: ImageVector, contentDescription: String?, + modifier: Modifier = Modifier, + text: String? = null, + contentColor: Color = MaterialTheme.colorScheme.onBackground.muted, + noClick: Boolean = false, + account: Account, + requiresAccount: Boolean = true, +) { + val ctx = LocalContext.current + + val barMod = if (noClick) { + modifier + } else { + modifier.clickable(onClick = { + if (!requiresAccount || account.isReadyAndIfNotShowSimplifiedInfoToast(ctx)) { + onClick() + } + }) + } + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = barMod, + ) { + Icon( + imageVector = icon, + contentDescription = contentDescription, + tint = contentColor, + ) + text?.also { + Spacer(Modifier.size(ButtonDefaults.IconSpacing)) + Text( + text = text, + color = contentColor, + style = MaterialTheme.typography.bodyMedium, + ) + } + } +} + +@Preview +@Composable +fun ActionBarButtonAndBadgePreview() { + ActionBarButtonAndBadge( + icon = Icons.Outlined.ChatBubbleOutline, + iconBadgeCount = siFormat(15), + contentDescription = null, + text = siFormat(2000), + noClick = true, + account = AnonAccount, + onClick = {}, + ) +} + +@Composable +fun ActionBarButtonAndBadge( + onClick: () -> Unit, + icon: ImageVector, + iconBadgeCount: String?, + contentDescription: String?, + modifier: Modifier = Modifier, text: String? = null, contentColor: Color = MaterialTheme.colorScheme.onBackground.muted, noClick: Boolean = false, @@ -292,9 +353,9 @@ fun ActionBarButton( val ctx = LocalContext.current val barMod = if (noClick) { - Modifier + modifier } else { - Modifier.clickable(onClick = { + modifier.clickable(onClick = { if (!requiresAccount || account.isReadyAndIfNotShowSimplifiedInfoToast(ctx)) { onClick() } @@ -317,6 +378,17 @@ fun ActionBarButton( style = MaterialTheme.typography.bodyMedium, ) } + iconBadgeCount?.also { + Spacer(Modifier.size(ButtonDefaults.IconSpacing)) + TextBadge( + containerColor = MaterialTheme.colorScheme.tertiaryContainer, + text = iconBadgeCount, + textStyle = MaterialTheme.typography.bodySmall.copy(fontStyle = FontStyle.Italic), + textColor = contentColor, + verticalTextPadding = 2f, + horizontalTextPadding = 4f, + ) + } } } @@ -356,6 +428,7 @@ fun InboxIconAndBadge( modifier = modifier, badge = { Badge( + containerColor = MaterialTheme.colorScheme.tertiary, content = { Text( text = iconBadgeCount.toString(), diff --git a/app/src/main/java/com/jerboa/ui/components/community/CommunityActivity.kt b/app/src/main/java/com/jerboa/ui/components/community/CommunityActivity.kt index 15942341d..2fd8d774f 100644 --- a/app/src/main/java/com/jerboa/ui/components/community/CommunityActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/community/CommunityActivity.kt @@ -51,6 +51,7 @@ import com.jerboa.datatypes.types.SavePost import com.jerboa.datatypes.types.SortType import com.jerboa.datatypes.types.SubscribedType import com.jerboa.db.entity.isAnon +import com.jerboa.feat.doIfReadyElseDisplayInfo import com.jerboa.hostName import com.jerboa.model.AccountViewModel import com.jerboa.model.AppSettingsViewModel @@ -72,7 +73,6 @@ import com.jerboa.ui.components.post.PostListings import com.jerboa.ui.components.post.PostViewReturn import com.jerboa.ui.components.post.edit.PostEditReturn import com.jerboa.util.InitializeRoute -import com.jerboa.util.doIfReadyElseDisplayInfo import kotlinx.collections.immutable.toImmutableList @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class) @@ -90,6 +90,7 @@ fun CommunityActivity( blurNSFW: Boolean, showPostLinkPreviews: Boolean, markAsReadOnScroll: Boolean, + postActionbarMode: Int, ) { Log.d("jerboa", "got to community activity") val transferCreatePostDepsViaRoot = appState.rootChannel() @@ -482,6 +483,7 @@ fun CommunityActivity( }, showIfRead = true, showScores = siteViewModel.showScores(), + postActionbarMode = postActionbarMode, ) } else -> {} diff --git a/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt b/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt index 35bb1bcae..d7bcb99dd 100644 --- a/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/home/BottomNavActivity.kt @@ -43,6 +43,7 @@ import com.jerboa.JerboaAppState import com.jerboa.R import com.jerboa.api.ApiState import com.jerboa.db.entity.AppSettings +import com.jerboa.feat.doIfReadyElseDisplayInfo import com.jerboa.fetchHomePosts import com.jerboa.model.AccountViewModel import com.jerboa.model.AppSettingsViewModel @@ -56,7 +57,6 @@ import com.jerboa.ui.components.drawer.MainDrawer import com.jerboa.ui.components.inbox.InboxActivity import com.jerboa.ui.components.person.PersonProfileActivity import com.jerboa.util.InitializeRoute -import com.jerboa.util.doIfReadyElseDisplayInfo import kotlinx.coroutines.launch enum class NavTab( @@ -227,6 +227,7 @@ fun BottomNavActivity( blurNSFW = appSettings.blurNSFW, showPostLinkPreviews = appSettings.showPostLinkPreviews, markAsReadOnScroll = appSettings.markAsReadOnScroll, + postActionbarMode = appSettings.postActionbarMode, ) } @@ -266,6 +267,7 @@ fun BottomNavActivity( showPostLinkPreviews = appSettings.showPostLinkPreviews, drawerState = drawerState, markAsReadOnScroll = appSettings.markAsReadOnScroll, + postActionbarMode = appSettings.postActionbarMode, ) } @@ -284,6 +286,7 @@ fun BottomNavActivity( showPostLinkPreviews = appSettings.showPostLinkPreviews, drawerState = drawerState, markAsReadOnScroll = appSettings.markAsReadOnScroll, + postActionbarMode = appSettings.postActionbarMode, ) } } diff --git a/app/src/main/java/com/jerboa/ui/components/home/HomeActivity.kt b/app/src/main/java/com/jerboa/ui/components/home/HomeActivity.kt index 7c22117ee..0f3a4c0bb 100644 --- a/app/src/main/java/com/jerboa/ui/components/home/HomeActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/home/HomeActivity.kt @@ -54,6 +54,7 @@ import com.jerboa.datatypes.types.Tagline import com.jerboa.db.entity.Account import com.jerboa.db.entity.isAnon import com.jerboa.db.entity.isReady +import com.jerboa.feat.doIfReadyElseDisplayInfo import com.jerboa.model.AccountViewModel import com.jerboa.model.AppSettingsViewModel import com.jerboa.model.HomeViewModel @@ -74,7 +75,6 @@ import com.jerboa.ui.components.common.isRefreshing import com.jerboa.ui.components.post.PostListings import com.jerboa.ui.components.post.PostViewReturn import com.jerboa.ui.components.post.edit.PostEditReturn -import com.jerboa.util.doIfReadyElseDisplayInfo import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.launch @@ -94,6 +94,7 @@ fun HomeActivity( blurNSFW: Boolean, showPostLinkPreviews: Boolean, markAsReadOnScroll: Boolean, + postActionbarMode: Int, ) { Log.d("jerboa", "got to home activity") val transferCreatePostDepsViaRoot = appState.rootChannel() @@ -158,6 +159,7 @@ fun HomeActivity( showPostLinkPreviews = showPostLinkPreviews, markAsReadOnScroll = markAsReadOnScroll, snackbarHostState = snackbarHostState, + postActionbarMode = postActionbarMode, ) }, floatingActionButtonPosition = FabPosition.End, @@ -206,6 +208,7 @@ fun MainPostListingsContent( showPostLinkPreviews: Boolean, snackbarHostState: SnackbarHostState, markAsReadOnScroll: Boolean, + postActionbarMode: Int, ) { val ctx = LocalContext.current val scope = rememberCoroutineScope() @@ -421,6 +424,7 @@ fun MainPostListingsContent( }, showIfRead = true, showScores = siteViewModel.showScores(), + postActionbarMode = postActionbarMode, ) } } diff --git a/app/src/main/java/com/jerboa/ui/components/inbox/InboxActivity.kt b/app/src/main/java/com/jerboa/ui/components/inbox/InboxActivity.kt index 83a4ff7e3..916bf241d 100644 --- a/app/src/main/java/com/jerboa/ui/components/inbox/InboxActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/inbox/InboxActivity.kt @@ -56,6 +56,7 @@ import com.jerboa.datatypes.types.MarkPrivateMessageAsRead import com.jerboa.datatypes.types.SaveComment import com.jerboa.db.entity.Account import com.jerboa.db.entity.isAnon +import com.jerboa.feat.doIfReadyElseDisplayInfo import com.jerboa.getCommentParentId import com.jerboa.getLocalizedStringForInboxTab import com.jerboa.isScrolledToEnd @@ -67,7 +68,7 @@ import com.jerboa.newVote import com.jerboa.pagerTabIndicatorOffset2 import com.jerboa.rootChannel import com.jerboa.ui.components.comment.mentionnode.CommentMentionNode -import com.jerboa.ui.components.comment.replynode.CommentReplyNode +import com.jerboa.ui.components.comment.replynode.CommentReplyNodeInbox import com.jerboa.ui.components.common.ApiEmptyText import com.jerboa.ui.components.common.ApiErrorText import com.jerboa.ui.components.common.JerboaSnackbarHost @@ -79,7 +80,6 @@ import com.jerboa.ui.components.common.simpleVerticalScrollbar import com.jerboa.ui.components.privatemessage.PrivateMessage import com.jerboa.unreadOrAllFromBool import com.jerboa.util.InitializeRoute -import com.jerboa.util.doIfReadyElseDisplayInfo import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -371,7 +371,7 @@ fun InboxTabs( key = { reply -> reply.comment_reply.id }, contentType = { "comment" }, ) { commentReplyView -> - CommentReplyNode( + CommentReplyNodeInbox( commentReplyView = commentReplyView, onUpvoteClick = { cr -> account.doIfReadyElseDisplayInfo( diff --git a/app/src/main/java/com/jerboa/ui/components/person/PersonProfileActivity.kt b/app/src/main/java/com/jerboa/ui/components/person/PersonProfileActivity.kt index 82f712b87..4b40c345c 100644 --- a/app/src/main/java/com/jerboa/ui/components/person/PersonProfileActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/person/PersonProfileActivity.kt @@ -70,6 +70,7 @@ import com.jerboa.datatypes.types.SavePost import com.jerboa.datatypes.types.SortType import com.jerboa.db.entity.Account import com.jerboa.db.entity.isAnon +import com.jerboa.feat.doIfReadyElseDisplayInfo import com.jerboa.getLocalizedStringForUserTab import com.jerboa.isScrolledToEnd import com.jerboa.model.AccountViewModel @@ -101,7 +102,6 @@ import com.jerboa.ui.components.post.PostViewReturn import com.jerboa.ui.components.post.edit.PostEditReturn import com.jerboa.ui.theme.MEDIUM_PADDING import com.jerboa.util.InitializeRoute -import com.jerboa.util.doIfReadyElseDisplayInfo import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -122,6 +122,7 @@ fun PersonProfileActivity( showPostLinkPreviews: Boolean, drawerState: DrawerState, markAsReadOnScroll: Boolean, + postActionbarMode: Int, onBack: (() -> Unit)? = null, ) { Log.d("jerboa", "got to person activity") @@ -289,6 +290,7 @@ fun PersonProfileActivity( markAsReadOnScroll = markAsReadOnScroll, snackbarHostState = snackbarHostState, showScores = siteViewModel.showScores(), + postActionbarMode = postActionbarMode, ) }, ) @@ -322,6 +324,7 @@ fun UserTabs( markAsReadOnScroll: Boolean, snackbarHostState: SnackbarHostState, showScores: Boolean, + postActionbarMode: Int, ) { val transferCommentEditDepsViaRoot = appState.rootChannel() val transferCommentReplyDepsViaRoot = appState.rootChannel() @@ -641,6 +644,7 @@ fun UserTabs( }, showIfRead = false, showScores = showScores, + postActionbarMode = postActionbarMode, ) } else -> {} diff --git a/app/src/main/java/com/jerboa/ui/components/post/PostActivity.kt b/app/src/main/java/com/jerboa/ui/components/post/PostActivity.kt index 4d5760374..bb7b71846 100644 --- a/app/src/main/java/com/jerboa/ui/components/post/PostActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/post/PostActivity.kt @@ -75,6 +75,7 @@ import com.jerboa.datatypes.types.PostView import com.jerboa.datatypes.types.SaveComment import com.jerboa.datatypes.types.SavePost import com.jerboa.db.entity.isAnon +import com.jerboa.feat.doIfReadyElseDisplayInfo import com.jerboa.getCommentParentId import com.jerboa.getDepthFromComment import com.jerboa.getLocalizedCommentSortTypeName @@ -104,7 +105,6 @@ import com.jerboa.ui.components.common.isRefreshing import com.jerboa.ui.components.common.simpleVerticalScrollbar import com.jerboa.ui.components.post.edit.PostEditReturn import com.jerboa.util.InitializeRoute -import com.jerboa.util.doIfReadyElseDisplayInfo import kotlinx.collections.immutable.toImmutableSet object PostViewReturn { @@ -149,6 +149,7 @@ fun PostActivity( navigateParentCommentsWithVolumeButtons: Boolean, blurNSFW: Boolean, showPostLinkPreview: Boolean, + postActionbarMode: Int, ) { Log.d("jerboa", "got to post activity") val transferCommentEditDepsViaRoot = appState.rootChannel() @@ -491,6 +492,7 @@ fun PostActivity( showPostLinkPreview = showPostLinkPreview, showIfRead = false, showScores = siteViewModel.showScores(), + postActionbarMode = postActionbarMode, ) } diff --git a/app/src/main/java/com/jerboa/ui/components/post/PostListing.kt b/app/src/main/java/com/jerboa/ui/components/post/PostListing.kt index d5e1238ba..33aeea19a 100644 --- a/app/src/main/java/com/jerboa/ui/components/post/PostListing.kt +++ b/app/src/main/java/com/jerboa/ui/components/post/PostListing.kt @@ -22,7 +22,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Bookmark import androidx.compose.material.icons.outlined.Block import androidx.compose.material.icons.outlined.BookmarkBorder -import androidx.compose.material.icons.outlined.ChatBubbleOutline +import androidx.compose.material.icons.outlined.Comment import androidx.compose.material.icons.outlined.CommentsDisabled import androidx.compose.material.icons.outlined.ContentCopy import androidx.compose.material.icons.outlined.Delete @@ -36,7 +36,6 @@ import androidx.compose.material.icons.outlined.Person import androidx.compose.material.icons.outlined.PushPin import androidx.compose.material.icons.outlined.Restore import androidx.compose.material.icons.outlined.Share -import androidx.compose.material.icons.outlined.Textsms import androidx.compose.material3.AlertDialog import androidx.compose.material3.Card import androidx.compose.material3.Divider @@ -84,11 +83,15 @@ import com.jerboa.datatypes.types.Post import com.jerboa.datatypes.types.PostView import com.jerboa.db.entity.Account import com.jerboa.db.entity.AnonAccount +import com.jerboa.feat.PostActionbarMode import com.jerboa.getPostType import com.jerboa.hostName import com.jerboa.isSameInstance import com.jerboa.nsfwCheck +import com.jerboa.siFormat +import com.jerboa.toEnum import com.jerboa.ui.components.common.ActionBarButton +import com.jerboa.ui.components.common.ActionBarButtonAndBadge import com.jerboa.ui.components.common.CircularIcon import com.jerboa.ui.components.common.CommentOrPostNodeHeader import com.jerboa.ui.components.common.DotSpacer @@ -561,6 +564,7 @@ fun PostFooterLine( enableDownVotes: Boolean, viewSource: Boolean, showScores: Boolean, + postActionbarMode: Int, ) { var showMoreOptions by remember { mutableStateOf(false) } @@ -609,100 +613,128 @@ fun PostFooterLine( ) } + val postActionbar = postActionbarMode.toEnum() + + val horizontalArrangement = when (postActionbar) { + PostActionbarMode.Long -> Arrangement.spacedBy(XXL_PADDING) + PostActionbarMode.LeftHandShort -> Arrangement.spacedBy(LARGE_PADDING) + PostActionbarMode.RightHandShort -> Arrangement.spacedBy(LARGE_PADDING) + } + Row( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = horizontalArrangement, + verticalAlignment = Alignment.Bottom, modifier = modifier .fillMaxWidth() .padding(bottom = SMALL_PADDING), ) { - CommentCount( - comments = postView.counts.comments, - unreadCount = postView.unread_comments, + // Right handside shows the comments on the left side + if (postActionbar == PostActionbarMode.RightHandShort) { + CommentNewCountRework( + comments = postView.counts.comments, + unreadCount = postView.unread_comments, + account = account, + modifier = Modifier.weight(1F, true), + ) + } + + VoteGeneric( + myVote = instantScores.myVote, + votes = instantScores.upvotes, + type = VoteType.Upvote, + showNumber = (instantScores.downvotes != 0) && showScores, + onVoteClick = onUpvoteClick, account = account, ) - Row( - horizontalArrangement = Arrangement.spacedBy(XXL_PADDING), - ) { + if (enableDownVotes) { VoteGeneric( myVote = instantScores.myVote, - votes = instantScores.upvotes, - type = VoteType.Upvote, - showNumber = (instantScores.downvotes != 0) && showScores, - onVoteClick = onUpvoteClick, + votes = instantScores.downvotes, + showNumber = showScores, + type = VoteType.Downvote, + onVoteClick = onDownvoteClick, account = account, ) - if (enableDownVotes) { - VoteGeneric( - myVote = instantScores.myVote, - votes = instantScores.downvotes, - showNumber = showScores, - type = VoteType.Downvote, - onVoteClick = onDownvoteClick, - account = account, - ) - } - ActionBarButton( - icon = if (postView.saved) { - Icons.Filled.Bookmark - } else { - Icons.Outlined.BookmarkBorder - }, - contentDescription = if (postView.saved) { - stringResource(R.string.removeBookmark) - } else { - stringResource(R.string.addBookmark) - }, - onClick = { onSaveClick(postView) }, - contentColor = if (postView.saved) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.onBackground.muted - }, + } + + if (postActionbar == PostActionbarMode.Long) { + CommentNewCountRework( + comments = postView.counts.comments, + unreadCount = postView.unread_comments, account = account, + modifier = Modifier.weight(1F, true), ) - if (showReply) { - ActionBarButton( - icon = Icons.Outlined.Textsms, - contentDescription = stringResource(R.string.postListing_reply), - onClick = { onReplyClick(postView) }, - account = account, - ) - } + } + + if (showReply) { ActionBarButton( - icon = Icons.Outlined.MoreVert, - contentDescription = stringResource(R.string.moreOptions), + icon = Icons.Outlined.Comment, + contentDescription = stringResource(R.string.postListing_reply), + onClick = { onReplyClick(postView) }, + account = account, + ) + } + ActionBarButton( + icon = if (postView.saved) { + Icons.Filled.Bookmark + } else { + Icons.Outlined.BookmarkBorder + }, + contentDescription = if (postView.saved) { + stringResource(R.string.removeBookmark) + } else { + stringResource(R.string.addBookmark) + }, + onClick = { onSaveClick(postView) }, + contentColor = if (postView.saved) { + MaterialTheme.colorScheme.primary + } else { + MaterialTheme.colorScheme.onBackground.muted + }, + account = account, + ) + ActionBarButton( + icon = Icons.Outlined.MoreVert, + contentDescription = stringResource(R.string.moreOptions), + account = account, + onClick = { showMoreOptions = !showMoreOptions }, + requiresAccount = false, + modifier = Modifier.weight(1F, true), + ) + + if (postActionbar == PostActionbarMode.LeftHandShort) { + CommentNewCountRework( + comments = postView.counts.comments, + unreadCount = postView.unread_comments, account = account, - onClick = { showMoreOptions = !showMoreOptions }, - requiresAccount = false, ) } } } @Composable -fun CommentCount( +fun CommentNewCountRework( comments: Int, unreadCount: Int, account: Account, + modifier: Modifier = Modifier, ) { - Row( - verticalAlignment = Alignment.CenterVertically, - ) { - ActionBarButton( - icon = Icons.Outlined.ChatBubbleOutline, - contentDescription = null, - text = stringResource(R.string.post_listing_comments, comments), - noClick = true, - account = account, - onClick = {}, // This is handled by the whole button click - ) - CommentNewCount( - comments = comments, - unreadCount = unreadCount, - spacing = SMALL_PADDING, - ) + val unread = if (unreadCount == 0 || comments == unreadCount) { + null + } else { + (if (unreadCount > 0) "+" else "") + siFormat(unreadCount) } + + ActionBarButtonAndBadge( + icon = Icons.Outlined.Forum, + iconBadgeCount = unread, + contentDescription = null, + text = siFormat(comments), + noClick = true, + account = account, + onClick = {}, + modifier = modifier, + ) } @Composable @@ -731,7 +763,7 @@ fun CommentNewCount( @Preview @Composable fun CommentCountPreview() { - CommentCount(42, 0, account = AnonAccount) + CommentNewCountRework(42, 0, account = AnonAccount) } @Preview @@ -765,6 +797,7 @@ fun PostFooterLinePreview() { enableDownVotes = true, viewSource = false, showScores = true, + postActionbarMode = PostActionbarMode.Long.ordinal, ) } @@ -801,6 +834,7 @@ fun PreviewPostListingCard() { openLink = { _: String, _: Boolean, _: Boolean -> }, showIfRead = true, showScores = true, + postActionbarMode = PostActionbarMode.Long.ordinal, ) } @@ -837,6 +871,7 @@ fun PreviewLinkPostListing() { openLink = { _: String, _: Boolean, _: Boolean -> }, showIfRead = true, showScores = true, + postActionbarMode = PostActionbarMode.Long.ordinal, ) } @@ -873,6 +908,7 @@ fun PreviewImagePostListingCard() { openLink = { _: String, _: Boolean, _: Boolean -> }, showIfRead = true, showScores = true, + postActionbarMode = PostActionbarMode.Long.ordinal, ) } @@ -909,6 +945,7 @@ fun PreviewImagePostListingSmallCard() { openLink = { _: String, _: Boolean, _: Boolean -> }, showIfRead = true, showScores = true, + postActionbarMode = PostActionbarMode.Long.ordinal, ) } @@ -945,6 +982,7 @@ fun PreviewLinkNoThumbnailPostListing() { openLink = { _: String, _: Boolean, _: Boolean -> }, showIfRead = true, showScores = true, + postActionbarMode = PostActionbarMode.Long.ordinal, ) } @@ -981,6 +1019,7 @@ fun PostListing( showPostLinkPreview: Boolean, showIfRead: Boolean, showScores: Boolean, + postActionbarMode: Int, ) { // This stores vote data val instantScores = remember { @@ -1045,6 +1084,7 @@ fun PostListing( showPostLinkPreview = showPostLinkPreview, showIfRead = showIfRead, showScores = showScores, + postActionbarMode = postActionbarMode, ) PostViewMode.SmallCard -> PostListingCard( @@ -1094,6 +1134,7 @@ fun PostListing( showPostLinkPreview = showPostLinkPreview, openImageViewer = openImageViewer, showScores = showScores, + postActionbarMode = postActionbarMode, ) PostViewMode.List -> PostListingList( @@ -1483,6 +1524,7 @@ fun PostListingCard( openImageViewer: (url: String) -> Unit, showIfRead: Boolean = false, showScores: Boolean, + postActionbarMode: Int, ) { Column( modifier = Modifier @@ -1546,6 +1588,7 @@ fun PostListingCard( enableDownVotes = enableDownVotes, viewSource = viewSource, showScores = showScores, + postActionbarMode = postActionbarMode, ) } } @@ -1585,7 +1628,6 @@ fun MetadataCard(post: Post) { ) } -@OptIn(ExperimentalMaterial3Api::class) @Composable fun PostOptionsDialog( postView: PostView, diff --git a/app/src/main/java/com/jerboa/ui/components/post/PostListings.kt b/app/src/main/java/com/jerboa/ui/components/post/PostListings.kt index 4301f2646..54816fc0b 100644 --- a/app/src/main/java/com/jerboa/ui/components/post/PostListings.kt +++ b/app/src/main/java/com/jerboa/ui/components/post/PostListings.kt @@ -67,6 +67,7 @@ fun PostListings( onMarkAsRead: (postView: PostView) -> Unit, showIfRead: Boolean, showScores: Boolean, + postActionbarMode: Int, ) { LazyColumn( state = listState, @@ -114,6 +115,7 @@ fun PostListings( openLink = openLink, showIfRead = showIfRead, showScores = showScores, + postActionbarMode = postActionbarMode, ).let { if (!postView.read && markAsReadOnScroll) { DisposableEffect(key1 = postView.post.id) { @@ -178,5 +180,6 @@ fun PreviewPostListings() { onMarkAsRead = {}, showIfRead = true, showScores = true, + postActionbarMode = 0, ) } diff --git a/app/src/main/java/com/jerboa/ui/components/privatemessage/PrivateMessage.kt b/app/src/main/java/com/jerboa/ui/components/privatemessage/PrivateMessage.kt index 93f3b60ae..53ab0be17 100644 --- a/app/src/main/java/com/jerboa/ui/components/privatemessage/PrivateMessage.kt +++ b/app/src/main/java/com/jerboa/ui/components/privatemessage/PrivateMessage.kt @@ -6,9 +6,9 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Comment import androidx.compose.material.icons.outlined.MarkChatRead import androidx.compose.material.icons.outlined.MarkChatUnread -import androidx.compose.material.icons.outlined.Textsms import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -169,7 +169,7 @@ fun PrivateMessageFooterLine( account = account, ) ActionBarButton( - icon = Icons.Outlined.Textsms, + icon = Icons.Outlined.Comment, contentDescription = stringResource(R.string.privateMessage_reply), onClick = { onReplyClick(privateMessageView) }, account = account, diff --git a/app/src/main/java/com/jerboa/ui/components/settings/lookandfeel/LookAndFeelActivity.kt b/app/src/main/java/com/jerboa/ui/components/settings/lookandfeel/LookAndFeelActivity.kt index df08a5259..e70b8b1f8 100644 --- a/app/src/main/java/com/jerboa/ui/components/settings/lookandfeel/LookAndFeelActivity.kt +++ b/app/src/main/java/com/jerboa/ui/components/settings/lookandfeel/LookAndFeelActivity.kt @@ -10,13 +10,13 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Colorize import androidx.compose.material.icons.outlined.ExitToApp import androidx.compose.material.icons.outlined.FormatSize +import androidx.compose.material.icons.outlined.Forum import androidx.compose.material.icons.outlined.Language import androidx.compose.material.icons.outlined.Palette import androidx.compose.material.icons.outlined.ViewList import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.Scaffold -import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -39,11 +39,13 @@ import com.jerboa.ThemeColor import com.jerboa.ThemeMode import com.jerboa.db.APP_SETTINGS_DEFAULT import com.jerboa.db.entity.AppSettings +import com.jerboa.feat.BackConfirmationMode +import com.jerboa.feat.PostActionbarMode import com.jerboa.getLangPreferenceDropdownEntries import com.jerboa.matchLocale import com.jerboa.model.AppSettingsViewModel +import com.jerboa.ui.components.common.JerboaSnackbarHost import com.jerboa.ui.components.common.SimpleTopAppBar -import com.jerboa.util.BackConfirmationMode @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -87,6 +89,7 @@ fun LookAndFeelActivity( val blurNSFW = rememberBooleanSettingState(settings.blurNSFW) val backConfirmationMode = rememberIntSettingState(settings.backConfirmationMode) val showPostLinkPreviewMode = rememberBooleanSettingState(settings.showPostLinkPreviews) + val postActionbarMode = rememberIntSettingState(settings.postActionbarMode) val snackbarHostState = remember { SnackbarHostState() } @@ -117,12 +120,13 @@ fun LookAndFeelActivity( backConfirmationMode = backConfirmationMode.value, showPostLinkPreviews = showPostLinkPreviewMode.value, markAsReadOnScroll = markAsReadOnScroll.value, + postActionbarMode = postActionbarMode.value, ), ) } Scaffold( - snackbarHost = { SnackbarHost(snackbarHostState) }, + snackbarHost = { JerboaSnackbarHost(snackbarHostState) }, topBar = { SimpleTopAppBar(text = stringResource(R.string.look_and_feel_look_and_feel), onClickBack = onBack) }, @@ -221,6 +225,40 @@ fun LookAndFeelActivity( updateAppSettings() }, ) + SettingsList( + title = { + Text(text = stringResource(R.string.confirm_exit)) + }, + state = backConfirmationMode, + items = BackConfirmationMode.values().map { stringResource(it.resId) }, + onItemSelected = { i, _ -> + backConfirmationMode.value = i + updateAppSettings() + }, + icon = { + Icon( + imageVector = Icons.Outlined.ExitToApp, + contentDescription = null, + ) + }, + ) + SettingsList( + title = { + Text(text = stringResource(R.string.post_actionbar)) + }, + state = postActionbarMode, + items = PostActionbarMode.values().map { stringResource(it.resId) }, + onItemSelected = { i, _ -> + postActionbarMode.value = i + updateAppSettings() + }, + icon = { + Icon( + imageVector = Icons.Outlined.Forum, + contentDescription = null, + ) + }, + ) SettingsCheckbox( state = showBottomNavState, title = { @@ -313,23 +351,6 @@ fun LookAndFeelActivity( }, onCheckedChange = { updateAppSettings() }, ) - SettingsList( - title = { - Text(text = stringResource(R.string.confirm_exit)) - }, - state = backConfirmationMode, - items = BackConfirmationMode.values().map { stringResource(it.resId) }, - onItemSelected = { i, _ -> - backConfirmationMode.value = i - updateAppSettings() - }, - icon = { - Icon( - imageVector = Icons.Outlined.ExitToApp, - contentDescription = null, - ) - }, - ) } }, ) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5fc7135ca..5954366aa 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -386,4 +386,8 @@ Share Enable 2FA Launch 2FA link + Long post actionbar + Short lefthand post actionbar + Short righthand post actionbar + Post actionbar mode diff --git a/app/src/release/generated/baselineProfiles/baseline-prof.txt b/app/src/release/generated/baselineProfiles/baseline-prof.txt index b544157dd..6f8d3947d 100644 --- a/app/src/release/generated/baselineProfiles/baseline-prof.txt +++ b/app/src/release/generated/baselineProfiles/baseline-prof.txt @@ -4228,8 +4228,8 @@ PLandroidx/compose/material/icons/outlined/SmartToyKt;->getSmartToy(Landroidx/co Landroidx/compose/material/icons/outlined/SortKt; HSPLandroidx/compose/material/icons/outlined/SortKt;->()V HPLandroidx/compose/material/icons/outlined/SortKt;->getSort(Landroidx/compose/material/icons/Icons$Outlined;)Landroidx/compose/ui/graphics/vector/ImageVector; -PLandroidx/compose/material/icons/outlined/TextsmsKt;->()V -HPLandroidx/compose/material/icons/outlined/TextsmsKt;->getTextsms(Landroidx/compose/material/icons/Icons$Outlined;)Landroidx/compose/ui/graphics/vector/ImageVector; +PLandroidx/compose/material/icons/outlined/CommentKt;->()V +HPLandroidx/compose/material/icons/outlined/CommentKt;->getComment(Landroidx/compose/material/icons/Icons$Outlined;)Landroidx/compose/ui/graphics/vector/ImageVector; PLandroidx/compose/material/icons/outlined/ViewAgendaKt;->()V PLandroidx/compose/material/icons/outlined/ViewAgendaKt;->getViewAgenda(Landroidx/compose/material/icons/Icons$Outlined;)Landroidx/compose/ui/graphics/vector/ImageVector; Landroidx/compose/material/pullrefresh/ArrowValues;