feat(posts, communities): add haptic feedback

This commit is contained in:
Diego Beraldin 2023-08-10 15:58:36 +02:00
parent c26ad24358
commit f2e763de14
11 changed files with 82 additions and 3 deletions

View File

@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MainApplication"
android:allowBackup="false"
@ -17,4 +15,7 @@
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@ -1,6 +1,7 @@
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail
import cafe.adriel.voyager.core.model.ScreenModel
import com.github.diegoberaldin.racconforlemmy.core.utils.HapticFeedback
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
import com.github.diegoberaldin.raccoonforlemmy.core.preferences.KeyStoreKeys
@ -21,6 +22,7 @@ class CommunityDetailViewModel(
private val identityRepository: IdentityRepository,
private val postsRepository: PostsRepository,
private val keyStore: TemporaryKeyStore,
private val hapticFeedback: HapticFeedback,
) : MviModel<CommunityDetailMviModel.Intent, CommunityDetailMviModel.UiState, CommunityDetailMviModel.Effect> by mvi,
ScreenModel {
private var currentPage: Int = 1
@ -97,6 +99,7 @@ class CommunityDetailViewModel(
}
private fun upVotePost(post: PostModel, value: Boolean) {
hapticFeedback.vibrate()
val newPost = postsRepository.asUpVoted(post, value)
mvi.updateState {
it.copy(
@ -135,6 +138,7 @@ class CommunityDetailViewModel(
}
private fun downVotePost(post: PostModel, value: Boolean) {
hapticFeedback.vibrate()
val newPost = postsRepository.asDownVoted(post, value)
mvi.updateState {
it.copy(
@ -173,6 +177,7 @@ class CommunityDetailViewModel(
}
private fun savePost(post: PostModel, value: Boolean) {
hapticFeedback.vibrate()
val newPost = postsRepository.asSaved(post, value)
mvi.updateState {
it.copy(

View File

@ -17,6 +17,7 @@ val commonUiModule = module {
commentRepository = get(),
keyStore = get(),
notificationCenter = get(),
hapticFeedback = get(),
)
}
factory { params ->
@ -26,6 +27,7 @@ val commonUiModule = module {
identityRepository = get(),
postsRepository = get(),
keyStore = get(),
hapticFeedback = get(),
)
}
}

View File

@ -1,6 +1,7 @@
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail
import cafe.adriel.voyager.core.model.ScreenModel
import com.github.diegoberaldin.racconforlemmy.core.utils.HapticFeedback
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenter
@ -24,6 +25,7 @@ class PostDetailViewModel(
private val commentRepository: CommentRepository,
private val keyStore: TemporaryKeyStore,
private val notificationCenter: NotificationCenter,
private val hapticFeedback: HapticFeedback,
) : MviModel<PostDetailMviModel.Intent, PostDetailMviModel.UiState, PostDetailMviModel.Effect> by mvi,
ScreenModel {
private var currentPage: Int = 1
@ -114,6 +116,7 @@ class PostDetailViewModel(
}
private fun upVotePost(post: PostModel, value: Boolean) {
hapticFeedback.vibrate()
val newPost = postsRepository.asUpVoted(post, value)
mvi.updateState { it.copy(post = newPost) }
mvi.scope.launch(Dispatchers.IO) {
@ -133,6 +136,7 @@ class PostDetailViewModel(
}
private fun downVotePost(post: PostModel, value: Boolean) {
hapticFeedback.vibrate()
val newPost = postsRepository.asDownVoted(post, value)
mvi.updateState { it.copy(post = newPost) }
@ -153,6 +157,7 @@ class PostDetailViewModel(
}
private fun savePost(post: PostModel, value: Boolean) {
hapticFeedback.vibrate()
val newPost = postsRepository.asSaved(post, value)
mvi.updateState { it.copy(post = newPost) }
mvi.scope.launch(Dispatchers.IO) {
@ -172,6 +177,7 @@ class PostDetailViewModel(
}
private fun upVoteComment(comment: CommentModel, value: Boolean) {
hapticFeedback.vibrate()
val newComment = commentRepository.asUpVoted(comment, value)
mvi.updateState {
it.copy(
@ -211,6 +217,7 @@ class PostDetailViewModel(
}
private fun downVoteComment(comment: CommentModel, value: Boolean) {
hapticFeedback.vibrate()
val newComment = commentRepository.asDownVoted(comment, value)
mvi.updateState {
it.copy(
@ -250,6 +257,7 @@ class PostDetailViewModel(
}
private fun saveComment(comment: CommentModel, value: Boolean) {
hapticFeedback.vibrate()
val newComment = commentRepository.asSaved(comment, value)
mvi.updateState {
it.copy(

View File

@ -0,0 +1,25 @@
package com.github.diegoberaldin.racconforlemmy.core.utils
import android.annotation.SuppressLint
import android.content.Context
import android.os.VibrationEffect
import android.os.Vibrator
import org.koin.dsl.module
class DefaultHapticFeedback(
private val context: Context,
) : HapticFeedback {
@SuppressLint("MissingPermission")
override fun vibrate() {
val vibrator = context.getSystemService(Vibrator::class.java)
vibrator.vibrate(VibrationEffect.createOneShot(50L, VibrationEffect.DEFAULT_AMPLITUDE))
}
}
actual val hapticFeedbackModule = module {
single<HapticFeedback> {
DefaultHapticFeedback(
context = get(),
)
}
}

View File

@ -0,0 +1,9 @@
package com.github.diegoberaldin.racconforlemmy.core.utils
import org.koin.core.module.Module
interface HapticFeedback {
fun vibrate()
}
expect val hapticFeedbackModule: Module

View File

@ -0,0 +1,19 @@
package com.github.diegoberaldin.racconforlemmy.core.utils
import org.koin.dsl.module
import platform.UIKit.UIImpactFeedbackGenerator
class DefaultHapticFeedback() : HapticFeedback {
override fun vibrate() {
UIImpactFeedbackGenerator().apply {
prepare()
impactOccurred()
}
}
}
actual val hapticFeedbackModule = module {
single<HapticFeedback> {
DefaultHapticFeedback()
}
}

View File

@ -3,8 +3,8 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.home.di
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.commonUiModule
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.di.postsRepositoryModule
import com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist.PostListViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist.PostListMviModel
import com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist.PostListViewModel
import org.koin.dsl.module
val homeTabModule = module {
@ -20,6 +20,7 @@ val homeTabModule = module {
identityRepository = get(),
keyStore = get(),
notificationCenter = get(),
hapticFeedback = get(),
)
}
}

View File

@ -1,6 +1,7 @@
package com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist
import cafe.adriel.voyager.core.model.ScreenModel
import com.github.diegoberaldin.racconforlemmy.core.utils.HapticFeedback
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenter
@ -29,6 +30,7 @@ class PostListViewModel(
private val identityRepository: IdentityRepository,
private val keyStore: TemporaryKeyStore,
private val notificationCenter: NotificationCenter,
private val hapticFeedback: HapticFeedback,
) : ScreenModel,
MviModel<PostListMviModel.Intent, PostListMviModel.UiState, PostListMviModel.Effect> by mvi {
@ -143,6 +145,7 @@ class PostListViewModel(
}
private fun upVote(post: PostModel, value: Boolean) {
hapticFeedback.vibrate()
val newPost = postsRepository.asUpVoted(post, value)
mvi.updateState {
it.copy(
@ -181,6 +184,7 @@ class PostListViewModel(
}
private fun downVote(post: PostModel, value: Boolean) {
hapticFeedback.vibrate()
val newPost = postsRepository.asDownVoted(post, value)
mvi.updateState {
it.copy(
@ -219,6 +223,7 @@ class PostListViewModel(
}
private fun save(post: PostModel, value: Boolean) {
hapticFeedback.vibrate()
val newPost = postsRepository.asSaved(post, value)
mvi.updateState {
it.copy(

View File

@ -1,5 +1,6 @@
package com.github.diegoberaldin.raccoonforlemmy
import com.github.diegoberaldin.racconforlemmy.core.utils.hapticFeedbackModule
import com.github.diegoberaldin.raccoonforlemmy.core.api.di.coreApiModule
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.coreAppearanceModule
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.di.coreNotificationModule
@ -20,6 +21,7 @@ val sharedHelperModule = module {
coreApiModule,
coreIdentityModule,
coreNotificationModule,
hapticFeedbackModule,
localizationModule,
homeTabModule,
inboxTabModule,

View File

@ -1,5 +1,6 @@
package com.github.diegoberaldin.raccoonforlemmy
import com.github.diegoberaldin.racconforlemmy.core.utils.hapticFeedbackModule
import com.github.diegoberaldin.raccoonforlemmy.core.api.di.coreApiModule
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.coreAppearanceModule
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.di.coreNotificationModule
@ -21,6 +22,7 @@ fun initKoin() {
coreApiModule,
coreIdentityModule,
coreNotificationModule,
hapticFeedbackModule,
localizationModule,
homeTabModule,
inboxTabModule,