From 50fbea3aa99162bee12918d0bee2294c550aa8e9 Mon Sep 17 00:00:00 2001 From: lsakee Date: Mon, 4 Nov 2024 21:52:39 +0900 Subject: [PATCH 01/10] feat:save link progress --- .../components/button/LinkMindBlockButton.kt | 9 ++++++ .../main/res/layout/button_block_linkmind.xml | 28 ++++++++++++++----- .../SaveLinkSetClipFragment.kt | 5 +++- .../ui/savelinksetclip/SetLinkViewModel.kt | 3 +- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/core/designsystem/src/main/java/designsystem/components/button/LinkMindBlockButton.kt b/core/designsystem/src/main/java/designsystem/components/button/LinkMindBlockButton.kt index a3321f6a..b7dce3d7 100644 --- a/core/designsystem/src/main/java/designsystem/components/button/LinkMindBlockButton.kt +++ b/core/designsystem/src/main/java/designsystem/components/button/LinkMindBlockButton.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater +import android.view.View import android.widget.FrameLayout import androidx.core.content.ContextCompat import designsystem.components.button.state.LinkMindButtonState @@ -58,6 +59,14 @@ class LinkMindBlockButton @JvmOverloads constructor( } } + fun showLoadingUsingSaveLink(loadingText: String = "저장 중...") { + binding.apply { + progressBar.visibility = View.VISIBLE + tvBtn.text = loadingText + state = LinkMindButtonState.DISABLE + } + } + init { val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater binding = ButtonBlockLinkmindBinding.inflate(inflater, this, true) diff --git a/core/designsystem/src/main/res/layout/button_block_linkmind.xml b/core/designsystem/src/main/res/layout/button_block_linkmind.xml index c4d032e7..ffd6c83e 100644 --- a/core/designsystem/src/main/res/layout/button_block_linkmind.xml +++ b/core/designsystem/src/main/res/layout/button_block_linkmind.xml @@ -13,13 +13,27 @@ android:paddingVertical="21dp"> + android:id="@+id/tv_btn" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="center" + android:textAppearance="@style/Typography.suit.bold_16" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:text="BTN" /> + + + diff --git a/feature/savelink/src/main/java/org/sopt/savelink/ui/savelinksetclip/SaveLinkSetClipFragment.kt b/feature/savelink/src/main/java/org/sopt/savelink/ui/savelinksetclip/SaveLinkSetClipFragment.kt index 3266aad6..08843205 100644 --- a/feature/savelink/src/main/java/org/sopt/savelink/ui/savelinksetclip/SaveLinkSetClipFragment.kt +++ b/feature/savelink/src/main/java/org/sopt/savelink/ui/savelinksetclip/SaveLinkSetClipFragment.kt @@ -115,7 +115,10 @@ class SaveLinkSetClipFragment : BindingFragment( btnClick { if (state == LinkMindButtonState.DISABLE) return@btnClick viewModel.viewModelScope.launch { - viewModel.saveLink(viewModel.container.stateFlow.value.url, viewModel.container.stateFlow.value.categoryId) + viewModel.saveLink( + viewModel.container.stateFlow.value.url, + viewModel.container.stateFlow.value.categoryId, + ) { showLoadingUsingSaveLink() } } } } diff --git a/feature/savelink/src/main/java/org/sopt/savelink/ui/savelinksetclip/SetLinkViewModel.kt b/feature/savelink/src/main/java/org/sopt/savelink/ui/savelinksetclip/SetLinkViewModel.kt index 760dfac3..f7b56f8c 100644 --- a/feature/savelink/src/main/java/org/sopt/savelink/ui/savelinksetclip/SetLinkViewModel.kt +++ b/feature/savelink/src/main/java/org/sopt/savelink/ui/savelinksetclip/SetLinkViewModel.kt @@ -88,9 +88,10 @@ class SetLinkViewModel @Inject constructor( } private val mutex = Mutex() - fun saveLink(linkUrl: String, categoryId: Long?) = viewModelScope.launch { + fun saveLink(linkUrl: String, categoryId: Long?, func: () -> Unit) = viewModelScope.launch { if (!mutex.isLocked) { mutex.withLock { + func() saveLinkUseCase( PostSaveLinkUseCase.Param( linkUrl = linkUrl, From f1b9a36b408f325dd369aab742b2d4b608e38c8e Mon Sep 17 00:00:00 2001 From: lsakee Date: Wed, 6 Nov 2024 17:18:28 +0900 Subject: [PATCH 02/10] feat:webview in mobile --- .../src/main/java/org/sopt/clip/webview/WebViewFragment.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt b/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt index 4b01e567..9aec5bf9 100644 --- a/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt +++ b/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt @@ -98,6 +98,10 @@ class WebViewFragment : BindingFragment({ FragmentWebvie val WebViewAddress = binding.tvWebviewAddress url?.let { + webView.settings.apply { + userAgentString = webView.settings.userAgentString.replace("wv", "") + domStorageEnabled = true + } webView.webViewClient = WebViewClient() webView.loadUrl(it) WebViewAddress.setText(it) From a52c93766321cab7c58c8745f2c7d29a0933c527 Mon Sep 17 00:00:00 2001 From: lsakee Date: Thu, 7 Nov 2024 20:31:16 +0900 Subject: [PATCH 03/10] feat:add tooltip icon share link design webview --- .../src/main/res/drawable/ic_share.xml | 9 + .../src/main/res/drawable/tool_tip.xml | 15 + .../src/main/res/drawable/tooltip_copy.xml | 15 + .../main/res/drawable/tooltip_move_clip.xml | 15 + .../src/main/res/drawable/tooltip_search.xml | 15 + .../clip/DeleteLinkBottomSheetFragment.kt | 1 + .../org/sopt/clip/webview/WebViewFragment.kt | 46 +- .../fragment_delete_link_bottom_sheet.xml | 15 +- .../src/main/res/layout/fragment_webview.xml | 256 +++++----- .../main/java/org/sopt/home/HomeContract.kt | 1 + .../main/java/org/sopt/home/HomeFragment.kt | 3 + .../main/java/org/sopt/home/HomeViewModel.kt | 22 +- .../src/main/res/layout/fragment_home.xml | 476 +++++++++--------- feature/maincontainer/build.gradle.kts | 1 + .../org/sopt/maincontainer/MainActivity.kt | 2 + .../org/sopt/maincontainer/MainContract.kt | 1 + .../org/sopt/maincontainer/MainViewModel.kt | 22 +- .../src/main/res/layout/activity_main.xml | 132 ++--- 18 files changed, 604 insertions(+), 443 deletions(-) create mode 100644 core/designsystem/src/main/res/drawable/ic_share.xml create mode 100644 core/designsystem/src/main/res/drawable/tool_tip.xml create mode 100644 core/designsystem/src/main/res/drawable/tooltip_copy.xml create mode 100644 core/designsystem/src/main/res/drawable/tooltip_move_clip.xml create mode 100644 core/designsystem/src/main/res/drawable/tooltip_search.xml diff --git a/core/designsystem/src/main/res/drawable/ic_share.xml b/core/designsystem/src/main/res/drawable/ic_share.xml new file mode 100644 index 00000000..fafa2bd0 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_share.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/tool_tip.xml b/core/designsystem/src/main/res/drawable/tool_tip.xml new file mode 100644 index 00000000..629203c2 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/tool_tip.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/core/designsystem/src/main/res/drawable/tooltip_copy.xml b/core/designsystem/src/main/res/drawable/tooltip_copy.xml new file mode 100644 index 00000000..7bc2e8e4 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/tooltip_copy.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/core/designsystem/src/main/res/drawable/tooltip_move_clip.xml b/core/designsystem/src/main/res/drawable/tooltip_move_clip.xml new file mode 100644 index 00000000..de520aa0 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/tooltip_move_clip.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/core/designsystem/src/main/res/drawable/tooltip_search.xml b/core/designsystem/src/main/res/drawable/tooltip_search.xml new file mode 100644 index 00000000..86bc5d8d --- /dev/null +++ b/core/designsystem/src/main/res/drawable/tooltip_search.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt b/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt index c32f0262..2eed5e43 100644 --- a/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt +++ b/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt @@ -27,6 +27,7 @@ class DeleteLinkBottomSheetFragment() : if (clipId?.toInt() == 0) { binding.tvDeleteLinkChange.isVisible = false + binding.testCoach.isVisible = false } binding.ivDeleteLinkBottomSheetClose.setOnClickListener { diff --git a/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt b/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt index 9aec5bf9..432ab2d3 100644 --- a/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt +++ b/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt @@ -4,14 +4,11 @@ import android.content.Intent import android.graphics.Bitmap import android.net.Uri import android.os.Bundle -import android.util.Log import android.view.View import android.view.inputmethod.EditorInfo import android.webkit.WebView import android.webkit.WebViewClient import androidx.core.content.ContextCompat -import androidx.core.view.isInvisible -import androidx.core.view.isVisible import androidx.fragment.app.viewModels import androidx.lifecycle.flowWithLifecycle import androidx.navigation.fragment.findNavController @@ -31,7 +28,8 @@ import java.net.URLDecoder import java.nio.charset.StandardCharsets @AndroidEntryPoint -class WebViewFragment : BindingFragment({ FragmentWebviewBinding.inflate(it) }) { +class WebViewFragment : + BindingFragment({ FragmentWebviewBinding.inflate(it) }) { private val viewModel: WebViewViewModel by viewModels() val args: WebViewFragmentArgs by navArgs() var isPatched: Boolean = false @@ -50,13 +48,9 @@ class WebViewFragment : BindingFragment({ FragmentWebvie viewModel.patchReadLinkResult.value = false } } - } else { - binding.ivRead.isInvisible = true - binding.ivRead.isClickable = false } - binding.ivRead.onThrottleClick { - Log.e("읽음", "누름") + binding.ivReadAfter.onThrottleClick { if (args.isMylink) { viewModel.patchReadLink(args.toastId, !viewModel.patchReadLinkResult.value) isPatched = true @@ -66,17 +60,18 @@ class WebViewFragment : BindingFragment({ FragmentWebvie viewModel.patchReadLinkResult.flowWithLifecycle(viewLifeCycle).onEach { when (it) { true -> { - binding.ivRead.setImageResource(org.sopt.mainfeature.R.drawable.ic_read_after_24) + binding.ivReadAfter.setImageResource(org.sopt.mainfeature.R.drawable.ic_read_after_24) if (isPatched) requireActivity().linkMindSnackBar(binding.clBottomBar, "열람 완료") } false -> { - binding.ivRead.setImageResource(R.drawable.ic_read_before_24) + binding.ivReadAfter.setImageResource(R.drawable.ic_read_before_24) if (isPatched) requireActivity().linkMindSnackBar(binding.clBottomBar, "열람 취소") } } }.launchIn(viewLifeCycleScope) setupWebView(decodedURL) + onClickShare(decodedURL) onClickClipLink() onClickWebViewClose() onClickWebViewReStart() @@ -86,6 +81,18 @@ class WebViewFragment : BindingFragment({ FragmentWebvie initEditorActionListener() } + private fun onClickShare(decodedURL: String) { + if (decodedURL.isEmpty()) return + binding.ivShare.onThrottleClick { + val shareIntent = Intent().apply { + action = Intent.ACTION_SEND + type = "text/plain" + putExtra(Intent.EXTRA_TEXT, decodedURL) + } + runCatching { startActivity(Intent.createChooser(shareIntent, "링크 공유하기")) } + } + } + private fun onClickClipLink() { val url = arguments?.getString("url") url?.let { @@ -127,23 +134,6 @@ class WebViewFragment : BindingFragment({ FragmentWebvie } } - private fun initReadBtnClickLister() { - with(binding) { - ivRead.onThrottleClick { - // handleVisibility(ivRead, ivReadAfter) - } - - /*ivReadAfter.onThrottleClick { - handleVisibility(ivReadAfter, ivRead) - }*/ - } - } - - private fun handleVisibility(visibleButton: View, invisibleButton: View) { - visibleButton.isVisible = !visibleButton.isVisible - invisibleButton.isVisible = !visibleButton.isVisible - } - private fun onClickWebViewClose() { binding.ivClose.onThrottleClick { findNavController().popBackStack() diff --git a/feature/clip/src/main/res/layout/fragment_delete_link_bottom_sheet.xml b/feature/clip/src/main/res/layout/fragment_delete_link_bottom_sheet.xml index f43f25be..6015d45d 100644 --- a/feature/clip/src/main/res/layout/fragment_delete_link_bottom_sheet.xml +++ b/feature/clip/src/main/res/layout/fragment_delete_link_bottom_sheet.xml @@ -58,7 +58,7 @@ - + - - - - - - + android:layout_height="match_parent" + tools:ignore="MissingDefaultResource"> + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + app:layout_constraintTop_toBottomOf="@id/wb_clip_container"> + android:id="@+id/iv_back" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="8dp" + android:src="@drawable/ic_back_24" + app:layout_constraintEnd_toStartOf="@+id/iv_next" + app:layout_constraintHorizontal_bias="0.5" + app:layout_constraintHorizontal_chainStyle="spread" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + android:id="@+id/iv_next" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="8dp" + android:src="@drawable/ic_next_24" + app:layout_constraintEnd_toStartOf="@+id/iv_read_after" + app:layout_constraintHorizontal_bias="0.5" + app:layout_constraintStart_toEndOf="@+id/iv_back" + app:layout_constraintTop_toTopOf="parent" /> + android:id="@+id/iv_read_after" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="8dp" + android:src="@drawable/ic_read_after_24" + app:layout_constraintEnd_toStartOf="@+id/iv_share" + app:layout_constraintHorizontal_bias="0.5" + app:layout_constraintStart_toEndOf="@+id/iv_next" + app:layout_constraintTop_toTopOf="parent" /> + android:id="@+id/iv_share" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="8dp" + android:src="@drawable/ic_share" + app:layout_constraintEnd_toStartOf="@+id/iv_internet" + app:layout_constraintHorizontal_bias="0.5" + app:layout_constraintStart_toEndOf="@+id/iv_read_after" + app:layout_constraintTop_toTopOf="parent" /> - + android:id="@+id/iv_internet" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="8dp" + android:src="@drawable/ic_internet_after_24" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" + app:layout_constraintStart_toEndOf="@+id/iv_share" + app:layout_constraintTop_toTopOf="parent" /> diff --git a/feature/home/src/main/java/org/sopt/home/HomeContract.kt b/feature/home/src/main/java/org/sopt/home/HomeContract.kt index da0628a0..0509b3ae 100644 --- a/feature/home/src/main/java/org/sopt/home/HomeContract.kt +++ b/feature/home/src/main/java/org/sopt/home/HomeContract.kt @@ -20,6 +20,7 @@ data class HomeState( val categoryName: String? = "전체 클립", val popupList: List = emptyList(), val marketUpdate: UpdatePriority = UpdatePriority.EMPTY, + val visibleBubbleMark: Boolean = false, ) { fun calculateProgress(): Int { if (readToastNum > allToastNum) return 0 diff --git a/feature/home/src/main/java/org/sopt/home/HomeFragment.kt b/feature/home/src/main/java/org/sopt/home/HomeFragment.kt index d8feb898..8f9d99e4 100644 --- a/feature/home/src/main/java/org/sopt/home/HomeFragment.kt +++ b/feature/home/src/main/java/org/sopt/home/HomeFragment.kt @@ -2,6 +2,7 @@ package org.sopt.home import android.os.Bundle import android.view.View +import androidx.core.view.isVisible import androidx.fragment.app.viewModels import androidx.navigation.fragment.findNavController import dagger.hilt.android.AndroidEntryPoint @@ -38,6 +39,7 @@ class HomeFragment : BindingFragment({ FragmentHomeBinding. private fun initView() { initAdapter() + viewModel.showThenHide() } private fun collectState() { @@ -50,6 +52,7 @@ class HomeFragment : BindingFragment({ FragmentHomeBinding. binding.tvHomeUserName.text = homeState.nickName binding.tvHomeUserClipName.text = homeState.nickName binding.tvHomeToastLinkCount.text = "${homeState.readToastNum}개의 링크" + binding.testCoach.isVisible = homeState.visibleBubbleMark binding.pbLinkmindHome.setProgressBarMain(homeState.calculateProgress()) homeClipAdapter.submitList(homeState.recentSavedLink) homeWeekLinkAdapter.submitList(homeState.weekBestLink) diff --git a/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt b/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt index a08fa649..26904cdd 100644 --- a/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt +++ b/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt @@ -8,6 +8,7 @@ import com.google.android.play.core.appupdate.AppUpdateManagerFactory import com.google.android.play.core.install.model.UpdateAvailability import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import org.orbitmvi.orbit.Container @@ -77,6 +78,21 @@ class HomeViewModel @Inject constructor( } } + fun showThenHide(showDelay: Long = 500, duration: Long = 2000) = intent { + Log.d("Update", "${dataStore.flowMarketUpdate().first()}") + if (dataStore.flowMarketUpdate().first()) { + delay(showDelay) + reduce { + state.copy(visibleBubbleMark = true) + } + delay(duration) + reduce { + state.copy(visibleBubbleMark = false) + } + dataStore.setMarketUpdate(false) + } + } + fun getRecommendSite() = intent { getRecommendSite.invoke().onSuccess { reduce { @@ -133,7 +149,11 @@ class HomeViewModel @Inject constructor( intent { postSideEffect(HomeSideEffect.ShowUpdateDialog) reduce { - state.copy(marketUpdate = UpdatePriority.toUpdatePriority(appUpdateInfo.updatePriority())) + state.copy( + marketUpdate = UpdatePriority.toUpdatePriority( + appUpdateInfo.updatePriority(), + ), + ) } } } diff --git a/feature/home/src/main/res/layout/fragment_home.xml b/feature/home/src/main/res/layout/fragment_home.xml index 73ced568..c6d2f758 100644 --- a/feature/home/src/main/res/layout/fragment_home.xml +++ b/feature/home/src/main/res/layout/fragment_home.xml @@ -1,258 +1,270 @@ - - + android:layout_height="match_parent" + android:orientation="vertical"> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - - - + + + + + + + + + + diff --git a/feature/maincontainer/build.gradle.kts b/feature/maincontainer/build.gradle.kts index 95368211..3ac1a4c6 100644 --- a/feature/maincontainer/build.gradle.kts +++ b/feature/maincontainer/build.gradle.kts @@ -18,4 +18,5 @@ dependencies { implementation(projects.feature.timer) implementation(projects.feature.search) implementation(projects.feature.savelink) + implementation(projects.core.datastore) } diff --git a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainActivity.kt b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainActivity.kt index 4193c849..03874418 100644 --- a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainActivity.kt +++ b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainActivity.kt @@ -47,6 +47,7 @@ class MainActivity : AppCompatActivity() { setFcv() changeBottomNavigationFragment() setBottomVisible() + viewModel.showThenHide() } private fun collectState() { @@ -55,6 +56,7 @@ class MainActivity : AppCompatActivity() { private fun render(mainState: MainState) { binding.bnvMain.isVisible = mainState.isBottomNavigationBarVisible + binding.testCoach.isVisible = mainState.visibleBubbleMark } private fun handleSideEffect(sideEffect: MainSideEffect) { diff --git a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainContract.kt b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainContract.kt index 53df177b..19acb39a 100644 --- a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainContract.kt +++ b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainContract.kt @@ -3,6 +3,7 @@ package org.sopt.maincontainer data class MainState( val isBottomNavigationBarVisible: Boolean = true, val clipboard: String = "", + val visibleBubbleMark: Boolean = false, ) sealed interface MainSideEffect { diff --git a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt index 8bc43043..276fe675 100644 --- a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt +++ b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt @@ -1,20 +1,40 @@ package org.sopt.maincontainer +import android.util.Log import androidx.lifecycle.ViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.first import org.orbitmvi.orbit.Container import org.orbitmvi.orbit.ContainerHost import org.orbitmvi.orbit.syntax.simple.intent import org.orbitmvi.orbit.syntax.simple.postSideEffect import org.orbitmvi.orbit.syntax.simple.reduce import org.orbitmvi.orbit.viewmodel.container +import org.sopt.datastore.datastore.SecurityDataStore import javax.inject.Inject @HiltViewModel -class MainViewModel @Inject constructor() : ContainerHost, ViewModel() { +class MainViewModel @Inject constructor( + private val dataStore: SecurityDataStore, +) : ContainerHost, ViewModel() { override val container: Container = container(MainState()) + fun showThenHide(showDelay: Long = 500, duration: Long = 2000) = intent { + Log.d("Update", "${dataStore.flowMarketUpdate().first()}") + if (dataStore.flowMarketUpdate().first()) { + delay(showDelay) + reduce { + state.copy(visibleBubbleMark = true) + } + delay(duration) + reduce { + state.copy(visibleBubbleMark = false) + } + } + } + fun updateClipBoard(clipboard: String) = intent { reduce { state.copy(clipboard = clipboard) diff --git a/feature/maincontainer/src/main/res/layout/activity_main.xml b/feature/maincontainer/src/main/res/layout/activity_main.xml index 52f88378..a6719891 100644 --- a/feature/maincontainer/src/main/res/layout/activity_main.xml +++ b/feature/maincontainer/src/main/res/layout/activity_main.xml @@ -1,64 +1,82 @@ - - + android:layout_height="match_parent" + tools:context=".MainActivity"> - + - + + + + + + + - + From 0af1439d96688d68433356d0009d2c0aa422afed Mon Sep 17 00:00:00 2001 From: lsakee Date: Thu, 7 Nov 2024 21:54:58 +0900 Subject: [PATCH 04/10] feat:navigate webview --- .editorconfig | 2 +- .../datastore/datastore/SecurityDataStore.kt | 7 ++++ .../src/main/res/drawable/ic_read.xml | 13 +++++++ .../src/main/res/drawable/ic_read_check.xml | 13 +++++++ feature/clip/build.gradle.kts | 1 + .../clip/DeleteLinkBottomSheetFragment.kt | 19 ++++++++-- .../sopt/clip/cliplink/ClipLinkFragment.kt | 1 + .../sopt/clip/cliplink/ClipLinkViewModel.kt | 31 ++++++++++++++++ .../org/sopt/clip/webview/WebViewFragment.kt | 14 ++++++-- .../org/sopt/clip/webview/WebViewViewModel.kt | 20 +++++++++++ .../src/main/res/layout/fragment_webview.xml | 2 +- .../main/java/org/sopt/home/HomeContract.kt | 2 ++ .../main/java/org/sopt/home/HomeFragment.kt | 5 +-- .../main/java/org/sopt/home/HomeViewModel.kt | 36 ++++++++++++------- .../sopt/login/onboarding/LoginActivity.kt | 1 + .../org/sopt/maincontainer/MainViewModel.kt | 24 +++++++------ 16 files changed, 159 insertions(+), 32 deletions(-) create mode 100644 core/designsystem/src/main/res/drawable/ic_read.xml create mode 100644 core/designsystem/src/main/res/drawable/ic_read_check.xml diff --git a/.editorconfig b/.editorconfig index 5b419e7c..b8401f7f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,7 +4,7 @@ root = true charset = utf-8 indent_size = 2 indent_style = space -max_line_length = 150 +max_line_length = 200 insert_final_newline = true trim_trailing_whitespace = true diff --git a/core/datastore/src/main/java/org/sopt/datastore/datastore/SecurityDataStore.kt b/core/datastore/src/main/java/org/sopt/datastore/datastore/SecurityDataStore.kt index 39316325..55343bcd 100644 --- a/core/datastore/src/main/java/org/sopt/datastore/datastore/SecurityDataStore.kt +++ b/core/datastore/src/main/java/org/sopt/datastore/datastore/SecurityDataStore.kt @@ -50,6 +50,12 @@ interface SecurityDataStore { @SetValue(KEY_MARKET_UPDATE) suspend fun setMarketUpdate(boolean: Boolean) + @GetValue(TOOLTIP) + fun flowTooltip(): Flow + + @SetValue(TOOLTIP) + suspend fun setTooltip(boolean: String) + @ClearValues suspend fun clearAll() @@ -61,5 +67,6 @@ interface SecurityDataStore { const val KEY_FCM_ALLOWED = "key-fcm-allowed" const val KEY_POPUP_VISIBILITY = "key-popup-dialog" const val KEY_MARKET_UPDATE = "key-market-update" + const val TOOLTIP = "tooltip" } } diff --git a/core/designsystem/src/main/res/drawable/ic_read.xml b/core/designsystem/src/main/res/drawable/ic_read.xml new file mode 100644 index 00000000..2dbf41ee --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_read.xml @@ -0,0 +1,13 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/ic_read_check.xml b/core/designsystem/src/main/res/drawable/ic_read_check.xml new file mode 100644 index 00000000..7dd2fa37 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_read_check.xml @@ -0,0 +1,13 @@ + + + diff --git a/feature/clip/build.gradle.kts b/feature/clip/build.gradle.kts index 16367cb4..6712a9e8 100644 --- a/feature/clip/build.gradle.kts +++ b/feature/clip/build.gradle.kts @@ -14,5 +14,6 @@ android { dependencies { implementation(projects.domain.category) implementation(projects.domain.link) + implementation(projects.core.datastore) implementation(libs.coil) } diff --git a/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt b/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt index 2eed5e43..bbb2ccd1 100644 --- a/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt +++ b/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt @@ -3,6 +3,9 @@ package org.sopt.clip import android.os.Bundle import android.view.View import androidx.core.view.isVisible +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import org.sopt.clip.databinding.FragmentDeleteLinkBottomSheetBinding import org.sopt.ui.base.BindingBottomSheetDialogFragment import org.sopt.ui.view.onThrottleClick @@ -11,6 +14,7 @@ class DeleteLinkBottomSheetFragment() : BindingBottomSheetDialogFragment({ FragmentDeleteLinkBottomSheetBinding.inflate(it) }) { var clipId: Long? = null var isFullClipSize: Boolean? = null + var tooltip: Boolean? = null private var handleDelete: () -> Unit = {} private var handleChange: () -> Unit = {} private var handleModify: () -> Unit = {} @@ -20,14 +24,20 @@ class DeleteLinkBottomSheetFragment() : super.onCreate(savedInstanceState) clipId = arguments?.getLong("clipId") isFullClipSize = arguments?.getBoolean("isFullClipSize") + tooltip = arguments?.getBoolean("tooltip") } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - + binding.testCoach.isVisible = tooltip ?: false + if (tooltip == true) { + lifecycleScope.launch { + delay(2000) // 0.5초 딜레이 + binding.testCoach.isVisible = false + } + } if (clipId?.toInt() == 0) { - binding.tvDeleteLinkChange.isVisible = false - binding.testCoach.isVisible = false +// binding.tvDeleteLinkChange.isVisible = false } binding.ivDeleteLinkBottomSheetClose.setOnClickListener { @@ -57,6 +67,7 @@ class DeleteLinkBottomSheetFragment() : fun newInstance( clipId: Long, isFullClipSize: Boolean, + tooltip: Boolean, isClipListEmpty: () -> Unit, handleDeleteButton: () -> Unit, handleChangeButton: () -> Unit, @@ -65,7 +76,9 @@ class DeleteLinkBottomSheetFragment() : val args = Bundle().apply { putLong("clipId", clipId) putBoolean("isFullClipSize", isFullClipSize) + putBoolean("tooltip", tooltip) } + return DeleteLinkBottomSheetFragment().apply { arguments = args handleDelete = handleDeleteButton diff --git a/feature/clip/src/main/java/org/sopt/clip/cliplink/ClipLinkFragment.kt b/feature/clip/src/main/java/org/sopt/clip/cliplink/ClipLinkFragment.kt index efed8391..fe597586 100644 --- a/feature/clip/src/main/java/org/sopt/clip/cliplink/ClipLinkFragment.kt +++ b/feature/clip/src/main/java/org/sopt/clip/cliplink/ClipLinkFragment.kt @@ -268,6 +268,7 @@ class ClipLinkFragment : BindingFragment({ FragmentClip DeleteLinkBottomSheetFragment.newInstance( clipId, isFullClipSize, + tooltip = viewModel.tooltip.value, { requireContext().linkMindSnackBar(binding.vSnack, "이동할 클립을 하나 이상 생성해 주세요", true) }, handleDeleteButton = { viewModel.deleteLink(linkDTO.toastId) diff --git a/feature/clip/src/main/java/org/sopt/clip/cliplink/ClipLinkViewModel.kt b/feature/clip/src/main/java/org/sopt/clip/cliplink/ClipLinkViewModel.kt index a792f120..803a15b5 100644 --- a/feature/clip/src/main/java/org/sopt/clip/cliplink/ClipLinkViewModel.kt +++ b/feature/clip/src/main/java/org/sopt/clip/cliplink/ClipLinkViewModel.kt @@ -4,11 +4,15 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import org.sopt.clip.SelectedToggle +import org.sopt.datastore.datastore.SecurityDataStore import org.sopt.domain.category.category.usecase.GetCategoryAllUseCase import org.sopt.domain.category.category.usecase.GetCategoryLinkUseCase import org.sopt.domain.link.usecase.DeleteLinkUseCase @@ -26,6 +30,7 @@ class ClipLinkViewModel @Inject constructor( private val patchLinkTitleUseCase: PatchLinkTitleUseCase, private val getCategoryAll: GetCategoryAllUseCase, private val patchLinkCategoryUseCase: PatchLinkCategoryUseCase, + private val dataStore: SecurityDataStore, ) : ViewModel() { private val _linkState = MutableStateFlow>>(UiState.Empty) val linkState: StateFlow>> = _linkState.asStateFlow() @@ -49,6 +54,32 @@ class ClipLinkViewModel @Inject constructor( val patchLinkCategory: StateFlow> = _patchLinkCategory.asStateFlow() var toggleSelectedPast: SelectedToggle = SelectedToggle.ALL + init { + showThenHide() + } + val tooltip = MutableStateFlow(false) + fun showThenHide(showDelay: Long = 500, duration: Long = 2000) = viewModelScope.launch(Dispatchers.IO) { + runCatching { + val booleanListFlow = + dataStore.flowTooltip().first().toString() + val stringValue = booleanListFlow.split(",").map { it.toBoolean() } + if (stringValue[3]) { + delay(showDelay) + tooltip.emit(stringValue[3]) + delay(duration) + tooltip.emit(false) + dataStore.setTooltip( + listOf( + stringValue[0], + stringValue[1], + stringValue[2], + !stringValue[3], + ).joinToString(","), + ) + } + } + } + fun deleteLink(toastId: Long) = viewModelScope.launch { deleteLinkUseCase.invoke(param = DeleteLinkUseCase.Param(toastId = toastId)).onSuccess { if (it == 200) { diff --git a/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt b/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt index 432ab2d3..a77aa877 100644 --- a/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt +++ b/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt @@ -4,11 +4,13 @@ import android.content.Intent import android.graphics.Bitmap import android.net.Uri import android.os.Bundle +import android.util.Log import android.view.View import android.view.inputmethod.EditorInfo import android.webkit.WebView import android.webkit.WebViewClient import androidx.core.content.ContextCompat +import androidx.core.view.isVisible import androidx.fragment.app.viewModels import androidx.lifecycle.flowWithLifecycle import androidx.navigation.fragment.findNavController @@ -36,6 +38,7 @@ class WebViewFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + viewModel.showThenHide() val decodedURL = URLDecoder.decode(args.site, StandardCharsets.UTF_8.toString()) binding.wbClip.settings.javaScriptEnabled = true if (args.isMylink) { @@ -60,16 +63,23 @@ class WebViewFragment : viewModel.patchReadLinkResult.flowWithLifecycle(viewLifeCycle).onEach { when (it) { true -> { - binding.ivReadAfter.setImageResource(org.sopt.mainfeature.R.drawable.ic_read_after_24) + binding.ivReadAfter.setImageResource(org.sopt.mainfeature.R.drawable.ic_read_check) if (isPatched) requireActivity().linkMindSnackBar(binding.clBottomBar, "열람 완료") } false -> { - binding.ivReadAfter.setImageResource(R.drawable.ic_read_before_24) + binding.ivReadAfter.setImageResource(org.sopt.mainfeature.R.drawable.ic_read) if (isPatched) requireActivity().linkMindSnackBar(binding.clBottomBar, "열람 취소") } } }.launchIn(viewLifeCycleScope) + + viewModel.tooltip.flowWithLifecycle(viewLifeCycle).onEach { + Log.d("tooltipVisible", "$it") + binding.testCoach.isVisible = it + binding.testCoach2.isVisible = it + }.launchIn(viewLifeCycleScope) + setupWebView(decodedURL) onClickShare(decodedURL) onClickClipLink() diff --git a/feature/clip/src/main/java/org/sopt/clip/webview/WebViewViewModel.kt b/feature/clip/src/main/java/org/sopt/clip/webview/WebViewViewModel.kt index f17464d2..1c6c2338 100644 --- a/feature/clip/src/main/java/org/sopt/clip/webview/WebViewViewModel.kt +++ b/feature/clip/src/main/java/org/sopt/clip/webview/WebViewViewModel.kt @@ -4,16 +4,22 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch +import org.sopt.datastore.datastore.SecurityDataStore import org.sopt.domain.link.usecase.PatchReadLinkUseCase import javax.inject.Inject @HiltViewModel class WebViewViewModel @Inject constructor( private val patchReadLinkUseCase: PatchReadLinkUseCase, + private val dataStore: SecurityDataStore, ) : ViewModel() { val patchReadLinkResult = MutableStateFlow(false) + val tooltip = MutableStateFlow(false) fun patchReadLink(toastId: Long, isRead: Boolean) = viewModelScope.launch { patchReadLinkUseCase(param = PatchReadLinkUseCase.Param(toastId, isRead)).onSuccess { patchReadLinkResult.emit(it) @@ -21,4 +27,18 @@ class WebViewViewModel @Inject constructor( Log.e("실패", it.message.toString()) } } + fun showThenHide(showDelay: Long = 500, duration: Long = 2000) = viewModelScope.launch(Dispatchers.IO) { + runCatching { + val booleanListFlow = + dataStore.flowTooltip().first().toString() + val stringValue = booleanListFlow.split(",").map { it.toBoolean() } + if (stringValue[2]) { + delay(showDelay) + tooltip.emit(true) + delay(duration) + tooltip.emit(false) + dataStore.setTooltip(listOf(stringValue[0], stringValue[1], !stringValue[2], stringValue[3]).joinToString(",")) + } + } + } } diff --git a/feature/clip/src/main/res/layout/fragment_webview.xml b/feature/clip/src/main/res/layout/fragment_webview.xml index e1935db9..005094e7 100644 --- a/feature/clip/src/main/res/layout/fragment_webview.xml +++ b/feature/clip/src/main/res/layout/fragment_webview.xml @@ -122,7 +122,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="8dp" - android:src="@drawable/ic_read_after_24" + android:src="@drawable/ic_read" app:layout_constraintEnd_toStartOf="@+id/iv_share" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toEndOf="@+id/iv_next" diff --git a/feature/home/src/main/java/org/sopt/home/HomeContract.kt b/feature/home/src/main/java/org/sopt/home/HomeContract.kt index 0509b3ae..0d44e2fe 100644 --- a/feature/home/src/main/java/org/sopt/home/HomeContract.kt +++ b/feature/home/src/main/java/org/sopt/home/HomeContract.kt @@ -16,6 +16,8 @@ data class HomeState( val recommendLink: List = emptyList(), val recentSavedLink: List = emptyList(), val url: String = "", + val toastId: Long = 0, + val isRead: Boolean = false, val categoryId: Long? = 0, val categoryName: String? = "전체 클립", val popupList: List = emptyList(), diff --git a/feature/home/src/main/java/org/sopt/home/HomeFragment.kt b/feature/home/src/main/java/org/sopt/home/HomeFragment.kt index 8f9d99e4..44967d03 100644 --- a/feature/home/src/main/java/org/sopt/home/HomeFragment.kt +++ b/feature/home/src/main/java/org/sopt/home/HomeFragment.kt @@ -33,6 +33,7 @@ class HomeFragment : BindingFragment({ FragmentHomeBinding. super.onViewCreated(view, savedInstanceState) initView() collectState() + collectState() navigateToSetting() navigateToAllClip() } @@ -70,7 +71,7 @@ class HomeFragment : BindingFragment({ FragmentHomeBinding. is HomeSideEffect.NavigateWebView -> { val encodedURL = URLEncoder.encode(viewModel.container.stateFlow.value.url, StandardCharsets.UTF_8.toString()) navigateToDestination( - "featureSaveLink://webViewFragment/${0}/${false}/${false}/$encodedURL", + "featureSaveLink://webViewFragment/${viewModel.container.stateFlow.value.toastId}/${viewModel.container.stateFlow.value.isRead}/${true}/$encodedURL", ) } @@ -109,7 +110,7 @@ class HomeFragment : BindingFragment({ FragmentHomeBinding. private fun setClipAdapter() { homeClipAdapter = HomeClipAdapter( onClickClip = { - viewModel.navigateWebview(it.linkUrl) + viewModel.navigateWebview(it.linkUrl, it.isRead, it.toastId) }, onClickEmptyClip = { viewModel.navigateSaveLink() diff --git a/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt b/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt index 26904cdd..0f9ac05e 100644 --- a/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt +++ b/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt @@ -79,17 +79,28 @@ class HomeViewModel @Inject constructor( } fun showThenHide(showDelay: Long = 500, duration: Long = 2000) = intent { - Log.d("Update", "${dataStore.flowMarketUpdate().first()}") - if (dataStore.flowMarketUpdate().first()) { - delay(showDelay) - reduce { - state.copy(visibleBubbleMark = true) - } - delay(duration) - reduce { - state.copy(visibleBubbleMark = false) + runCatching { + val booleanListFlow = + dataStore.flowTooltip().first().toString() + val stringValue = booleanListFlow.split(",").map { it.toBoolean() } + if (stringValue[1]) { + delay(showDelay) + reduce { + state.copy(visibleBubbleMark = true) + } + delay(duration) + reduce { + state.copy(visibleBubbleMark = false) + } + dataStore.setTooltip( + listOf( + !stringValue[0], + !stringValue[1], + stringValue[2], + stringValue[3], + ).joinToString(","), + ) } - dataStore.setMarketUpdate(false) } } @@ -169,8 +180,9 @@ class HomeViewModel @Inject constructor( fun navigateAllClip() = intent { postSideEffect(HomeSideEffect.NavigateAllClip) } @OptIn(OrbitExperimental::class) - fun navigateWebview(url: String) = blockingIntent { - reduce { state.copy(url = url) } + fun navigateWebview(url: String, isRead: Boolean = false, toastId: Long = 0) = blockingIntent { + reduce { state.copy(url = url, toastId = toastId, isRead = isRead) } + Log.d("testSak", "$toastId $isRead") postSideEffect(HomeSideEffect.NavigateWebView) } diff --git a/feature/login/src/main/java/org/sopt/login/onboarding/LoginActivity.kt b/feature/login/src/main/java/org/sopt/login/onboarding/LoginActivity.kt index 957c5df2..7b949c5f 100644 --- a/feature/login/src/main/java/org/sopt/login/onboarding/LoginActivity.kt +++ b/feature/login/src/main/java/org/sopt/login/onboarding/LoginActivity.kt @@ -110,6 +110,7 @@ class LoginActivity : AppCompatActivity() { private fun initMarketUpdateVisible() { lifecycleScope.launch { dataStore.setMarketUpdate(true) + dataStore.setTooltip(listOf(true, true, true, true).joinToString(",")) } } diff --git a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt index 276fe675..e3b97c24 100644 --- a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt +++ b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt @@ -1,6 +1,5 @@ package org.sopt.maincontainer -import android.util.Log import androidx.lifecycle.ViewModel import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.delay @@ -22,19 +21,22 @@ class MainViewModel @Inject constructor( container(MainState()) fun showThenHide(showDelay: Long = 500, duration: Long = 2000) = intent { - Log.d("Update", "${dataStore.flowMarketUpdate().first()}") - if (dataStore.flowMarketUpdate().first()) { - delay(showDelay) - reduce { - state.copy(visibleBubbleMark = true) - } - delay(duration) - reduce { - state.copy(visibleBubbleMark = false) + runCatching { + val booleanListFlow = + dataStore.flowTooltip().first().toString() + val stringValue = booleanListFlow.split(",").map { it.toBoolean() } + if (stringValue[0]) { + delay(showDelay) + reduce { + state.copy(visibleBubbleMark = true) + } + delay(duration) + reduce { + state.copy(visibleBubbleMark = false) + } } } } - fun updateClipBoard(clipboard: String) = intent { reduce { state.copy(clipboard = clipboard) From 1a6ed017592fbf1b23b0f390e43fc8ce4c90d89d Mon Sep 17 00:00:00 2001 From: lsakee Date: Thu, 7 Nov 2024 22:02:58 +0900 Subject: [PATCH 05/10] feat:recent Link --- .../org/sopt/datastore/datastore/SecurityDataStore.kt | 7 +++++++ .../src/main/java/org/sopt/maincontainer/MainActivity.kt | 7 +++++-- .../main/java/org/sopt/maincontainer/MainViewModel.kt | 9 +++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/core/datastore/src/main/java/org/sopt/datastore/datastore/SecurityDataStore.kt b/core/datastore/src/main/java/org/sopt/datastore/datastore/SecurityDataStore.kt index 55343bcd..123e18f3 100644 --- a/core/datastore/src/main/java/org/sopt/datastore/datastore/SecurityDataStore.kt +++ b/core/datastore/src/main/java/org/sopt/datastore/datastore/SecurityDataStore.kt @@ -56,6 +56,12 @@ interface SecurityDataStore { @SetValue(TOOLTIP) suspend fun setTooltip(boolean: String) + @GetValue(RECENT_LINK) + fun flowRecentLink(): Flow + + @SetValue(RECENT_LINK) + suspend fun setRecentLink(link: String) + @ClearValues suspend fun clearAll() @@ -68,5 +74,6 @@ interface SecurityDataStore { const val KEY_POPUP_VISIBILITY = "key-popup-dialog" const val KEY_MARKET_UPDATE = "key-market-update" const val TOOLTIP = "tooltip" + const val RECENT_LINK = "recent_link" } } diff --git a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainActivity.kt b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainActivity.kt index 03874418..df34c952 100644 --- a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainActivity.kt +++ b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainActivity.kt @@ -6,6 +6,7 @@ import android.content.ClipboardManager import android.content.Context import android.content.Intent import android.os.Bundle +import android.util.Log import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isVisible @@ -149,9 +150,8 @@ class MainActivity : AppCompatActivity() { override fun onWindowFocusChanged(hasFocus: Boolean) { super.onWindowFocusChanged(hasFocus) - if (!hasFocus) return - + viewModel.getRecentLink() val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager if (!clipboard.hasPrimaryClip()) return @@ -161,7 +161,10 @@ class MainActivity : AppCompatActivity() { if (item.isNullOrEmpty()) return val pasteData = item.toString() + Log.d("recentLink","${viewModel.container.stateFlow.value.clipboard} ${pasteData}") + if (pasteData== viewModel.container.stateFlow.value.clipboard) return viewModel.updateClipBoard(pasteData) + hideKeyBoard() val action: () -> Unit = { diff --git a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt index e3b97c24..ad553933 100644 --- a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt +++ b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt @@ -41,6 +41,15 @@ class MainViewModel @Inject constructor( reduce { state.copy(clipboard = clipboard) } + dataStore.setRecentLink(clipboard) + } + + fun getRecentLink() =intent { + if (dataStore.flowRecentLink().first().isNullOrEmpty()) return@intent + val clipboard=dataStore.flowRecentLink().first() + reduce { + state.copy(clipboard = clipboard) + } } fun updateBnvVisible(isCheck: Boolean) = intent { From 3906f0c93645fe32a190faefc2b449366d0ac075 Mon Sep 17 00:00:00 2001 From: lsakee Date: Thu, 7 Nov 2024 22:06:00 +0900 Subject: [PATCH 06/10] feat:icon --- .../src/main/res/drawable/tooltip_open.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 core/designsystem/src/main/res/drawable/tooltip_open.xml diff --git a/core/designsystem/src/main/res/drawable/tooltip_open.xml b/core/designsystem/src/main/res/drawable/tooltip_open.xml new file mode 100644 index 00000000..14093ad2 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/tooltip_open.xml @@ -0,0 +1,15 @@ + + + + + From 1b710600cf856ad7d78936402c17af40b0fcc40f Mon Sep 17 00:00:00 2001 From: lsakee Date: Wed, 13 Nov 2024 17:44:07 +0900 Subject: [PATCH 07/10] feat:tooltip --- .../main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt | 3 ++- feature/home/src/main/java/org/sopt/home/HomeViewModel.kt | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt b/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt index bbb2ccd1..d24cb0ec 100644 --- a/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt +++ b/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt @@ -37,7 +37,8 @@ class DeleteLinkBottomSheetFragment() : } } if (clipId?.toInt() == 0) { -// binding.tvDeleteLinkChange.isVisible = false + binding.tvDeleteLinkChange.isVisible = false + binding.testCoach.isVisible=false } binding.ivDeleteLinkBottomSheetClose.setOnClickListener { diff --git a/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt b/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt index 0f9ac05e..4bf7d780 100644 --- a/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt +++ b/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt @@ -168,6 +168,7 @@ class HomeViewModel @Inject constructor( } } } +// setToolTip() }.addOnFailureListener { appUpdateInfo -> Log.d("appUpdateInfo", appUpdateInfo.message.toString()) } @@ -175,6 +176,10 @@ class HomeViewModel @Inject constructor( } } + fun setToolTip() =viewModelScope.launch { + dataStore.setTooltip(listOf(true, true, true, true).joinToString(",")) + } + fun navigateSetting() = intent { postSideEffect(HomeSideEffect.NavigateSetting) } fun navigateSaveLink() = intent { postSideEffect(HomeSideEffect.NavigateSaveLink) } fun navigateAllClip() = intent { postSideEffect(HomeSideEffect.NavigateAllClip) } From 3fbde0bd0f5faf273cbf7e26a45da9e3a8aae1c8 Mon Sep 17 00:00:00 2001 From: lsakee Date: Sat, 16 Nov 2024 13:32:47 +0900 Subject: [PATCH 08/10] feat:temp qa --- .../main/java/org/sopt/clip/webview/WebViewFragment.kt | 6 ++++-- .../java/org/sopt/clip/webview/WebViewViewModel.kt | 4 ++++ .../home/src/main/java/org/sopt/home/HomeViewModel.kt | 2 +- feature/home/src/main/res/layout/fragment_home.xml | 2 +- .../main/java/org/sopt/maincontainer/MainViewModel.kt | 10 +++++++++- .../main/res/layout/fragment_save_link_set_clip.xml | 2 +- 6 files changed, 20 insertions(+), 6 deletions(-) diff --git a/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt b/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt index a77aa877..fc794e6f 100644 --- a/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt +++ b/feature/clip/src/main/java/org/sopt/clip/webview/WebViewFragment.kt @@ -74,12 +74,14 @@ class WebViewFragment : } }.launchIn(viewLifeCycleScope) - viewModel.tooltip.flowWithLifecycle(viewLifeCycle).onEach { + viewModel.tooltip2.flowWithLifecycle(viewLifeCycle).onEach { Log.d("tooltipVisible", "$it") binding.testCoach.isVisible = it + }.launchIn(viewLifeCycleScope) + viewModel.tooltip.flowWithLifecycle(viewLifeCycle).onEach { + Log.d("tooltipVisible2", "$it") binding.testCoach2.isVisible = it }.launchIn(viewLifeCycleScope) - setupWebView(decodedURL) onClickShare(decodedURL) onClickClipLink() diff --git a/feature/clip/src/main/java/org/sopt/clip/webview/WebViewViewModel.kt b/feature/clip/src/main/java/org/sopt/clip/webview/WebViewViewModel.kt index 1c6c2338..9dc9c27d 100644 --- a/feature/clip/src/main/java/org/sopt/clip/webview/WebViewViewModel.kt +++ b/feature/clip/src/main/java/org/sopt/clip/webview/WebViewViewModel.kt @@ -20,6 +20,7 @@ class WebViewViewModel @Inject constructor( ) : ViewModel() { val patchReadLinkResult = MutableStateFlow(false) val tooltip = MutableStateFlow(false) + val tooltip2 = MutableStateFlow(false) fun patchReadLink(toastId: Long, isRead: Boolean) = viewModelScope.launch { patchReadLinkUseCase(param = PatchReadLinkUseCase.Param(toastId, isRead)).onSuccess { patchReadLinkResult.emit(it) @@ -37,6 +38,9 @@ class WebViewViewModel @Inject constructor( tooltip.emit(true) delay(duration) tooltip.emit(false) + tooltip2.emit(true) + delay(duration) + tooltip2.emit(false) dataStore.setTooltip(listOf(stringValue[0], stringValue[1], !stringValue[2], stringValue[3]).joinToString(",")) } } diff --git a/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt b/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt index 4bf7d780..70b0b105 100644 --- a/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt +++ b/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt @@ -94,7 +94,7 @@ class HomeViewModel @Inject constructor( } dataStore.setTooltip( listOf( - !stringValue[0], + stringValue[0], !stringValue[1], stringValue[2], stringValue[3], diff --git a/feature/home/src/main/res/layout/fragment_home.xml b/feature/home/src/main/res/layout/fragment_home.xml index c6d2f758..c389ea9a 100644 --- a/feature/home/src/main/res/layout/fragment_home.xml +++ b/feature/home/src/main/res/layout/fragment_home.xml @@ -50,7 +50,7 @@ = container(MainState()) - fun showThenHide(showDelay: Long = 500, duration: Long = 2000) = intent { + fun showThenHide(showDelay: Long = 3100, duration: Long = 2000) = intent { runCatching { val booleanListFlow = dataStore.flowTooltip().first().toString() @@ -34,6 +34,14 @@ class MainViewModel @Inject constructor( reduce { state.copy(visibleBubbleMark = false) } + dataStore.setTooltip( + listOf( + !stringValue[0], + stringValue[1], + stringValue[2], + stringValue[3], + ).joinToString(","), + ) } } } diff --git a/feature/savelink/src/main/res/layout/fragment_save_link_set_clip.xml b/feature/savelink/src/main/res/layout/fragment_save_link_set_clip.xml index 4d5dcadf..7990b9da 100644 --- a/feature/savelink/src/main/res/layout/fragment_save_link_set_clip.xml +++ b/feature/savelink/src/main/res/layout/fragment_save_link_set_clip.xml @@ -20,7 +20,7 @@ android:layout_height="wrap_content" android:paddingStart="4dp" android:paddingTop="16dp" - android:text="@string/savelink_text_savelink_en" + android:text="@string/savelink_save_link" android:textAppearance="@style/Typography.suit.bold_18" android:textColor="@color/neutrals900" app:layout_constraintStart_toEndOf="@+id/iv_save_link_clip_back" From 16486f8053707cd3d9bf0c3f207770d2e0b24ac5 Mon Sep 17 00:00:00 2001 From: lsakee Date: Sun, 24 Nov 2024 20:53:13 +0900 Subject: [PATCH 09/10] feat:test build will delete --- .../src/main/java/org/sopt/maincontainer/MainViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt index e6f3eab6..4eebbcec 100644 --- a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt +++ b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt @@ -37,7 +37,7 @@ class MainViewModel @Inject constructor( dataStore.setTooltip( listOf( !stringValue[0], - stringValue[1], + !stringValue[1], stringValue[2], stringValue[3], ).joinToString(","), From ea2bf7a80fc785ab117edfcd06c6512d549f61a8 Mon Sep 17 00:00:00 2001 From: leeseokchan00 <112953135+leeseokchan00@users.noreply.github.com> Date: Fri, 20 Dec 2024 19:50:40 +0900 Subject: [PATCH 10/10] [chore] #192 ktlint --- .../main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt | 2 +- feature/home/src/main/java/org/sopt/home/HomeViewModel.kt | 2 +- .../src/main/java/org/sopt/maincontainer/MainActivity.kt | 4 ++-- .../src/main/java/org/sopt/maincontainer/MainViewModel.kt | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt b/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt index d24cb0ec..b0594413 100644 --- a/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt +++ b/feature/clip/src/main/java/org/sopt/clip/DeleteLinkBottomSheetFragment.kt @@ -38,7 +38,7 @@ class DeleteLinkBottomSheetFragment() : } if (clipId?.toInt() == 0) { binding.tvDeleteLinkChange.isVisible = false - binding.testCoach.isVisible=false + binding.testCoach.isVisible = false } binding.ivDeleteLinkBottomSheetClose.setOnClickListener { diff --git a/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt b/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt index 70b0b105..b79d2724 100644 --- a/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt +++ b/feature/home/src/main/java/org/sopt/home/HomeViewModel.kt @@ -176,7 +176,7 @@ class HomeViewModel @Inject constructor( } } - fun setToolTip() =viewModelScope.launch { + fun setToolTip() = viewModelScope.launch { dataStore.setTooltip(listOf(true, true, true, true).joinToString(",")) } diff --git a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainActivity.kt b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainActivity.kt index df34c952..0c144f9f 100644 --- a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainActivity.kt +++ b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainActivity.kt @@ -161,8 +161,8 @@ class MainActivity : AppCompatActivity() { if (item.isNullOrEmpty()) return val pasteData = item.toString() - Log.d("recentLink","${viewModel.container.stateFlow.value.clipboard} ${pasteData}") - if (pasteData== viewModel.container.stateFlow.value.clipboard) return + Log.d("recentLink", "${viewModel.container.stateFlow.value.clipboard} $pasteData") + if (pasteData == viewModel.container.stateFlow.value.clipboard) return viewModel.updateClipBoard(pasteData) hideKeyBoard() diff --git a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt index 4eebbcec..c173be46 100644 --- a/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt +++ b/feature/maincontainer/src/main/java/org/sopt/maincontainer/MainViewModel.kt @@ -52,9 +52,9 @@ class MainViewModel @Inject constructor( dataStore.setRecentLink(clipboard) } - fun getRecentLink() =intent { + fun getRecentLink() = intent { if (dataStore.flowRecentLink().first().isNullOrEmpty()) return@intent - val clipboard=dataStore.flowRecentLink().first() + val clipboard = dataStore.flowRecentLink().first() reduce { state.copy(clipboard = clipboard) }