Skip to content

Commit

Permalink
Merge pull request #1976 from pantasystem/feature/#1975/safesearch
Browse files Browse the repository at this point in the history
セーフサーチを実装した
  • Loading branch information
pantasystem authored Nov 19, 2023
2 parents c9a5f81 + 234cc37 commit e52e86a
Show file tree
Hide file tree
Showing 13 changed files with 184 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,17 @@ internal class MainActivityEventHandler(
collectRequestPostNotificationState()
collectDraftNoteSavedEvent()
collectCurrentPageableState()
collectEnableSafeSearchDescriptionState()
}

private fun collectCrashlyticsCollectionState() {
lifecycleScope.launch {
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
mainViewModel.isShowFirebaseCrashlytics.collect {
if (it && activity.supportFragmentManager.findFragmentByTag(ConfirmCrashlyticsDialog.FRAGMENT_TAG) == null) {
if (it && activity.supportFragmentManager.findFragmentByTag(
ConfirmCrashlyticsDialog.FRAGMENT_TAG
) == null
) {
ConfirmCrashlyticsDialog().show(
activity.supportFragmentManager,
ConfirmCrashlyticsDialog.FRAGMENT_TAG
Expand All @@ -129,11 +133,32 @@ internal class MainActivityEventHandler(
}
}

private fun collectEnableSafeSearchDescriptionState() {
lifecycleScope.launch {
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
mainViewModel.isShowEnableSafeSearchDescription.collect {
if (it && activity.supportFragmentManager.findFragmentByTag(
SafeSearchDescriptionDialog.TAG
) == null
) {
SafeSearchDescriptionDialog().show(
activity.supportFragmentManager,
SafeSearchDescriptionDialog.TAG
)
}
}
}
}
}

private fun collectConfirmGoogleAnalyticsState() {
lifecycleScope.launch {
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
mainViewModel.isShowGoogleAnalyticsDialog.collect {
if (it && activity.supportFragmentManager.findFragmentByTag(ConfirmGoogleAnalyticsDialog.FRAGMENT_TAG) == null) {
if (it && activity.supportFragmentManager.findFragmentByTag(
ConfirmGoogleAnalyticsDialog.FRAGMENT_TAG
) == null
) {
ConfirmGoogleAnalyticsDialog().show(
activity.supportFragmentManager,
ConfirmGoogleAnalyticsDialog.FRAGMENT_TAG
Expand Down Expand Up @@ -318,6 +343,7 @@ internal class MainActivityEventHandler(
CurrentPageType.Account -> {
R.drawable.ic_person_add_black_24dp
}

is CurrentPageType.Page -> {
R.drawable.ic_edit_black_24dp
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package jp.panta.misskeyandroidclient.ui.main

import android.app.Dialog
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import jp.panta.misskeyandroidclient.ui.main.viewmodel.MainViewModel
import net.pantasystem.milktea.common_resource.R
import net.pantasystem.milktea.setting.activities.SettingMovementActivity

class SafeSearchDescriptionDialog : DialogFragment() {
companion object {
const val TAG = "SafeSearchDescriptionDialog"
}

private val preferences by lazy {
requireContext().getSharedPreferences("safe_search_description_dialog", Context.MODE_PRIVATE)
}

private val mainViewModel by activityViewModels<MainViewModel>()

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.safe_search_description_dialog_title)
.setMessage(R.string.safe_search_description_dialog_message)
.setPositiveButton(R.string.safe_search_description_dialog_positive_button) { _, _ ->
val intent = Intent(requireContext(), SettingMovementActivity::class.java)
intent.putExtra(SettingMovementActivity.EXTRA_HIGHLIGHT_SAFE_SEARCH, true)
startActivity(intent)
dismiss()
}
.setNegativeButton(R.string.safe_search_description_dialog_negative_button) { _, _ ->
preferences.edit().putInt("counter", preferences.getInt("counter", 0) + 1).apply()
if (preferences.getInt("counter", 0) >= 3) {
mainViewModel.onDoNotShowSafeSearchDescription()
}
// 何もしない
dismiss()
}
.setCancelable(false)

.create()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ class MainViewModel @Inject constructor(
!(it.isEnable || it.isConfirmed)
}.distinctUntilChanged().shareIn(viewModelScope, SharingStarted.Lazily)

val isShowEnableSafeSearchDescription = settingStore.configState.map {
it.isEnableSafeSearch
}.map {
!(!it.isEnabled || it.isConfirmed)
}.distinctUntilChanged().shareIn(viewModelScope, SharingStarted.Lazily)

val isShowGoogleAnalyticsDialog = settingStore.configState.map { config ->
!(config.isAnalyticsCollectionEnabled.isEnabled
|| config.isAnalyticsCollectionEnabled.isConfirmed)
Expand Down Expand Up @@ -121,6 +127,16 @@ class MainViewModel @Inject constructor(
}
}

fun onDoNotShowSafeSearchDescription() {
viewModelScope.launch {
configRepository.get().mapCancellableCatching {
configRepository.save(it.copy(isEnableSafeSearch = it.isEnableSafeSearch.copy(isConfirmed = true)))
}.onFailure {
logger.error("設定状態の保存に失敗", it)
}
}
}

}

data class MainUiState (
Expand Down
5 changes: 5 additions & 0 deletions modules/common_resource/src/main/res/values-ja/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,11 @@
<string name="settings_user_cache">ユーザキャッシュ</string>
<string name="jump_to_new_post">新着投稿を表示</string>
<string name="exclude_if_exists_sensitive_media">センシティブなメディアを含む投稿を除外</string>
<string name="enable_safe_search">セーフサーチを有効にする</string>

<string name="safe_search_description_dialog_title">セーフサーチが有効になっています</string>
<string name="safe_search_description_dialog_message">Gogole Playのユーザコンテンツポリシーに準拠するためにセーフサーチが有効になっています。セーフサーチが有効になっていると、センシティブなメディアが含まれる投稿がタイムラインに表示されなくなります。セーフサーチを無効化するには、設定>動き>セーフサーチを有効にするをOFFにしてください。</string>
<string name="safe_search_description_dialog_positive_button">設定へ移動する</string>
<string name="safe_search_description_dialog_negative_button">セーフサーチを有効にしてお</string>

</resources>
6 changes: 5 additions & 1 deletion modules/common_resource/src/main/res/values-zh/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,10 @@
<string name="settings_user_cache">User caches</string>
<string name="jump_to_new_post">Jump to new post</string>
<string name="exclude_if_exists_sensitive_media">Exclude if exists senstive media</string>

<string name="enable_safe_search">启用安全搜索</string>
<string name="safe_search_description_dialog_title">安全搜索已启用</string>
<string name="safe_search_description_dialog_message">为遵守Google Play用户内容政策,已启用安全搜索。启用安全搜索时,包含敏感媒体的帖子将不会显示在时间线上。要禁用安全搜索,请转到设置>动作>启用安全搜索并关闭。</string>
<string name="safe_search_description_dialog_positive_button">移动到设置</string>
<string name="safe_search_description_dialog_negative_button">保持启用安全搜索</string>

</resources>
5 changes: 5 additions & 0 deletions modules/common_resource/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,11 @@
<string name="settings_user_cache">User cache</string>
<string name="jump_to_new_post">Jump to new post</string>
<string name="exclude_if_exists_sensitive_media">Exclude if exists sensitive media</string>
<string name="enable_safe_search">Enable Safe Search</string>
<string name="safe_search_description_dialog_title">Safe Search is enabled</string>
<string name="safe_search_description_dialog_message">Safe Search has been enabled to comply with Google Play\'s User Content Policy. When Safe Search is enabled, posts containing sensitive media will not be displayed on your timeline. To disable Safe Search, go to Settings > Motion > Enable Safe Search and turn it off.</string>
<string name="safe_search_description_dialog_positive_button">Go to Settings</string>
<string name="safe_search_description_dialog_negative_button">Keep Safe Search enabled</string>
<!-- reaction-acceptance -->

</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,14 @@ fun Config.Companion.from(map: Map<Keys, PrefType?>): Config {
)?.value?.let { value ->
MediaDisplayMode.values().find { it.value == value }
} ?: DefaultConfig.config.mediaDisplayMode,
excludeIfExistsSensitiveMedia = map.getValue<PrefType.BoolPref>(
Keys.ExcludeIfExistsSensitiveMedia
)?.value ?: DefaultConfig.config.excludeIfExistsSensitiveMedia,
isEnableSafeSearch = IsSafeSearchEnabled(
isEnabled = map.getValue<PrefType.BoolPref>(
Keys.IsSafeSearchEnabled
)?.value ?: DefaultConfig.config.isEnableSafeSearch.isEnabled,
isConfirmed = map.getValue<PrefType.BoolPref>(
Keys.IsConfirmedSafeSearchEnabled
)?.value ?: DefaultConfig.config.isEnableSafeSearch.isConfirmed
),
)
}

Expand Down Expand Up @@ -305,8 +310,11 @@ fun Config.pref(key: Keys): PrefType {
Keys.MediaDisplayMode -> {
PrefType.IntPref(mediaDisplayMode.value)
}
Keys.ExcludeIfExistsSensitiveMedia -> {
PrefType.BoolPref(excludeIfExistsSensitiveMedia)
Keys.IsSafeSearchEnabled -> {
PrefType.BoolPref(isEnableSafeSearch.isEnabled)
}
Keys.IsConfirmedSafeSearchEnabled -> {
PrefType.BoolPref(isEnableSafeSearch.isConfirmed)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,13 @@ class ConfigKtTest {
config.mediaDisplayMode.value,
(u as PrefType.IntPref).value
)
Keys.ExcludeIfExistsSensitiveMedia -> Assertions.assertEquals(
config.excludeIfExistsSensitiveMedia,
Keys.IsSafeSearchEnabled -> Assertions.assertEquals(
config.isEnableSafeSearch.isEnabled,
(u as PrefType.BoolPref).value
)

Keys.IsConfirmedSafeSearchEnabled -> Assertions.assertEquals(
config.isEnableSafeSearch.isConfirmed,
(u as PrefType.BoolPref).value
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,19 +129,27 @@ class KeysKtTest {
"MediaDisplayMode",
key.str()
)
Keys.ExcludeIfExistsSensitiveMedia -> Assertions.assertEquals(
Keys.IsSafeSearchEnabled -> Assertions.assertEquals(
"ExcludeIfExistsSensitiveMedia",
key.str()
)
Keys.IsSafeSearchEnabled -> Assertions.assertEquals(
"ExcludeIfExistsSensitiveMedia",
key.str()
)
Keys.IsConfirmedSafeSearchEnabled -> Assertions.assertEquals(
"IsConfirmedSafeSearchEnabled",
key.str()
)
}
}
}


@Test
fun checkAllKeysCount() {
Assertions.assertEquals(35, Keys.allKeys.size)
Assertions.assertEquals(35, Keys.allKeys.map { it.str() }.toSet().size)
Assertions.assertEquals(36, Keys.allKeys.size)
Assertions.assertEquals(36, Keys.allKeys.map { it.str() }.toSet().size)
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ExcludeIfExistsSensitiveMediaFilter(private val pageable: Pageable, privat
val config = configRepository.get().getOrElse { DefaultConfig.config }

// 除外設定がされていない場合は何もしない
if (!config.excludeIfExistsSensitiveMedia && (pageable as? CanExcludeIfExistsSensitiveMedia<*>)?.getExcludeIfExistsSensitiveMedia() != true) {
if (!config.isEnableSafeSearch.isEnabled && (pageable as? CanExcludeIfExistsSensitiveMedia<*>)?.getExcludeIfExistsSensitiveMedia() != true) {
return viewData.filterResult
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.util.Log
import android.view.MenuItem
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -46,6 +47,11 @@ import javax.inject.Inject
@AndroidEntryPoint
class SettingMovementActivity : AppCompatActivity() {

companion object {
const val EXTRA_HIGHLIGHT_SAFE_SEARCH = "EXTRA_HIGHLIGHT_SAFE_SEARCH"

}


@Inject
lateinit var accountStore: AccountStore
Expand All @@ -62,6 +68,8 @@ class SettingMovementActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
applyTheme()

val isHighlightSafeSearch = intent.getBooleanExtra(EXTRA_HIGHLIGHT_SAFE_SEARCH, false)
setContent {
val configState by settingStore.configState.collectAsState()
val currentAccount by accountStore.observeCurrentAccount.collectAsState(initial = null)
Expand Down Expand Up @@ -143,13 +151,22 @@ class SettingMovementActivity : AppCompatActivity() {
}

SettingSwitchTile(
checked = currentConfigState.excludeIfExistsSensitiveMedia,
checked = currentConfigState.isEnableSafeSearch.isEnabled,
modifier = Modifier.then(
if (isHighlightSafeSearch)
Modifier.background(MaterialTheme.colors.primary.copy(alpha = 0.2f))
else Modifier
),
onChanged = {
currentConfigState =
currentConfigState.copy(excludeIfExistsSensitiveMedia = it)
currentConfigState.copy(
isEnableSafeSearch = currentConfigState.isEnableSafeSearch.copy(
isEnabled = it
),
)
},
) {
Text(text = stringResource(id = R.string.exclude_if_exists_sensitive_media))
Text(text = stringResource(id = R.string.enable_safe_search))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ data class IsAnalyticsCollectionEnabled(
val isConfirmed: Boolean,
)

data class IsSafeSearchEnabled(
val isEnabled: Boolean,
val isConfirmed: Boolean,
)

/**
* @param isSimpleEditorEnabled シンプルエディターを使用するのか
* @param reactionPickerType リアクションピッカーの種別 
Expand Down Expand Up @@ -88,7 +93,7 @@ data class Config(
val emojiPickerEmojiDisplaySize: Int,
val avatarIconShapeType: AvatarIconShapeType,
val mediaDisplayMode: MediaDisplayMode,
val excludeIfExistsSensitiveMedia: Boolean,
val isEnableSafeSearch: IsSafeSearchEnabled,
) {
companion object

Expand All @@ -109,6 +114,15 @@ data class Config(
)
)
}

fun setSafeSearchEnabled(enabled: Boolean): Config {
return copy(
isEnableSafeSearch = IsSafeSearchEnabled(
isEnabled = enabled,
isConfirmed = true
)
)
}
}

object DefaultConfig {
Expand Down Expand Up @@ -151,7 +165,10 @@ object DefaultConfig {
emojiPickerEmojiDisplaySize = 28,
avatarIconShapeType = AvatarIconShapeType.Circle,
mediaDisplayMode = MediaDisplayMode.AUTO,
excludeIfExistsSensitiveMedia = false,
isEnableSafeSearch =IsSafeSearchEnabled(
isEnabled = true,
isConfirmed = false,
),
)

fun getRememberVisibilityConfig(accountId: Long): RememberVisibility.Remember {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ val Keys.Companion.allKeys by lazy {
Keys.EmojiPickerEmojiDisplaySize,
Keys.AvatarIconShapeType,
Keys.MediaDisplayMode,
Keys.ExcludeIfExistsSensitiveMedia,
Keys.IsSafeSearchEnabled,
Keys.IsConfirmedSafeSearchEnabled,
)
}

Expand Down Expand Up @@ -104,7 +105,9 @@ sealed interface Keys {

data object MediaDisplayMode : Keys

data object ExcludeIfExistsSensitiveMedia : Keys
data object IsSafeSearchEnabled : Keys

data object IsConfirmedSafeSearchEnabled : Keys

companion object
}
Expand Down Expand Up @@ -145,6 +148,7 @@ fun Keys.str(): String {
is Keys.EmojiPickerEmojiDisplaySize -> "EmojiPickerEmojiDisplaySize"
is Keys.AvatarIconShapeType -> "AvatarIconShapeType"
is Keys.MediaDisplayMode -> "MediaDisplayMode"
is Keys.ExcludeIfExistsSensitiveMedia -> "ExcludeIfExistsSensitiveMedia"
is Keys.IsSafeSearchEnabled -> "ExcludeIfExistsSensitiveMedia"
is Keys.IsConfirmedSafeSearchEnabled -> "IsConfirmedSafeSearchEnabled"
}
}

0 comments on commit e52e86a

Please sign in to comment.