From dd2b7e22d27596daefff9138185fd55219bdbbeb Mon Sep 17 00:00:00 2001 From: JIULANG <2021662556@qq.com> Date: Sun, 11 Aug 2024 20:52:04 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=96=B0=E5=A2=9E=E7=AC=94=E8=AE=B0=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E9=95=BF=E6=96=87=E6=9C=AC=E6=8A=98=E5=8F=A0/?= =?UTF-8?q?=E5=B1=95=E5=BC=80=E5=8A=9F=E8=83=BD=202.=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=BC=80=E5=A7=8B=E4=B9=A6=E5=86=99=E4=BF=9D=E5=AD=98=E4=BD=93?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 74 +++++---- .../note/data/AppSystemSetManage.kt | 7 +- .../wordsfairy/note/ui/common/AppModifier.kt | 27 +++- .../note/ui/page/create/CreateNoteUI.kt | 23 +-- .../ui/page/detail/NoteDetailNavigation.kt | 5 +- .../note/ui/page/detail/NoteDetailsUI.kt | 3 +- .../ui/page/detail/search/ContentSearchUI.kt | 3 +- .../ui/page/detail/set/ContentSetContract.kt | 6 + .../note/ui/page/detail/set/ContentSetUI.kt | 35 +++-- .../ui/page/detail/set/ContentSetViewModel.kt | 12 +- .../detail/wifgets/NoteContentDropdownMenu.kt | 29 ++-- .../note/ui/page/detail/wifgets/Widgets.kt | 144 +++++++++++++----- .../note/ui/page/search/SearchUI.kt | 3 +- .../wordsfairy/note/ui/page/set/SetPageUI.kt | 13 +- .../com/wordsfairy/note/ui/theme/AppResId.kt | 1 + .../com/wordsfairy/note/ui/theme/Dimens.kt | 1 + .../wordsfairy/note/ui/widgets/AssistChip.kt | 2 +- .../com/wordsfairy/note/ui/widgets/Divider.kt | 13 +- .../wordsfairy/note/ui/widgets/TextContent.kt | 40 ++++- .../note/ui/widgets/dropdown/DropdownMenu.kt | 2 - .../res/drawable-v24/app_ic_arrow_down.xml | 14 ++ buildSrc/src/main/kotlin/AndroidX.kt | 15 +- buildSrc/src/main/kotlin/BuildConfig.kt | 4 +- 23 files changed, 330 insertions(+), 146 deletions(-) create mode 100644 app/src/main/res/drawable-v24/app_ic_arrow_down.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 387ee40..75ee55c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,4 +1,5 @@ import kotlin.collections.* + plugins { id("com.android.application") id("kotlin-android") @@ -13,9 +14,9 @@ android { compileSdk = BuildConfig.compileSdk - defaultConfig{ + defaultConfig { applicationId = BuildConfig.applicationId - minSdk=BuildConfig.minSdkVersion + minSdk = BuildConfig.minSdkVersion targetSdk = BuildConfig.targetSdkVersion versionCode = BuildConfig.versionCode versionName = BuildConfig.versionName @@ -47,7 +48,6 @@ android { buildTypes { debug { isMinifyEnabled = false - isZipAlignEnabled = false isShrinkResources = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), @@ -58,13 +58,11 @@ android { release { isMinifyEnabled = true - isZipAlignEnabled = true isShrinkResources = true isDebuggable = false //是否debug - isJniDebuggable = false // 是否打开jniDebuggable开关 - isZipAlignEnabled = true //压缩优化 + isJniDebuggable = false // 是否打开jniDebuggable开关 - proguardFiles ( + proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) @@ -96,47 +94,47 @@ android { dependencies { - implementation (AndroidX.coreKtx) - implementation (AndroidX.coresplashscreen) - implementation (AndroidX.Lifecycle.runtimeKtx) - implementation (AndroidX.Compose.activity) - implementation (AndroidX.Compose.ui) - implementation (AndroidX.Compose.tooling_preview) - implementation (AndroidX.Compose.material3) - implementation (AndroidX.Compose.runtime) - implementation (AndroidX.Compose.ui_util) - implementation (AndroidX.Compose.Accompanist.insets) - implementation (AndroidX.Compose.Accompanist.placeholder) - implementation (AndroidX.Compose.Accompanist.systemuicontroller) - implementation (AndroidX.Paging.compose) - implementation (AndroidX.Paging.runtimeKtx) - implementation (AndroidX.Navigation.compose) - implementation (AndroidX.Navigation.uiKtx) - implementation (AndroidX.Navigation.animation) - implementation (AndroidX.Work.runtime) - implementation (AndroidX.Work.runtime_ktx) - implementation (AndroidX.multidex) - implementation (AndroidX.Documentfile) + implementation(AndroidX.coreKtx) + implementation(AndroidX.coresplashscreen) + implementation(AndroidX.Lifecycle.runtimeKtx) + implementation(AndroidX.Compose.activity) + implementation(AndroidX.Compose.ui) + implementation(AndroidX.Compose.tooling_preview) + implementation(AndroidX.Compose.material3) + implementation(AndroidX.Compose.runtime) + implementation(AndroidX.Compose.ui_util) + implementation(AndroidX.Compose.Accompanist.insets) + implementation(AndroidX.Compose.Accompanist.placeholder) + implementation(AndroidX.Compose.Accompanist.systemuicontroller) + implementation(AndroidX.Paging.compose) + implementation(AndroidX.Paging.runtimeKtx) + implementation(AndroidX.Navigation.compose) + implementation(AndroidX.Navigation.uiKtx) + implementation(AndroidX.Navigation.animation) + implementation(AndroidX.Work.runtime) + implementation(AndroidX.Work.runtime_ktx) + implementation(AndroidX.multidex) + implementation(AndroidX.Documentfile) //Hilt - implementation (AndroidX.Hilt.common) - kapt (AndroidX.Hilt.compiler) - implementation (AndroidX.Hilt.navigation_compose) + implementation(AndroidX.Hilt.common) + kapt(AndroidX.Hilt.compiler) + implementation(AndroidX.Hilt.navigation_compose) //Room implementation(AndroidX.Room.runtime) kapt(AndroidX.Room.compiler) implementation(AndroidX.Room.ktx) - // debugImplementation(ThirdPart.leakcanary) + // debugImplementation(ThirdPart.leakcanary) implementation(project(Lib.base)) implementation(project(Lib.common)) - debugImplementation (AndroidX.Compose.uiTooling) - debugImplementation (AndroidX.Compose.ui_test_manifest) + debugImplementation(AndroidX.Compose.uiTooling) + debugImplementation(AndroidX.Compose.ui_test_manifest) - testImplementation (Testing.junit) - androidTestImplementation (Testing.androidJunit) - androidTestImplementation (Testing.espresso) - androidTestImplementation (Testing.compose_ui_test) + testImplementation(Testing.junit) + androidTestImplementation(Testing.androidJunit) + androidTestImplementation(Testing.espresso) + androidTestImplementation(Testing.compose_ui_test) } \ No newline at end of file diff --git a/app/src/main/kotlin/com/wordsfairy/note/data/AppSystemSetManage.kt b/app/src/main/kotlin/com/wordsfairy/note/data/AppSystemSetManage.kt index 220123c..e755e8e 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/data/AppSystemSetManage.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/data/AppSystemSetManage.kt @@ -60,7 +60,12 @@ object AppSystemSetManage { var jumpToWeChat: Boolean get() = DataStoreUtils.readBooleanData(JumpToWeChat, false) set(value) = DataStoreUtils.saveSyncBooleanData(JumpToWeChat, value = value) - + /** + * 长文本自动折叠 默认开启 + */ + var longTextAutoFold: Boolean + get() = DataStoreUtils.readBooleanData("long_text_auto_fold", true) + set(value) = DataStoreUtils.saveSyncBooleanData("long_text_auto_fold", value = value) /** * 首页索引 */ diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/common/AppModifier.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/common/AppModifier.kt index 252ad97..423afb5 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/common/AppModifier.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/common/AppModifier.kt @@ -1,8 +1,7 @@ package com.wordsfairy.note.ui.common +import android.annotation.SuppressLint import android.app.Activity -import android.content.Context -import android.view.inputmethod.InputMethodManager import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.interaction.MutableInteractionSource @@ -14,9 +13,7 @@ import androidx.compose.ui.geometry.Offset import androidx.compose.ui.hapticfeedback.HapticFeedback import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.semantics.Role -import androidx.core.content.ContextCompat.getSystemService import com.wordsfairy.base.tools.hideKeyboard import com.wordsfairy.note.MainActivity @@ -29,6 +26,7 @@ const val VIEW_CLICK_INTERVAL_TIME = 800 /** * 防止重复点击(有的人可能会手抖连点两次,造成奇怪的bug) */ +@SuppressLint("ModifierFactoryUnreferencedReceiver") @Composable inline fun Modifier.click( time: Int = VIEW_CLICK_INTERVAL_TIME, @@ -113,7 +111,7 @@ fun Modifier.autoCloseKeyboard(activity: Activity = MainActivity.CONTEXT): Modif ) } - +//不会触发水波纹之类的效果 @Composable fun Modifier.clickableNoIndication(focusManager: FocusManager) = this.clickable( @@ -126,6 +124,25 @@ fun Modifier.clickableNoIndication(focusManager: FocusManager) = MutableInteractionSource() } ) +/** + * 点击时,自动隐藏键盘 + * 同时解决 输入框 换行时,输入法消失的问题 + */ +@Composable +fun Modifier.onPressNoIndication(focusManager: FocusManager) = + this.pointerInput(Unit) { + detectTapGestures( + onDoubleTap = { + }, + onLongPress = { + }, + onPress = { + }, + onTap = { + focusManager.clearFocus() + } + ) + } fun HapticFeedback.vibration() { this.performHapticFeedback(HapticFeedbackType.TextHandleMove) diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/page/create/CreateNoteUI.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/page/create/CreateNoteUI.kt index dce9920..78952bf 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/page/create/CreateNoteUI.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/page/create/CreateNoteUI.kt @@ -39,6 +39,7 @@ import com.wordsfairy.note.ext.flow.noteStartWith import com.wordsfairy.note.ext.flowbus.observeEvent import com.wordsfairy.note.ext.flowbus.postEventValue import com.wordsfairy.note.ui.common.clickableNoIndication +import com.wordsfairy.note.ui.common.onPressNoIndication import com.wordsfairy.note.ui.common.vibration import com.wordsfairy.note.ui.theme.AppColor @@ -165,7 +166,7 @@ fun CreateNoteUI( .fillMaxSize() .blur(if (isShowAddFolderDialog) 6.dp else 0.dp) .background(WordsFairyTheme.colors.whiteBackground) - .clickableNoIndication(focusManager) + .onPressNoIndication(focusManager) .systemBarsPadding() ) { Row( @@ -284,16 +285,9 @@ fun NoteContentEditView( Column( Modifier.padding(horizontal = 6.dp) ) { - Spacer(Modifier.height(6.dp)) + var appendTextValue by remember { mutableStateOf("") } - /** 笔记输入框 */ - CreateNoteContentEditView( - text = viewState.noteContent, - addendText = appendTextValue, - placeholder = "开始书学" - ) { - intentChannel.trySend(ViewIntent.NoteContentChanged(it)) - } + Row(Modifier.fillMaxWidth()) { Spacer(Modifier.width(6.dp)) if (viewState.noteEntity != null) { @@ -313,6 +307,15 @@ fun NoteContentEditView( } Spacer(Modifier.width(6.dp)) } + /** 笔记输入框 */ + CreateNoteContentEditView( + text = viewState.noteContent, + addendText = appendTextValue, + placeholder = "开始书学" + ) { + intentChannel.trySend(ViewIntent.NoteContentChanged(it)) + } + Spacer(Modifier.height(6.dp)) } } } diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/NoteDetailNavigation.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/NoteDetailNavigation.kt index 717d11e..e075b5c 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/NoteDetailNavigation.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/NoteDetailNavigation.kt @@ -16,6 +16,7 @@ import com.wordsfairy.note.constants.GlobalData import com.wordsfairy.note.constants.NavigateRouter import com.wordsfairy.note.data.entity.NoteEntity import com.wordsfairy.note.ext.flowbus.postEventValue +import kotlinx.coroutines.ExperimentalCoroutinesApi import java.net.URLDecoder @@ -26,6 +27,8 @@ fun ColumnScope.toNoteDetailsUI(it: NoteEntity, isSearch: Boolean) { GlobalData.noteDetailsNoteEntity = it postEventValue(EventBus.NavController, NavigateRouter.DetailPage.Detail + "/$isSearch") } + +@OptIn(ExperimentalCoroutinesApi::class) @ExperimentalAnimationApi fun NavGraphBuilder.noteDetailScreen( navController: NavHostController @@ -44,6 +47,6 @@ fun NavGraphBuilder.noteDetailScreen( val isSearch = backStackEntry.arguments?.getBoolean(Detail_Is_Search) NoteDetailsUI(onBack = { navController.navigateUp() - }, isSearch?:false) + }, isSearch ?: false) } } diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/NoteDetailsUI.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/NoteDetailsUI.kt index afd3551..ace4c49 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/NoteDetailsUI.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/NoteDetailsUI.kt @@ -27,6 +27,7 @@ import com.wordsfairy.note.ext.coreui.rememberFlowWithLifecycle import com.wordsfairy.note.ext.flow.noteStartWith import com.wordsfairy.note.ext.flowbus.postEventValue import com.wordsfairy.note.ui.common.clickableNoIndication +import com.wordsfairy.note.ui.common.onPressNoIndication import com.wordsfairy.note.ui.common.vibration import com.wordsfairy.note.ui.page.create.ChooseClassifyButton @@ -115,7 +116,7 @@ fun NoteDetailsUI( .fillMaxSize() .blur(if (isShowContentModifierDialog) 6.dp else 0.dp) .background(WordsFairyTheme.colors.whiteBackground) - .clickableNoIndication(focusManager) //点击无涟漪效果 + .onPressNoIndication(focusManager) //点击无涟漪效果 .systemBarsPadding() ) { Row( diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/search/ContentSearchUI.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/search/ContentSearchUI.kt index cc4b676..645c0a2 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/search/ContentSearchUI.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/search/ContentSearchUI.kt @@ -24,6 +24,7 @@ import com.wordsfairy.note.ext.coreui.rememberFlowWithLifecycle import com.wordsfairy.note.ext.flow.noteStartWith import com.wordsfairy.note.ui.common.autoCloseKeyboard import com.wordsfairy.note.ui.common.clickableNoIndication +import com.wordsfairy.note.ui.common.onPressNoIndication import com.wordsfairy.note.ui.theme.AppResId import com.wordsfairy.note.ui.widgets.SearchEditView import kotlinx.coroutines.channels.Channel @@ -80,7 +81,7 @@ fun ContentSearchUI( Column( Modifier .fillMaxSize() - .clickableNoIndication(focusManager), + .onPressNoIndication(focusManager), horizontalAlignment = Alignment.CenterHorizontally ) { SearchEditView( diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/set/ContentSetContract.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/set/ContentSetContract.kt index 17252b4..7374147 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/set/ContentSetContract.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/set/ContentSetContract.kt @@ -16,6 +16,8 @@ sealed interface ViewIntent : MviIntent { object Initial : ViewIntent data class SearchEngines(val url: String) : ViewIntent data class CopyJumpToWeChat(val jump: Boolean) : ViewIntent +// 长文本自动折叠 + data class LongTextAutoFold(val fold: Boolean) : ViewIntent object RecycleNote : ViewIntent object RecycleNoteContents : ViewIntent data class ShowDialog(val dialogDataBean: DialogDataBean) : ViewIntent @@ -25,6 +27,7 @@ data class ViewState( val isLoading: Boolean, val currentUrl: String, val jumpToWeChat: Boolean, + val longTextAutoFold: Boolean, val dialogDataBean: DialogDataBean ) : MviViewState { companion object { @@ -32,6 +35,7 @@ data class ViewState( isLoading = true, currentUrl = AppSystemSetManage.searchEngines, jumpToWeChat = AppSystemSetManage.jumpToWeChat, + longTextAutoFold = AppSystemSetManage.longTextAutoFold, dialogDataBean = DialogDataBean.create(), ) } @@ -53,12 +57,14 @@ internal sealed interface PartialChange { is Dialog -> vs is SetSearchEngines -> vs.copy(currentUrl = url) is CopyJumpToWeChat -> vs.copy(jumpToWeChat = jump) + is LongTextAutoFold -> vs.copy(longTextAutoFold = fold) is ShowDialog -> vs.copy(dialogDataBean = dialogDataBean) } } object Init : UI() data class SetSearchEngines(val url:String) : UI() data class CopyJumpToWeChat(val jump:Boolean) : UI() + data class LongTextAutoFold(val fold:Boolean) : UI() data class ShowDialog(val dialogDataBean :DialogDataBean) : UI() data class Dialog(val dialogDataBean :DialogDataBean) : UI() } diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/set/ContentSetUI.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/set/ContentSetUI.kt index d002c04..fa1add1 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/set/ContentSetUI.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/set/ContentSetUI.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.KeyboardArrowLeft import androidx.compose.material3.Divider +import androidx.compose.material3.HorizontalDivider import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -152,21 +153,19 @@ fun ContentSetUI( ImmerseCard(Modifier.padding(12.dp)) { Column { - AnimateContentIcon("数据批量导出/导入") { - CommonItemIcon("导入 [txt]") { - txtSelectorLauncher.launch(txtSelectorIntent) - } - CommonItemIcon("导出(即将开发)") { - ToastModel("即将开发", ToastModel.Type.Normal).showToast() - } - } - ItemDividerSetUI() + CommonItemSwitch( "复制后转跳微信", viewState.jumpToWeChat ) { jump -> intentChannel.trySend(ViewIntent.CopyJumpToWeChat(jump)) } + CommonItemSwitch( + "长文本自动折叠", + viewState.longTextAutoFold + ) { jump -> + intentChannel.trySend(ViewIntent.LongTextAutoFold(jump)) + } ItemDividerSetUI() AnimateContentIcon("搜索引擎") { @@ -190,6 +189,18 @@ fun ContentSetUI( intentChannel.trySend(ViewIntent.SearchEngines(google)) } } + } + } + ImmerseCard(Modifier.padding(12.dp)) { + Column { + AnimateContentIcon("数据批量导出/导入") { + CommonItemIcon("导入 [txt]") { + txtSelectorLauncher.launch(txtSelectorIntent) + } + CommonItemIcon("导出(即将开发)") { + ToastModel("即将开发", ToastModel.Type.Normal).showToast() + } + } ItemDividerSetUI() AnimateContentIcon("清除数据") { @@ -252,11 +263,11 @@ fun ContentSetUI( */ @Composable private fun ItemDividerSetUI() { - Divider( + HorizontalDivider( Modifier .fillMaxWidth() .padding(horizontal = 20.dp), - color = WordsFairyTheme.colors.textSecondary, - thickness = 0.3.dp + thickness = 0.3.dp, + color = WordsFairyTheme.colors.textSecondary ) } diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/set/ContentSetViewModel.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/set/ContentSetViewModel.kt index 41a5564..fa4c6ad 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/set/ContentSetViewModel.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/set/ContentSetViewModel.kt @@ -85,13 +85,20 @@ class ContentSetViewModel @Inject internal constructor( /** 复制之后转跳微信 */ val jumpToWeChatFlow = filterIsInstance() - .log("[SearchEngines]") + .log("[JumpToWeChatFlow]") .map { val jump =it.jump AppSystemSetManage.jumpToWeChat =jump PartialChange.UI.CopyJumpToWeChat(jump) }.distinctUntilChanged() - + /** 长文本自动折叠 */ + val longTextAutoFoldFlow = filterIsInstance() + .log("[longTextAutoFoldFlow]") + .map { + val fold =it.fold + AppSystemSetManage.longTextAutoFold =fold + PartialChange.UI.LongTextAutoFold(fold) + }.distinctUntilChanged() /** 回收笔记实体 */ val recycleNoteFlow = filterIsInstance() .log("[回收笔记实体]") @@ -120,6 +127,7 @@ class ContentSetViewModel @Inject internal constructor( return merge( initFlow,searchEnginesFlow, jumpToWeChatFlow, + longTextAutoFoldFlow, recycleNoteFlow, recycleNoteContentsFlow, showDialogFlow diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/wifgets/NoteContentDropdownMenu.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/wifgets/NoteContentDropdownMenu.kt index a4d5c9d..32ca5fa 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/wifgets/NoteContentDropdownMenu.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/wifgets/NoteContentDropdownMenu.kt @@ -31,11 +31,12 @@ fun NoteContentDropdownMenu( onClick: (Int) -> Unit, ) { val list = listOf( - ContextItem(1,"",AppResId.Drawable.Search), - ContextItem(2,"复制",AppResId.Drawable.Copy), - ContextItem(3,"转发",AppResId.Drawable.Forward), - ContextItem(4,"删除",AppResId.Drawable.Delete), - ContextItem(5,"修改",AppResId.Drawable.Modify)) + ContextItem(1, "", AppResId.Drawable.Search), + ContextItem(2, "复制", AppResId.Drawable.Copy), + ContextItem(3, "转发", AppResId.Drawable.Forward), + ContextItem(4, "删除", AppResId.Drawable.Delete), + ContextItem(5, "修改", AppResId.Drawable.Modify) + ) DropdownMenu( expanded = expanded, @@ -43,7 +44,7 @@ fun NoteContentDropdownMenu( offset = DpOffset(9.dp, 0.dp), onDismissRequest = onDismiss, ) { - Row(Modifier.padding(1.dp),verticalAlignment = Alignment.CenterVertically) { + Row(Modifier.padding(1.dp), verticalAlignment = Alignment.CenterVertically) { list.forEachIndexed { index, item -> val haveName = item.name.isNotEmpty() @@ -62,12 +63,18 @@ fun NoteContentDropdownMenu( Image( painter = painterResource(id = item.icon), contentDescription = item.name, - Modifier.size(if (haveName) 19.dp else 26.dp), - colorFilter= ColorFilter.tint(color = WordsFairyTheme.colors.iconBlack) + Modifier + .padding(3.dp) + .size(if (haveName) 19.dp else 26.dp), + colorFilter = ColorFilter.tint(color = WordsFairyTheme.colors.iconBlack) ) - if (haveName){ + if (haveName) { Spacer(Modifier.height(2.dp)) - Title(item.name, color = WordsFairyTheme.colors.textPrimary, fontSize = 13.sp) + Title( + item.name, + color = WordsFairyTheme.colors.textPrimary, + fontSize = 13.sp + ) } } } @@ -76,4 +83,4 @@ fun NoteContentDropdownMenu( } -private data class ContextItem(val id: Int,val name: String,val icon:Int) \ No newline at end of file +private data class ContextItem(val id: Int, val name: String, val icon: Int) \ No newline at end of file diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/wifgets/Widgets.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/wifgets/Widgets.kt index dfcf457..2d8cb3b 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/wifgets/Widgets.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/page/detail/wifgets/Widgets.kt @@ -4,7 +4,9 @@ import android.os.Parcelable import androidx.compose.animation.* import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.animateDpAsState +import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed @@ -17,6 +19,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.rotate import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.hapticfeedback.HapticFeedbackType @@ -154,22 +157,9 @@ fun ContentEditView( ) { var appendTextValue by remember { mutableStateOf("") } /** 笔记输入框 */ - Spacer(Modifier.height(6.dp)) - CreateNoteContentEditView( - text = noteContent, - addendText = appendTextValue, - placeholder = if (isSearch) "搜索笔记" else "开始书学", - isAutoFocused = false - ) { - if (isSearch) { - onSearch.invoke(it) - } else { - onContentChange.invoke(it) - } - } Row(Modifier.fillMaxWidth()) { if (isSearch) { - NoteTag(string = "搜索模式", Modifier.align(Alignment.Bottom)) + NoteTag(string = "搜索模式", Modifier.align(Alignment.CenterVertically)) } Spacer(Modifier.weight(1f)) SmallButton("剪贴板", color = AppColor.blue) { @@ -185,6 +175,19 @@ fun ContentEditView( } Spacer(Modifier.width(6.dp)) } + CreateNoteContentEditView( + text = noteContent, + addendText = appendTextValue, + placeholder = if (isSearch) "搜索笔记" else "开始书学", + isAutoFocused = false + ) { + if (isSearch) { + onSearch.invoke(it) + } else { + onContentChange.invoke(it) + } + } + Spacer(Modifier.height(6.dp)) } } } @@ -199,7 +202,7 @@ fun ContentList( onDelete: (NoteContentEntity) -> Unit, onModify: (NoteContentEntity) -> Unit, ) { - + val autoFold = AppSystemSetManage.longTextAutoFold var showProgress by remember { mutableStateOf(false) } LaunchedEffect(Unit) { delay(460) @@ -258,6 +261,7 @@ fun ContentList( } } val deletedRouteList = remember { mutableStateListOf() } + LazyColumn( state = state.listState, modifier = Modifier.reorderable(state) @@ -287,7 +291,8 @@ fun ContentList( ) ) ) { - val elevation = animateDpAsState(if (isDragging) 16.dp else 0.dp, + val elevation = animateDpAsState( + if (isDragging) 16.dp else 0.dp, label = "elevation" ) ImmerseCard( @@ -302,12 +307,15 @@ fun ContentList( shape = RoundedCornerShape(6.dp), backgroundColor = WordsFairyTheme.colors.itemImmerse, ) { - ContentLayout(item, state, onDelete = { id -> - deletedRouteList.add(id) - onDelete.invoke(noteContentsCache[index]) - }, onModify = { - onModify.invoke(noteContentsCache[index]) - }) + ContentLayout(item = item, + state = state, + autoFold = autoFold, + onDelete = { id -> + deletedRouteList.add(id) + onDelete.invoke(noteContentsCache[index]) + }, onModify = { + onModify.invoke(noteContentsCache[index]) + }) } } } @@ -327,6 +335,7 @@ fun SearchResultList( onModify: (NoteContentEntity) -> Unit, ) { var data by remember { mutableStateOf>(mutableListOf()) } + val autoFold = AppSystemSetManage.longTextAutoFold val isVisible = noteContents.isNotEmpty() if (isVisible) { @@ -365,12 +374,14 @@ fun SearchResultList( shape = RoundedCornerShape(6.dp), backgroundColor = WordsFairyTheme.colors.itemImmerse, ) { - ContentLayout(item, null, onDelete = { id -> - deletedRouteList.add(id) - onDelete.invoke(noteContents[index]) - }, onModify = { - onModify.invoke(noteContents[index]) - }) + ContentLayout(item = item, state = null, + autoFold = autoFold, + onDelete = { id -> + deletedRouteList.add(id) + onDelete.invoke(noteContents[index]) + }, onModify = { + onModify.invoke(noteContents[index]) + }) } } } @@ -381,26 +392,87 @@ fun SearchResultList( @Composable private fun ContentLayout( - item: NoteContentItem, state: ReorderableLazyListState?, + item: NoteContentItem, + state: ReorderableLazyListState?, + autoFold: Boolean = true, onDelete: (Long) -> Unit, onModify: () -> Unit, ) { var expanded by remember { mutableStateOf(false) } + val context = LocalContext.current + val scope = rememberCoroutineScope() + val feedback = LocalHapticFeedback.current val clipboardManager: ClipboardManager = LocalClipboardManager.current + //折叠 + var isFold by remember { mutableStateOf(autoFold) } + //超出6行 + var isExceed by remember { mutableStateOf(false) } + // 用于延迟更新状态 + val rotationValue: Float by animateFloatAsState( + if (isFold) 0f else 180f, + label = "isFoldRotation", + animationSpec = tween( + durationMillis = 399, + easing = LinearEasing + ) + ) Box( Modifier .click { expanded = true } - .padding(start = 9.dp, top = 1.dp, bottom = 1.dp, end = 3.dp) + .padding(start = 9.dp, top = 1.dp, bottom = 1.dp, end = 6.dp) .fillMaxWidth(), contentAlignment = Alignment.CenterStart ) { - TextNoteContent( - text = item.content, - Modifier.padding(vertical = 9.dp), - color = WordsFairyTheme.colors.textPrimary - ) + Column( + modifier = Modifier + .wrapContentSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer(modifier = Modifier.height(9.dp)) + TextNoteContent( + text = item.content, + modifier = Modifier + .fillMaxWidth(), + color = WordsFairyTheme.colors.textPrimary, + isFold = isFold, + onTextLayout = { result -> + // 更新 isExceed 状态 如果折叠并且实际行数超过6行,则设置 isExceed 为 true + scope.launch { + if (isFold && (result.didOverflowWidth || result.didOverflowHeight)) { + isExceed = true + } else if (!isFold) { + isExceed = result.lineCount > 6 + } + } + } + ) + + if (isExceed && autoFold) { + Box( + modifier = Modifier + .fillMaxWidth() + .click { + isFold = !isFold + feedback.vibration() + }, + ) { + Image( + painter = painterResource(id = AppResId.Drawable.Arrow_Down), + contentDescription = "right", + Modifier + .size(24.dp) + .rotate(rotationValue) + .align(Alignment.Center) + ) + } + } else { + Spacer(modifier = Modifier.height(9.dp)) + } + + } + if (state != null) { IconButtonWithHiddenIcon( imageVector = Icons.Rounded.Menu, @@ -409,7 +481,6 @@ private fun ContentLayout( .align(Alignment.TopEnd) ) } - NoteContentDropdownMenu(expanded, onDismiss = { expanded = false }) { @@ -444,6 +515,7 @@ private fun ContentLayout( } } } + } } diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/page/search/SearchUI.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/page/search/SearchUI.kt index 67a8005..cc344d2 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/page/search/SearchUI.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/page/search/SearchUI.kt @@ -18,6 +18,7 @@ import com.wordsfairy.note.ext.coreui.rememberFlowWithLifecycle import com.wordsfairy.note.ext.flow.noteStartWith import com.wordsfairy.note.ext.flowbus.postEventValue import com.wordsfairy.note.ui.common.clickableNoIndication +import com.wordsfairy.note.ui.common.onPressNoIndication import com.wordsfairy.note.ui.page.detail.toNoteDetailsUI import com.wordsfairy.note.ui.page.search.widgets.ResultList import com.wordsfairy.note.ui.page.search.widgets.SearchEdit @@ -73,7 +74,7 @@ fun SearchUI( Modifier .fillMaxSize() .statusBarsPadding() - .clickableNoIndication(focusManager), + .onPressNoIndication(focusManager), horizontalAlignment = Alignment.CenterHorizontally ) { SearchEdit(viewState.keyword){ diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/page/set/SetPageUI.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/page/set/SetPageUI.kt index 7fab602..fadb21a 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/page/set/SetPageUI.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/page/set/SetPageUI.kt @@ -190,10 +190,18 @@ fun SetPageUI( AnimateContentIcon("联系作者") { CommonTextItem( "微信", - "WordFairy", + "ISSWENJIE", horizontalPadding = 0.dp ){ - clipboardManager.setText(AnnotatedString("WordFairy")) + clipboardManager.setText(AnnotatedString("ISSWENJIE")) + ToastModel("已复制至剪贴板", ToastModel.Type.Normal).showToast() + } + CommonTextItem( + "微信公众号", + "九狼", + horizontalPadding = 0.dp + ){ + clipboardManager.setText(AnnotatedString("九狼")) ToastModel("已复制至剪贴板", ToastModel.Type.Normal).showToast() } CommonTextItem( @@ -203,7 +211,6 @@ fun SetPageUI( ){ clipboardManager.setText(AnnotatedString("2021662556")) ToastModel("已复制至剪贴板", ToastModel.Type.Normal).showToast() - } CommonTextItem( "博客", diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/theme/AppResId.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/theme/AppResId.kt index b6ed809..ff018a0 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/theme/AppResId.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/theme/AppResId.kt @@ -20,6 +20,7 @@ object AppResId { var ReadMode = R.drawable.app_ic_read_mode var Modify = R.drawable.app_ic_modify var Arrow_Right = R.drawable.app_ic_arrow_right + var Arrow_Down = R.drawable.app_ic_arrow_down var Correct = R.drawable.app_ic_correct } object Mipmap { diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/theme/Dimens.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/theme/Dimens.kt index 663174b..dfb08df 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/theme/Dimens.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/theme/Dimens.kt @@ -20,6 +20,7 @@ val H4 = 20.sp //普通标题 val H5 = 16.sp //内容文本 val H6 = 13.sp //普通文字尺寸 val H7 = 12.sp //提示语尺寸 +val H8 = 10.sp //提示语尺寸 val ToolBarTitleSize = 18.sp diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/AssistChip.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/AssistChip.kt index bbe5dfd..0ad9c95 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/AssistChip.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/AssistChip.kt @@ -21,7 +21,7 @@ fun NoteTag(string: String, modifier: Modifier = Modifier, ) { Text( text = string, - modifier = modifier.background(AppColor.themeAccent, RoundedCornerShape(6.dp)).padding(2.dp), + modifier = modifier.background(AppColor.themeAccent, RoundedCornerShape(6.dp)).padding(horizontal = 5.dp), color = AppColor.themeColor, fontSize = 12.sp ) diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/Divider.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/Divider.kt index 81c3968..f4895e2 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/Divider.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/Divider.kt @@ -2,9 +2,10 @@ package com.wordsfairy.note.ui.widgets import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Divider +import androidx.compose.material3.HorizontalDivider import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.wordsfairy.note.ui.theme.WordsFairyTheme @@ -18,12 +19,12 @@ import com.wordsfairy.note.ui.theme.WordsFairyTheme * 分割线 */ @Composable -fun ItemDivider() { - Divider( +fun ItemDivider(hPadding: Dp = 20.dp) { + HorizontalDivider( Modifier .fillMaxWidth() - .padding(horizontal = 20.dp), - color = WordsFairyTheme.colors.textSecondary, - thickness = 0.3.dp + .padding(horizontal = hPadding), + thickness = 0.3.dp, + color = WordsFairyTheme.colors.textSecondary ) } \ No newline at end of file diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/TextContent.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/TextContent.kt index e9bf1bd..a70a598 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/TextContent.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/TextContent.kt @@ -7,6 +7,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextLayoutResult import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -29,8 +30,11 @@ fun TextNoteContent( text: String, modifier: Modifier = Modifier, color: Color = WordsFairyTheme.colors.textPrimary, - textAlign: TextAlign = TextAlign.Start + textAlign: TextAlign = TextAlign.Start, + isFold: Boolean = false, + onTextLayout: ((TextLayoutResult) -> Unit)? = null, ) { + // SelectionContainer { // Text( // text = text, @@ -45,7 +49,10 @@ fun TextNoteContent( modifier = modifier, fontSize = 17.sp, color = color, - textAlign = textAlign + textAlign = textAlign, + onTextLayout = onTextLayout, + maxLines = if (isFold) 6 else Int.MAX_VALUE, // 限制最多显示3行 + overflow = TextOverflow.Ellipsis // 当文本超出时显示省 ) } @@ -105,15 +112,18 @@ fun MiniText( } @Composable -fun BigTitle( title: String, - modifier: Modifier = Modifier,) { +fun BigTitle( + title: String, + modifier: Modifier = Modifier, +) { Title( title = title, modifier = modifier, fontSize = H3, - color = WordsFairyTheme.colors.textPrimary + color = WordsFairyTheme.colors.textPrimary ) } + @Composable fun TextSecondary( text: String, @@ -127,7 +137,8 @@ fun TextSecondary( text = text, modifier = modifier.placeholder( visible = isLoading, - ), + + ), fontSize = 15.sp, color = color, maxLines = maxLines, @@ -136,6 +147,23 @@ fun TextSecondary( ) } +@Composable +fun MiniTimeText( + text: String, + modifier: Modifier = Modifier, + fontSize: TextUnit = H8, + color: Color = WordsFairyTheme.colors.textSecondary, +) { + Text( + text = text, + modifier = modifier, + fontWeight = FontWeight.Normal, + fontSize = fontSize, + color = color, + maxLines = 1, + ) +} + @Composable fun AnnotatedText( text: AnnotatedString, diff --git a/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/dropdown/DropdownMenu.kt b/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/dropdown/DropdownMenu.kt index ac11c87..506484a 100644 --- a/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/dropdown/DropdownMenu.kt +++ b/app/src/main/kotlin/com/wordsfairy/note/ui/widgets/dropdown/DropdownMenu.kt @@ -18,7 +18,6 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.blur import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.tooling.preview.Preview @@ -30,7 +29,6 @@ import com.wordsfairy.note.data.entity.NoteFolderEntity import com.wordsfairy.note.ui.common.click import com.wordsfairy.note.ui.theme.AppColor import com.wordsfairy.note.ui.theme.WordsFairyTheme -import com.wordsfairy.note.ui.widgets.ImmerseCard import com.wordsfairy.note.ui.widgets.Title diff --git a/app/src/main/res/drawable-v24/app_ic_arrow_down.xml b/app/src/main/res/drawable-v24/app_ic_arrow_down.xml new file mode 100644 index 0000000..4261a57 --- /dev/null +++ b/app/src/main/res/drawable-v24/app_ic_arrow_down.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/AndroidX.kt b/buildSrc/src/main/kotlin/AndroidX.kt index b91c2f2..130edea 100644 --- a/buildSrc/src/main/kotlin/AndroidX.kt +++ b/buildSrc/src/main/kotlin/AndroidX.kt @@ -20,7 +20,7 @@ object AndroidX { const val coresplashscreen = "androidx.core:core-splashscreen:1.0.0" object Compose { - private const val version = "1.6.7" + private const val version = "1.6.8" const val ui = "androidx.compose.ui:ui:$version" const val tooling_preview = "androidx.compose.ui:ui-tooling-preview:$version" @@ -28,19 +28,19 @@ object AndroidX { const val uiTooling = "androidx.compose.ui:ui-tooling:$version" const val ui_util = "androidx.compose.ui:ui-util:$version" const val material3 = "androidx.compose.material3:material3:1.2.1" - const val activity = "androidx.activity:activity-compose:1.9.0" + const val activity = "androidx.activity:activity-compose:1.9.1" const val runtime = "androidx.compose.runtime:runtime:$version" const val ui_test_manifest = "androidx.compose.ui:ui-test-manifest:1.3.3" object Accompanist { - private const val Version = "0.34.0" + private const val version = "0.34.0" const val systemuicontroller = - "com.google.accompanist:accompanist-systemuicontroller:$Version" + "com.google.accompanist:accompanist-systemuicontroller:$version" const val insets = "com.google.accompanist:accompanist-insets:0.30.1" const val placeholder = - "com.google.accompanist:accompanist-placeholder-material:$Version" + "com.google.accompanist:accompanist-placeholder-material:$version" } //更多compose工具集查看 accompanist项目#https://github.com/google/accompanist } @@ -50,8 +50,10 @@ object AndroidX { private const val version = "3.2.1" const val runtime = "androidx.paging:paging-runtime:$version" const val runtimeKtx = "androidx.paging:paging-runtime-ktx:$version" + // optional - Guava ListenableFuture support const val guava = "androidx.paging:paging-guava:$version" + // optional - Jetpack Compose integration const val compose = "androidx.paging:paging-compose:$version" } @@ -141,7 +143,7 @@ object AndroidX { object Room { - private const val version = "2.5.1" + private const val version = "2.6.1" const val runtime = "androidx.room:room-runtime:$version" @@ -181,7 +183,6 @@ object AndroidX { } - const val Documentfile = "androidx.documentfile:documentfile:1.0.1" /** diff --git a/buildSrc/src/main/kotlin/BuildConfig.kt b/buildSrc/src/main/kotlin/BuildConfig.kt index 28e9c13..f1fba26 100644 --- a/buildSrc/src/main/kotlin/BuildConfig.kt +++ b/buildSrc/src/main/kotlin/BuildConfig.kt @@ -10,8 +10,8 @@ object BuildConfig { const val applicationId ="com.wordsfairy.note" const val testInstrumentationRunner="androidx.test.runner.AndroidJUnitRunner" - var versionName = "1.6.0" - var versionCode = 8 + var versionName = "1.6.1" + var versionCode = 9 } object SigningConfigs{ /** 密钥别名 */