From b47e1ae8b01411c631b0b66d05c23176a82f17a9 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 01:35:12 +0900 Subject: [PATCH 01/14] =?UTF-8?q?AppRepositoryImpl=E3=81=AE=E3=82=B3?= =?UTF-8?q?=E3=83=B3=E3=82=B9=E3=83=88=E3=83=A9=E3=82=AF=E3=82=BF=E3=81=A7?= =?UTF-8?q?PackageManager=E3=82=92DI=E3=81=99=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/me/nya_n/notificationnotifier/App.kt | 6 +++--- .../data/repository/AppRepository.kt | 3 +-- .../data/repository/impl/AppRepositoryImpl.kt | 7 ++++--- .../java/me/nya_n/notificationnotifier/UseCaseTest.kt | 8 +++----- .../domain/usecase/LoadAppUseCase.kt | 3 +-- .../domain/usecase/dummy/LoadAppUseCaseDummyImpl.kt | 3 +-- .../domain/usecase/impl/LoadAppUseCaseImpl.kt | 9 ++++----- .../ui/screen/selection/SelectionViewModel.kt | 7 +------ .../ui/screen/target/TargetViewModel.kt | 5 +---- 9 files changed, 19 insertions(+), 32 deletions(-) diff --git a/AndroidApp/app/src/main/kotlin/me/nya_n/notificationnotifier/App.kt b/AndroidApp/app/src/main/kotlin/me/nya_n/notificationnotifier/App.kt index 5865ba0e..51795ce1 100644 --- a/AndroidApp/app/src/main/kotlin/me/nya_n/notificationnotifier/App.kt +++ b/AndroidApp/app/src/main/kotlin/me/nya_n/notificationnotifier/App.kt @@ -81,13 +81,13 @@ class App : Application() { // Repository single { UserSettingsRepositoryImpl(get()) } - single { AppRepositoryImpl(get(), get()) } + single { AppRepositoryImpl(applicationContext.packageManager, get(), get()) } // ViewModel viewModel { AppViewModel(get(), packageName, get(), get()) } - viewModel { SelectionViewModel(get(), get(), get()) } + viewModel { SelectionViewModel(get(), get()) } viewModel { params -> DetailViewModel(get(), get(), get(), get(), params.get()) } - viewModel { TargetViewModel(get(), get()) } + viewModel { TargetViewModel(get()) } viewModel { SettingsViewModel(get(), get(), get(), get(), get(), get()) } // UseCase diff --git a/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/AppRepository.kt b/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/AppRepository.kt index 83aed6ad..681372f2 100644 --- a/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/AppRepository.kt +++ b/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/AppRepository.kt @@ -1,6 +1,5 @@ package me.nya_n.notificationnotifier.data.repository -import android.content.pm.PackageManager import me.nya_n.notificationnotifier.model.FilterCondition import me.nya_n.notificationnotifier.model.InstalledApp @@ -23,5 +22,5 @@ interface AppRepository { suspend fun deleteTargetApp(target: InstalledApp) - fun loadInstalledAppList(pm: PackageManager): List + fun loadInstalledAppList(): List } \ No newline at end of file diff --git a/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/impl/AppRepositoryImpl.kt b/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/impl/AppRepositoryImpl.kt index 8bd590af..57af1d6a 100644 --- a/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/impl/AppRepositoryImpl.kt +++ b/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/impl/AppRepositoryImpl.kt @@ -11,6 +11,7 @@ import me.nya_n.notificationnotifier.model.FilterCondition import me.nya_n.notificationnotifier.model.InstalledApp class AppRepositoryImpl( + private val packageManager: PackageManager, private val filterConditionDao: FilterConditionDao, private val targetAppDao: TargetAppDao, private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO @@ -62,10 +63,10 @@ class AppRepositoryImpl( } } - override fun loadInstalledAppList(pm: PackageManager): List { - return pm.getInstalledApplications(PackageManager.GET_META_DATA) + override fun loadInstalledAppList(): List { + return packageManager.getInstalledApplications(PackageManager.GET_META_DATA) .map { - val label = pm.getApplicationLabel(it).toString() + val label = packageManager.getApplicationLabel(it).toString() InstalledApp( label, it.packageName diff --git a/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt b/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt index 26815640..87de8390 100644 --- a/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt +++ b/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt @@ -1,7 +1,6 @@ package me.nya_n.notificationnotifier import android.content.Context -import android.content.pm.PackageManager import android.net.Uri import androidx.core.content.edit import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -57,7 +56,6 @@ class UseCaseTest { @OptIn(ExperimentalCoroutinesApi::class) private val testDispatcher = UnconfinedTestDispatcher() private lateinit var appContext: Context - private lateinit var pm: PackageManager private lateinit var exportFile: File private lateinit var addTargetAppUseCase: AddTargetAppUseCase @@ -82,7 +80,6 @@ class UseCaseTest { delete() } } - pm = appContext.packageManager val userSettingsRepository = UserSettingsRepositoryImpl( UserSettingsDataStore( SharedPreferenceProvider.create( @@ -99,6 +96,7 @@ class UseCaseTest { clearAllTables() } val appRepository = AppRepositoryImpl( + appContext.packageManager, db.filterConditionDao(), db.targetAppDao(), testDispatcher @@ -139,7 +137,7 @@ class UseCaseTest { @Test fun `インストール済みアプリの取得_成功(ついでにアプリ一覧取得権限許可処理も)`() { packageVisibilityGrantedUseCase() - val ret = loadAppUseCase.loadInstalledAppList(pm) + val ret = loadAppUseCase.loadInstalledAppList() assertThat(ret.getOrNull()).apply { isNotNull() isNotEmpty() @@ -148,7 +146,7 @@ class UseCaseTest { @Test fun `インストール済みアプリの取得_失敗`() { - val ret = loadAppUseCase.loadInstalledAppList(pm) + val ret = loadAppUseCase.loadInstalledAppList() assertThat(ret.exceptionOrNull()).apply { isNotNull() isInstanceOf(PermissionDeniedException::class.java) diff --git a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/LoadAppUseCase.kt b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/LoadAppUseCase.kt index 1d4ac0cf..b6773e8b 100644 --- a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/LoadAppUseCase.kt +++ b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/LoadAppUseCase.kt @@ -1,10 +1,9 @@ package me.nya_n.notificationnotifier.domain.usecase -import android.content.pm.PackageManager import me.nya_n.notificationnotifier.model.InstalledApp interface LoadAppUseCase { - suspend operator fun invoke(pm: PackageManager): Result + suspend operator fun invoke(): Result data class Outputs( val notTargets: List, diff --git a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/dummy/LoadAppUseCaseDummyImpl.kt b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/dummy/LoadAppUseCaseDummyImpl.kt index 4353f47e..18abcb34 100644 --- a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/dummy/LoadAppUseCaseDummyImpl.kt +++ b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/dummy/LoadAppUseCaseDummyImpl.kt @@ -1,11 +1,10 @@ package me.nya_n.notificationnotifier.domain.usecase.dummy -import android.content.pm.PackageManager import me.nya_n.notificationnotifier.domain.usecase.LoadAppUseCase import me.nya_n.notificationnotifier.model.InstalledApp class LoadAppUseCaseDummyImpl : LoadAppUseCase { - override suspend fun invoke(pm: PackageManager): Result { + override suspend fun invoke(): Result { return Result.success( LoadAppUseCase.Outputs( listOf( diff --git a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/impl/LoadAppUseCaseImpl.kt b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/impl/LoadAppUseCaseImpl.kt index 9d3a11ce..9d36fa94 100644 --- a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/impl/LoadAppUseCaseImpl.kt +++ b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/impl/LoadAppUseCaseImpl.kt @@ -1,6 +1,5 @@ package me.nya_n.notificationnotifier.domain.usecase.impl -import android.content.pm.PackageManager import androidx.annotation.VisibleForTesting import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers @@ -18,9 +17,9 @@ class LoadAppUseCaseImpl( private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO ) : LoadAppUseCase { - override suspend operator fun invoke(pm: PackageManager): Result = + override suspend operator fun invoke(): Result = withContext(coroutineDispatcher) { - val apps = loadInstalledAppList(pm).getOrElse { + val apps = loadInstalledAppList().getOrElse { return@withContext Result.failure(it) } val targets = loadTargetList() @@ -28,12 +27,12 @@ class LoadAppUseCaseImpl( } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - fun loadInstalledAppList(pm: PackageManager): Result> { + fun loadInstalledAppList(): Result> { val settings = userSettingsRepository.getUserSettings() return if (!settings.isPackageVisibilityGranted) { Result.failure(AppException.PermissionDeniedException()) } else { - Result.success(appRepository.loadInstalledAppList(pm)) + Result.success(appRepository.loadInstalledAppList()) } } diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/selection/SelectionViewModel.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/selection/SelectionViewModel.kt index 4740881f..6d474865 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/selection/SelectionViewModel.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/selection/SelectionViewModel.kt @@ -1,7 +1,5 @@ package me.nya_n.notificationnotifier.ui.screen.selection -import android.content.Context -import android.content.pm.PackageManager import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableStateFlow @@ -16,12 +14,9 @@ import me.nya_n.notificationnotifier.model.Message import me.nya_n.notificationnotifier.ui.R class SelectionViewModel( - context: Context, private val loadAppUseCase: LoadAppUseCase, private val addTargetAppUseCase: AddTargetAppUseCase ) : ViewModel() { - private val pm: PackageManager = context.packageManager - private val _uiState = MutableStateFlow(UiState()) val uiState: StateFlow = _uiState.asStateFlow() @@ -32,7 +27,7 @@ class SelectionViewModel( // 未読込の場合だけプログレスバーを表示 _uiState.update { it.copy(isLoading = true) } } - loadAppUseCase(pm).onSuccess { res -> + loadAppUseCase().onSuccess { res -> val query = uiState.value.query val items = res.notTargets .filter { app -> app.label.contains(query) || app.packageName.contains(query) } diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/target/TargetViewModel.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/target/TargetViewModel.kt index 244ab6e2..19374071 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/target/TargetViewModel.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/target/TargetViewModel.kt @@ -1,6 +1,5 @@ package me.nya_n.notificationnotifier.ui.screen.target -import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableStateFlow @@ -12,10 +11,8 @@ import me.nya_n.notificationnotifier.domain.usecase.LoadAppUseCase import me.nya_n.notificationnotifier.model.Message class TargetViewModel( - context: Context, private val useCase: LoadAppUseCase ) : ViewModel() { - private val pm = context.packageManager private val _uiState = MutableStateFlow(UiState()) val uiState: StateFlow = _uiState.asStateFlow() @@ -26,7 +23,7 @@ class TargetViewModel( // 未読込の場合だけプログレスバーを表示 _uiState.update { it.copy(isLoading = true) } } - useCase(pm).onSuccess { res -> + useCase().onSuccess { res -> _uiState.update { it.copy(items = res.targets) } } _uiState.update { it.copy(isLoading = false) } From 1019a4848c0d958793320b0adcd9735a49f9f629 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 01:55:04 +0900 Subject: [PATCH 02/14] =?UTF-8?q?import/export=E3=81=AEUseCase#invoke?= =?UTF-8?q?=E3=82=92context=E4=B8=8D=E8=A6=81=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../me/nya_n/notificationnotifier/App.kt | 7 ++-- .../data/repository/BackupRepository.kt | 17 +++++++++ .../repository/impl/BackupRepositoryImpl.kt | 35 +++++++++++++++++++ .../domain/usecase/ExportDataUseCase.kt | 3 +- .../domain/usecase/ImportDataUseCase.kt | 3 +- .../usecase/impl/ExportDataUseCaseImpl.kt | 15 +++----- .../usecase/impl/ImportDataUseCaseImpl.kt | 21 +++-------- 7 files changed, 67 insertions(+), 34 deletions(-) create mode 100644 AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/BackupRepository.kt create mode 100644 AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/impl/BackupRepositoryImpl.kt diff --git a/AndroidApp/app/src/main/kotlin/me/nya_n/notificationnotifier/App.kt b/AndroidApp/app/src/main/kotlin/me/nya_n/notificationnotifier/App.kt index 51795ce1..01611226 100644 --- a/AndroidApp/app/src/main/kotlin/me/nya_n/notificationnotifier/App.kt +++ b/AndroidApp/app/src/main/kotlin/me/nya_n/notificationnotifier/App.kt @@ -2,8 +2,10 @@ package me.nya_n.notificationnotifier import android.app.Application import me.nya_n.notificationnotifier.data.repository.AppRepository +import me.nya_n.notificationnotifier.data.repository.BackupRepository import me.nya_n.notificationnotifier.data.repository.UserSettingsRepository import me.nya_n.notificationnotifier.data.repository.impl.AppRepositoryImpl +import me.nya_n.notificationnotifier.data.repository.impl.BackupRepositoryImpl import me.nya_n.notificationnotifier.data.repository.impl.UserSettingsRepositoryImpl import me.nya_n.notificationnotifier.data.repository.source.DB import me.nya_n.notificationnotifier.data.repository.source.UserSettingsDataStore @@ -82,6 +84,7 @@ class App : Application() { // Repository single { UserSettingsRepositoryImpl(get()) } single { AppRepositoryImpl(applicationContext.packageManager, get(), get()) } + single { BackupRepositoryImpl(applicationContext) } // ViewModel viewModel { AppViewModel(get(), packageName, get(), get()) } @@ -93,8 +96,8 @@ class App : Application() { // UseCase factory { AddTargetAppUseCaseImpl(get()) } factory { DeleteTargetAppUseCaseImpl(get()) } - factory { ExportDataUseCaseImpl(get(), get()) } - factory { ImportDataUseCaseImpl(get(), get()) } + factory { ExportDataUseCaseImpl(get(), get(), get()) } + factory { ImportDataUseCaseImpl(get(), get(), get()) } factory { LoadAddressUseCaseImpl(get()) } factory { LoadAppUseCaseImpl(get(), get()) } factory { LoadFilterConditionUseCaseImpl(get()) } diff --git a/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/BackupRepository.kt b/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/BackupRepository.kt new file mode 100644 index 00000000..4591a16b --- /dev/null +++ b/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/BackupRepository.kt @@ -0,0 +1,17 @@ +package me.nya_n.notificationnotifier.data.repository + +import android.net.Uri + +interface BackupRepository { + /** [uri]に通知対象や条件、設定を保存 + * @param uri 保存先 + * @param data 保存するデータ + */ + suspend fun exportToUri(uri: Uri, data: String) + + /** [uri]から通知対象や条件、設定を復元 + * @param uri 読み込み元 + * @return 復元したデータ + */ + suspend fun importFromUri(uri: Uri): String +} \ No newline at end of file diff --git a/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/impl/BackupRepositoryImpl.kt b/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/impl/BackupRepositoryImpl.kt new file mode 100644 index 00000000..222487e9 --- /dev/null +++ b/AndroidApp/data/repository/src/main/kotlin/me/nya_n/notificationnotifier/data/repository/impl/BackupRepositoryImpl.kt @@ -0,0 +1,35 @@ +package me.nya_n.notificationnotifier.data.repository.impl + +import android.content.Context +import android.net.Uri +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import me.nya_n.notificationnotifier.data.repository.BackupRepository +import java.io.BufferedReader +import java.io.InputStreamReader + +class BackupRepositoryImpl( + private val context: Context, + private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO +) : BackupRepository { + override suspend fun exportToUri(uri: Uri, data: String) { + withContext(coroutineDispatcher) { + context.contentResolver.openOutputStream(uri)?.use { + it.write(data.toByteArray()) + } ?: throw RuntimeException("Failed to open output stream.") + } + } + + override suspend fun importFromUri(uri: Uri): String { + val sb = StringBuilder() + withContext(coroutineDispatcher) { + context.contentResolver.openInputStream(uri)?.use { input -> + BufferedReader(InputStreamReader(input)).use { reader -> + sb.append(reader.readLine()) + } ?: throw RuntimeException("Failed to read input stream.") + } ?: throw RuntimeException("Failed to open input stream.") + } + return sb.toString() + } +} \ No newline at end of file diff --git a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/ExportDataUseCase.kt b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/ExportDataUseCase.kt index 40654349..7b884da7 100644 --- a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/ExportDataUseCase.kt +++ b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/ExportDataUseCase.kt @@ -1,9 +1,8 @@ package me.nya_n.notificationnotifier.domain.usecase -import android.content.Context import android.net.Uri /** バックアップのために外部ストレージにデータを保存 */ interface ExportDataUseCase { - suspend operator fun invoke(context: Context, uri: Uri): Result + suspend operator fun invoke(uri: Uri): Result } \ No newline at end of file diff --git a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/ImportDataUseCase.kt b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/ImportDataUseCase.kt index 359c5568..7086df0e 100644 --- a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/ImportDataUseCase.kt +++ b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/ImportDataUseCase.kt @@ -1,9 +1,8 @@ package me.nya_n.notificationnotifier.domain.usecase -import android.content.Context import android.net.Uri /** 外部ストレージのバックアップからデータを復元 */ interface ImportDataUseCase { - suspend operator fun invoke(context: Context, uri: Uri): Result + suspend operator fun invoke(uri: Uri): Result } \ No newline at end of file diff --git a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/impl/ExportDataUseCaseImpl.kt b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/impl/ExportDataUseCaseImpl.kt index 6d80df50..b8d5454c 100644 --- a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/impl/ExportDataUseCaseImpl.kt +++ b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/impl/ExportDataUseCaseImpl.kt @@ -1,12 +1,9 @@ package me.nya_n.notificationnotifier.domain.usecase.impl -import android.content.Context import android.net.Uri import com.google.gson.Gson -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext import me.nya_n.notificationnotifier.data.repository.AppRepository +import me.nya_n.notificationnotifier.data.repository.BackupRepository import me.nya_n.notificationnotifier.data.repository.UserSettingsRepository import me.nya_n.notificationnotifier.data.repository.source.DB import me.nya_n.notificationnotifier.domain.usecase.ExportDataUseCase @@ -15,9 +12,9 @@ import me.nya_n.notificationnotifier.model.Backup class ExportDataUseCaseImpl( private val userSettingsRepository: UserSettingsRepository, private val appRepository: AppRepository, - private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO + private val backupRepository: BackupRepository, ) : ExportDataUseCase { - override suspend operator fun invoke(context: Context, uri: Uri): Result { + override suspend operator fun invoke(uri: Uri): Result { return runCatching { val data = Backup( userSettingsRepository.getUserSettings(), @@ -26,11 +23,7 @@ class ExportDataUseCaseImpl( appRepository.getFilterConditionList() ) val json = Gson().toJson(data) - withContext(coroutineDispatcher) { - context.contentResolver.openOutputStream(uri).use { - it?.write(json.toByteArray()) - } - } + backupRepository.exportToUri(uri, json) } } } \ No newline at end of file diff --git a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/impl/ImportDataUseCaseImpl.kt b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/impl/ImportDataUseCaseImpl.kt index d3d3bba2..858c3f3a 100644 --- a/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/impl/ImportDataUseCaseImpl.kt +++ b/AndroidApp/domain/src/main/kotlin/me/nya_n/notificationnotifier/domain/usecase/impl/ImportDataUseCaseImpl.kt @@ -1,35 +1,22 @@ package me.nya_n.notificationnotifier.domain.usecase.impl -import android.content.Context import android.net.Uri import com.google.gson.Gson -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext import me.nya_n.notificationnotifier.data.repository.AppRepository +import me.nya_n.notificationnotifier.data.repository.BackupRepository import me.nya_n.notificationnotifier.data.repository.UserSettingsRepository import me.nya_n.notificationnotifier.data.repository.source.DB import me.nya_n.notificationnotifier.domain.usecase.ImportDataUseCase import me.nya_n.notificationnotifier.model.Backup -import java.io.BufferedReader -import java.io.InputStreamReader class ImportDataUseCaseImpl( private val userSettingsRepository: UserSettingsRepository, private val appRepository: AppRepository, - private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO + private val backupRepository: BackupRepository, ) : ImportDataUseCase { - override suspend operator fun invoke(context: Context, uri: Uri): Result { + override suspend operator fun invoke(uri: Uri): Result { return runCatching { - val sb = StringBuilder() - withContext(coroutineDispatcher) { - context.contentResolver.openInputStream(uri).use { input -> - BufferedReader(InputStreamReader(input)).use { reader -> - sb.append(reader.readLine()) - } - } - } - val json = sb.toString() + val json = backupRepository.importFromUri(uri) val backup = Gson().fromJson(json, Backup::class.java) if (backup.version != DB.version()) { throw RuntimeException("bad version.") From 13e963f0f2fdc2baec1987834c8fa2e3f7601d73 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 01:55:12 +0900 Subject: [PATCH 03/14] =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../me/nya_n/notificationnotifier/UseCaseTest.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt b/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt index 87de8390..ab29b4f4 100644 --- a/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt +++ b/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt @@ -1,6 +1,5 @@ package me.nya_n.notificationnotifier -import android.content.Context import android.net.Uri import androidx.core.content.edit import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -10,6 +9,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import me.nya_n.notificationnotifier.data.repository.impl.AppRepositoryImpl +import me.nya_n.notificationnotifier.data.repository.impl.BackupRepositoryImpl import me.nya_n.notificationnotifier.data.repository.impl.UserSettingsRepositoryImpl import me.nya_n.notificationnotifier.data.repository.source.DB import me.nya_n.notificationnotifier.data.repository.source.UserSettingsDataStore @@ -55,7 +55,6 @@ class UseCaseTest { @OptIn(ExperimentalCoroutinesApi::class) private val testDispatcher = UnconfinedTestDispatcher() - private lateinit var appContext: Context private lateinit var exportFile: File private lateinit var addTargetAppUseCase: AddTargetAppUseCase @@ -73,7 +72,7 @@ class UseCaseTest { @Before fun setUp() { - appContext = InstrumentationRegistry.getInstrumentation().targetContext + val appContext = InstrumentationRegistry.getInstrumentation().targetContext exportFile = appContext.filesDir File(exportFile, ExportFileName).apply { if (exists()) { @@ -101,6 +100,7 @@ class UseCaseTest { db.targetAppDao(), testDispatcher ) + val backupRepository = BackupRepositoryImpl(appContext, testDispatcher) addTargetAppUseCase = AddTargetAppUseCaseImpl(appRepository) loadAppUseCase = LoadAppUseCaseImpl(userSettingsRepository, appRepository, testDispatcher) deleteTargetAppUseCase = DeleteTargetAppUseCaseImpl(appRepository) @@ -113,9 +113,9 @@ class UseCaseTest { loadAddressUseCase = LoadAddressUseCaseImpl(userSettingsRepository) notifyUseCase = NotifyUseCaseImpl(userSettingsRepository, testDispatcher) exportDataUseCase = - ExportDataUseCaseImpl(userSettingsRepository, appRepository, testDispatcher) + ExportDataUseCaseImpl(userSettingsRepository, appRepository, backupRepository) importDataUseCase = - ImportDataUseCaseImpl(userSettingsRepository, appRepository, testDispatcher) + ImportDataUseCaseImpl(userSettingsRepository, appRepository, backupRepository) } @Test @@ -283,7 +283,7 @@ class UseCaseTest { saveAddressUseCase(addr) // バックアップ - exportDataUseCase(appContext, uri) + exportDataUseCase(uri) // バックアップ時とは異なるように適当に変更 // ターゲット @@ -293,7 +293,7 @@ class UseCaseTest { toggleIgnoreSummaryUseCase.invoke(ToggleIgnoreSummaryUseCase.Args(app)) // 復元 - importDataUseCase(appContext, uri) + importDataUseCase(uri) // 正常に復元できているか確認 // ターゲット一覧 From c9c4f792a0100d87a413773a1b086778c86d95a5 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 02:26:31 +0900 Subject: [PATCH 04/14] =?UTF-8?q?data=E5=B1=A4=E3=81=AB=E3=82=82=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E7=94=A8=E3=83=A9=E3=82=A4=E3=83=96=E3=83=A9?= =?UTF-8?q?=E3=83=AA=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AndroidApp/data/repository/build.gradle.kts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/AndroidApp/data/repository/build.gradle.kts b/AndroidApp/data/repository/build.gradle.kts index 8548beb8..c356a23c 100644 --- a/AndroidApp/data/repository/build.gradle.kts +++ b/AndroidApp/data/repository/build.gradle.kts @@ -20,6 +20,13 @@ dependencies { // room api(libs.androidx.room.runtime) ksp(libs.androidx.room.compiler) + + // test + androidTestImplementation(libs.junit) + androidTestImplementation(libs.com.google.truth) + androidTestImplementation(libs.androidx.test.ext.junit) + androidTestImplementation(libs.androidx.test.espresso.core) + androidTestImplementation(libs.kotlinx.coroutines.test) } ksp { From 73ab13718d29dd7aa9dbd0a480505e590e23dc57 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 02:28:46 +0900 Subject: [PATCH 05/14] =?UTF-8?q?AppRepository=E3=81=AE=E3=83=86=E3=82=B9?= =?UTF-8?q?=E3=83=88=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notificationnotifier/AppRepositoryTest.kt | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 AndroidApp/data/repository/src/androidTest/kotlin/me/nya_n/notificationnotifier/AppRepositoryTest.kt diff --git a/AndroidApp/data/repository/src/androidTest/kotlin/me/nya_n/notificationnotifier/AppRepositoryTest.kt b/AndroidApp/data/repository/src/androidTest/kotlin/me/nya_n/notificationnotifier/AppRepositoryTest.kt new file mode 100644 index 00000000..7393fe78 --- /dev/null +++ b/AndroidApp/data/repository/src/androidTest/kotlin/me/nya_n/notificationnotifier/AppRepositoryTest.kt @@ -0,0 +1,82 @@ +package me.nya_n.notificationnotifier + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runTest +import me.nya_n.notificationnotifier.data.repository.AppRepository +import me.nya_n.notificationnotifier.data.repository.impl.AppRepositoryImpl +import me.nya_n.notificationnotifier.data.repository.source.DB +import me.nya_n.notificationnotifier.model.FilterCondition +import me.nya_n.notificationnotifier.model.InstalledApp +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@Suppress("NonAsciiCharacters") +@RunWith(AndroidJUnit4::class) +class AppRepositoryTest { + @OptIn(ExperimentalCoroutinesApi::class) + private val testDispatcher = UnconfinedTestDispatcher() + private lateinit var appRepository: AppRepository + + @Before + fun setUp() { + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + val db = DB.get(appContext, isInMemory = true).apply { + clearAllTables() + } + appRepository = AppRepositoryImpl( + appContext.packageManager, + db.filterConditionDao(), + db.targetAppDao(), + testDispatcher + ) + } + + @Test + fun `通知対象アプリの追加、取得、削除`() { + runTest(testDispatcher) { + val app = InstalledApp("sample", "com.sample.www") + appRepository.addTargetApp(app) + + val added = appRepository.getTargetAppList() + assertThat(added).hasSize(1) + assertThat(added.first()).isEqualTo(app) + + appRepository.deleteTargetApp(app) + val deleted = appRepository.getTargetAppList() + assertThat(deleted).isEmpty() + } + } + + + @Test + fun `通知条件の追加、取得、更新`() { + runTest(testDispatcher) { + val packageName = "com.sample.www" + + // データなし + assertThat(appRepository.getFilterCondition(packageName)).isNull() + assertThat(appRepository.getFilterConditionOrDefault(packageName)) + .isEqualTo(FilterCondition.default(packageName)) + + // 追加 + val added = FilterCondition(packageName, false, "test") + appRepository.saveFilterCondition(added) + assertThat(appRepository.getFilterCondition(packageName)).isEqualTo(added) + + // メッセージ条件の更新 + val updatedCondition = added.copy(condition = "updated") + appRepository.saveFilterCondition(updatedCondition) + assertThat(appRepository.getFilterCondition(packageName)).isEqualTo(updatedCondition) + + // サマリー条件の更新 + val updatedSummary = updatedCondition.copy(isIgnoreSummary = true) + appRepository.saveFilterCondition(updatedSummary) + assertThat(appRepository.getFilterCondition(packageName)).isEqualTo(updatedSummary) + } + } +} \ No newline at end of file From 6accb47afe706f2ff55df63658acf1955d1aabc6 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 02:37:54 +0900 Subject: [PATCH 06/14] =?UTF-8?q?UserSettingsRepository=E3=81=AE=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UserSettingsRepositoryTest.kt | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 AndroidApp/data/repository/src/androidTest/kotlin/me/nya_n/notificationnotifier/UserSettingsRepositoryTest.kt diff --git a/AndroidApp/data/repository/src/androidTest/kotlin/me/nya_n/notificationnotifier/UserSettingsRepositoryTest.kt b/AndroidApp/data/repository/src/androidTest/kotlin/me/nya_n/notificationnotifier/UserSettingsRepositoryTest.kt new file mode 100644 index 00000000..99c81685 --- /dev/null +++ b/AndroidApp/data/repository/src/androidTest/kotlin/me/nya_n/notificationnotifier/UserSettingsRepositoryTest.kt @@ -0,0 +1,51 @@ +package me.nya_n.notificationnotifier + +import androidx.core.content.edit +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runTest +import me.nya_n.notificationnotifier.data.repository.UserSettingsRepository +import me.nya_n.notificationnotifier.data.repository.impl.UserSettingsRepositoryImpl +import me.nya_n.notificationnotifier.data.repository.source.UserSettingsDataStore +import me.nya_n.notificationnotifier.data.repository.util.SharedPreferenceProvider +import me.nya_n.notificationnotifier.model.UserSettings +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@Suppress("NonAsciiCharacters") +@RunWith(AndroidJUnit4::class) +class UserSettingsRepositoryTest { + @OptIn(ExperimentalCoroutinesApi::class) + private val testDispatcher = UnconfinedTestDispatcher() + private lateinit var userSettingsRepository: UserSettingsRepository + + @Before + fun setUp() { + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + userSettingsRepository = UserSettingsRepositoryImpl( + UserSettingsDataStore( + SharedPreferenceProvider.create( + appContext, + UserSettingsDataStore.DATA_STORE_NAME + ).apply { + edit { + clear() + } + } + ) + ) + } + + @Test + fun `ユーザー設定の保存、取得`() { + runTest(testDispatcher) { + val data = UserSettings("192.168.10.18", 8484, false) + userSettingsRepository.saveUserSettings(data) + assertThat(userSettingsRepository.getUserSettings()).isEqualTo(data) + } + } +} \ No newline at end of file From 5bff6278a8f76a87194d4cf00f3bea79826da825 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 02:46:10 +0900 Subject: [PATCH 07/14] =?UTF-8?q?mockk=E5=B0=8E=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AndroidApp/domain/build.gradle.kts | 1 + AndroidApp/gradle/libs.versions.toml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/AndroidApp/domain/build.gradle.kts b/AndroidApp/domain/build.gradle.kts index 29f7b8d2..187e0bb5 100644 --- a/AndroidApp/domain/build.gradle.kts +++ b/AndroidApp/domain/build.gradle.kts @@ -26,6 +26,7 @@ dependencies { androidTestImplementation(libs.androidx.test.ext.junit) androidTestImplementation(libs.androidx.test.espresso.core) androidTestImplementation(libs.kotlinx.coroutines.test) + androidTestImplementation(libs.mockk) // その他 implementation(libs.com.google.code.gson) diff --git a/AndroidApp/gradle/libs.versions.toml b/AndroidApp/gradle/libs.versions.toml index b62c350a..1b9b71eb 100644 --- a/AndroidApp/gradle/libs.versions.toml +++ b/AndroidApp/gradle/libs.versions.toml @@ -32,6 +32,7 @@ androidx-room = "2.8.4" io-insert-koin = "4.1.1" com-google-code-gson = "2.13.2" com-squareup-leakcanary = "2.14" +mockk = "1.14.7" [plugins] com-android-application = { id = "com.android.application", version.ref = "agp" } @@ -68,6 +69,7 @@ kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-t com-google-truth = { module = "com.google.truth:truth", version.ref = "com-google-truth" } androidx-test-ext-junit = { module = "androidx.test.ext:junit", version.ref = "androidx-test-ext" } androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-test-espresso" } +mockk = { module = "io.mockk:mockk", version.ref = "mockk" } # for build-logic android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "agp" } From 248d75bb1e673e0330ac6793104a7b272eef5315 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 02:46:37 +0900 Subject: [PATCH 08/14] =?UTF-8?q?usecase=E3=81=AE=E3=83=86=E3=82=B9?= =?UTF-8?q?=E3=83=88=E6=99=82=E3=81=AFmockk=E3=81=AErepository=E3=82=92?= =?UTF-8?q?=E4=BD=BF=E3=81=86=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nya_n/notificationnotifier/UseCaseTest.kt | 33 ++++--------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt b/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt index ab29b4f4..85b2af18 100644 --- a/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt +++ b/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt @@ -1,19 +1,16 @@ package me.nya_n.notificationnotifier import android.net.Uri -import androidx.core.content.edit import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import com.google.common.truth.Truth.assertThat +import io.mockk.mockk import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest -import me.nya_n.notificationnotifier.data.repository.impl.AppRepositoryImpl +import me.nya_n.notificationnotifier.data.repository.AppRepository +import me.nya_n.notificationnotifier.data.repository.UserSettingsRepository import me.nya_n.notificationnotifier.data.repository.impl.BackupRepositoryImpl -import me.nya_n.notificationnotifier.data.repository.impl.UserSettingsRepositoryImpl -import me.nya_n.notificationnotifier.data.repository.source.DB -import me.nya_n.notificationnotifier.data.repository.source.UserSettingsDataStore -import me.nya_n.notificationnotifier.data.repository.util.SharedPreferenceProvider import me.nya_n.notificationnotifier.domain.usecase.AddTargetAppUseCase import me.nya_n.notificationnotifier.domain.usecase.DeleteTargetAppUseCase import me.nya_n.notificationnotifier.domain.usecase.ExportDataUseCase @@ -57,6 +54,9 @@ class UseCaseTest { private val testDispatcher = UnconfinedTestDispatcher() private lateinit var exportFile: File + private val userSettingsRepository: UserSettingsRepository = mockk() + private val appRepository: AppRepository = mockk() + private lateinit var addTargetAppUseCase: AddTargetAppUseCase private lateinit var loadAppUseCase: LoadAppUseCaseImpl private lateinit var deleteTargetAppUseCase: DeleteTargetAppUseCase @@ -79,27 +79,6 @@ class UseCaseTest { delete() } } - val userSettingsRepository = UserSettingsRepositoryImpl( - UserSettingsDataStore( - SharedPreferenceProvider.create( - appContext, - UserSettingsDataStore.DATA_STORE_NAME - ).apply { - edit { - clear() - } - } - ) - ) - val db = DB.get(appContext, isInMemory = true).apply { - clearAllTables() - } - val appRepository = AppRepositoryImpl( - appContext.packageManager, - db.filterConditionDao(), - db.targetAppDao(), - testDispatcher - ) val backupRepository = BackupRepositoryImpl(appContext, testDispatcher) addTargetAppUseCase = AddTargetAppUseCaseImpl(appRepository) loadAppUseCase = LoadAppUseCaseImpl(userSettingsRepository, appRepository, testDispatcher) From 0fc7b13589fa64dfd0606c2c167a0152413b9c99 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 03:49:57 +0900 Subject: [PATCH 09/14] =?UTF-8?q?rep=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notificationnotifier/UserSettingsRepositoryTest.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/AndroidApp/data/repository/src/androidTest/kotlin/me/nya_n/notificationnotifier/UserSettingsRepositoryTest.kt b/AndroidApp/data/repository/src/androidTest/kotlin/me/nya_n/notificationnotifier/UserSettingsRepositoryTest.kt index 99c81685..18eab7d4 100644 --- a/AndroidApp/data/repository/src/androidTest/kotlin/me/nya_n/notificationnotifier/UserSettingsRepositoryTest.kt +++ b/AndroidApp/data/repository/src/androidTest/kotlin/me/nya_n/notificationnotifier/UserSettingsRepositoryTest.kt @@ -41,11 +41,15 @@ class UserSettingsRepositoryTest { } @Test - fun `ユーザー設定の保存、取得`() { + fun `ユーザー設定の保存、取得、更新`() { runTest(testDispatcher) { val data = UserSettings("192.168.10.18", 8484, false) userSettingsRepository.saveUserSettings(data) assertThat(userSettingsRepository.getUserSettings()).isEqualTo(data) + + val updated = data.copy(port = 2525, isPackageVisibilityGranted = true) + userSettingsRepository.saveUserSettings(updated) + assertThat(userSettingsRepository.getUserSettings()).isEqualTo(updated) } } } \ No newline at end of file From b150cdbceeb6722c3a553ceb87ee82b8f8cf3549 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 03:50:08 +0900 Subject: [PATCH 10/14] =?UTF-8?q?mockk-android=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AndroidApp/domain/build.gradle.kts | 1 + AndroidApp/gradle/libs.versions.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/AndroidApp/domain/build.gradle.kts b/AndroidApp/domain/build.gradle.kts index 187e0bb5..bfe39954 100644 --- a/AndroidApp/domain/build.gradle.kts +++ b/AndroidApp/domain/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { androidTestImplementation(libs.androidx.test.espresso.core) androidTestImplementation(libs.kotlinx.coroutines.test) androidTestImplementation(libs.mockk) + androidTestImplementation(libs.mockk.android) // その他 implementation(libs.com.google.code.gson) diff --git a/AndroidApp/gradle/libs.versions.toml b/AndroidApp/gradle/libs.versions.toml index 1b9b71eb..098b780c 100644 --- a/AndroidApp/gradle/libs.versions.toml +++ b/AndroidApp/gradle/libs.versions.toml @@ -70,6 +70,7 @@ com-google-truth = { module = "com.google.truth:truth", version.ref = "com-googl androidx-test-ext-junit = { module = "androidx.test.ext:junit", version.ref = "androidx-test-ext" } androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-test-espresso" } mockk = { module = "io.mockk:mockk", version.ref = "mockk" } +mockk-android = { module = "io.mockk:mockk-android", version.ref = "mockk" } # for build-logic android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "agp" } From 2a18193dbcdf0eac86de617dac8d0632ef9da991 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 04:22:22 +0900 Subject: [PATCH 11/14] =?UTF-8?q?androidTest=E3=81=A8test=E5=88=86?= =?UTF-8?q?=E9=9B=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AndroidApp/domain/build.gradle.kts | 4 + .../nya_n/notificationnotifier/UseCaseTest.kt | 162 ------------------ .../nya_n/notificationnotifier/Annotations.kt | 5 + .../nya_n/notificationnotifier/UseCaseTest.kt | 125 ++++++++++++++ 4 files changed, 134 insertions(+), 162 deletions(-) create mode 100644 AndroidApp/domain/src/test/java/me/nya_n/notificationnotifier/Annotations.kt create mode 100644 AndroidApp/domain/src/test/java/me/nya_n/notificationnotifier/UseCaseTest.kt diff --git a/AndroidApp/domain/build.gradle.kts b/AndroidApp/domain/build.gradle.kts index bfe39954..175f61be 100644 --- a/AndroidApp/domain/build.gradle.kts +++ b/AndroidApp/domain/build.gradle.kts @@ -21,6 +21,10 @@ dependencies { api(libs.androidx.compose.runtime) // test + testImplementation(libs.junit) + testImplementation(libs.com.google.truth) + testImplementation(libs.kotlinx.coroutines.test) + testImplementation(libs.mockk) androidTestImplementation(libs.junit) androidTestImplementation(libs.com.google.truth) androidTestImplementation(libs.androidx.test.ext.junit) diff --git a/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt b/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt index 85b2af18..2658f0f4 100644 --- a/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt +++ b/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt @@ -12,32 +12,24 @@ import me.nya_n.notificationnotifier.data.repository.AppRepository import me.nya_n.notificationnotifier.data.repository.UserSettingsRepository import me.nya_n.notificationnotifier.data.repository.impl.BackupRepositoryImpl import me.nya_n.notificationnotifier.domain.usecase.AddTargetAppUseCase -import me.nya_n.notificationnotifier.domain.usecase.DeleteTargetAppUseCase import me.nya_n.notificationnotifier.domain.usecase.ExportDataUseCase import me.nya_n.notificationnotifier.domain.usecase.ImportDataUseCase import me.nya_n.notificationnotifier.domain.usecase.LoadAddressUseCase import me.nya_n.notificationnotifier.domain.usecase.LoadFilterConditionUseCase -import me.nya_n.notificationnotifier.domain.usecase.NotifyUseCase -import me.nya_n.notificationnotifier.domain.usecase.PackageVisibilityGrantedUseCase import me.nya_n.notificationnotifier.domain.usecase.SaveAddressUseCase import me.nya_n.notificationnotifier.domain.usecase.SaveFilterConditionUseCase import me.nya_n.notificationnotifier.domain.usecase.ToggleIgnoreSummaryUseCase import me.nya_n.notificationnotifier.domain.usecase.impl.AddTargetAppUseCaseImpl -import me.nya_n.notificationnotifier.domain.usecase.impl.DeleteTargetAppUseCaseImpl import me.nya_n.notificationnotifier.domain.usecase.impl.ExportDataUseCaseImpl import me.nya_n.notificationnotifier.domain.usecase.impl.ImportDataUseCaseImpl import me.nya_n.notificationnotifier.domain.usecase.impl.LoadAddressUseCaseImpl import me.nya_n.notificationnotifier.domain.usecase.impl.LoadAppUseCaseImpl import me.nya_n.notificationnotifier.domain.usecase.impl.LoadFilterConditionUseCaseImpl -import me.nya_n.notificationnotifier.domain.usecase.impl.NotifyUseCaseImpl -import me.nya_n.notificationnotifier.domain.usecase.impl.PackageVisibilityGrantedUseCaseImpl import me.nya_n.notificationnotifier.domain.usecase.impl.SaveAddressUseCaseImpl import me.nya_n.notificationnotifier.domain.usecase.impl.SaveFilterConditionUseCaseImpl import me.nya_n.notificationnotifier.domain.usecase.impl.ToggleIgnoreSummaryUseCaseImpl -import me.nya_n.notificationnotifier.model.AppException.PermissionDeniedException import me.nya_n.notificationnotifier.model.FilterCondition import me.nya_n.notificationnotifier.model.InstalledApp -import org.junit.Assume.assumeTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -59,14 +51,11 @@ class UseCaseTest { private lateinit var addTargetAppUseCase: AddTargetAppUseCase private lateinit var loadAppUseCase: LoadAppUseCaseImpl - private lateinit var deleteTargetAppUseCase: DeleteTargetAppUseCase - private lateinit var packageVisibilityGrantedUseCase: PackageVisibilityGrantedUseCase private lateinit var saveFilterConditionUseCase: SaveFilterConditionUseCase private lateinit var toggleIgnoreSummaryUseCase: ToggleIgnoreSummaryUseCase private lateinit var loadFilterConditionUseCase: LoadFilterConditionUseCase private lateinit var saveAddressUseCase: SaveAddressUseCase private lateinit var loadAddressUseCase: LoadAddressUseCase - private lateinit var notifyUseCase: NotifyUseCase private lateinit var exportDataUseCase: ExportDataUseCase private lateinit var importDataUseCase: ImportDataUseCase @@ -82,168 +71,17 @@ class UseCaseTest { val backupRepository = BackupRepositoryImpl(appContext, testDispatcher) addTargetAppUseCase = AddTargetAppUseCaseImpl(appRepository) loadAppUseCase = LoadAppUseCaseImpl(userSettingsRepository, appRepository, testDispatcher) - deleteTargetAppUseCase = DeleteTargetAppUseCaseImpl(appRepository) - packageVisibilityGrantedUseCase = - PackageVisibilityGrantedUseCaseImpl(userSettingsRepository) saveFilterConditionUseCase = SaveFilterConditionUseCaseImpl(appRepository) toggleIgnoreSummaryUseCase = ToggleIgnoreSummaryUseCaseImpl(appRepository) loadFilterConditionUseCase = LoadFilterConditionUseCaseImpl(appRepository) saveAddressUseCase = SaveAddressUseCaseImpl(userSettingsRepository) loadAddressUseCase = LoadAddressUseCaseImpl(userSettingsRepository) - notifyUseCase = NotifyUseCaseImpl(userSettingsRepository, testDispatcher) exportDataUseCase = ExportDataUseCaseImpl(userSettingsRepository, appRepository, backupRepository) importDataUseCase = ImportDataUseCaseImpl(userSettingsRepository, appRepository, backupRepository) } - @Test - fun `通知対象アプリの追加、取得、削除`() { - runTest(testDispatcher) { - val app = InstalledApp("sample", "com.sample.www") - addTargetAppUseCase(app) - - val added = loadAppUseCase.loadTargetList() - assertThat(added).hasSize(1) - assertThat(added.first()).isEqualTo(app) - - deleteTargetAppUseCase(app) - val deleted = loadAppUseCase.loadTargetList() - assertThat(deleted).isEmpty() - } - } - - @Test - fun `インストール済みアプリの取得_成功(ついでにアプリ一覧取得権限許可処理も)`() { - packageVisibilityGrantedUseCase() - val ret = loadAppUseCase.loadInstalledAppList() - assertThat(ret.getOrNull()).apply { - isNotNull() - isNotEmpty() - } - } - - @Test - fun `インストール済みアプリの取得_失敗`() { - val ret = loadAppUseCase.loadInstalledAppList() - assertThat(ret.exceptionOrNull()).apply { - isNotNull() - isInstanceOf(PermissionDeniedException::class.java) - } - } - - @Test - fun `通知条件の追加、取得、更新`() { - runTest(testDispatcher) { - val cond = "test" - val updatedCond = "updated" - val packageName = "com.sample.www" - val app = InstalledApp("sample", packageName) - - // 追加 - saveFilterConditionUseCase(SaveFilterConditionUseCase.Args(app, cond)) - assertThat(loadFilterConditionUseCase(app)).isEqualTo( - FilterCondition( - packageName, - false, - cond - ) - ) - - // メッセージ条件の更新 - saveFilterConditionUseCase(SaveFilterConditionUseCase.Args(app, updatedCond)) - assertThat(loadFilterConditionUseCase(app)).isEqualTo( - FilterCondition( - packageName, - false, - updatedCond - ) - ) - - // サマリー条件の更新 - toggleIgnoreSummaryUseCase.invoke(ToggleIgnoreSummaryUseCase.Args(app)) - assertThat(loadFilterConditionUseCase(app)).isEqualTo( - FilterCondition( - packageName, - true, - updatedCond - ) - ) - } - } - - @Test - fun `IPアドレスの追加、更新_成功、成功`() { - val host = "192.168.11.4" - val port = 5555 - val addr = "$host:$port" - assertThat(saveAddressUseCase(addr).getOrNull()).isNotNull() - assertThat(loadAddressUseCase()).isEqualTo(addr) - - val updatedHost = "192.168.11.2" - val updatedPort = 3456 - val updatedAddr = "$updatedHost:$updatedPort" - assertThat(saveAddressUseCase(updatedAddr).getOrNull()).isNotNull() - assertThat(loadAddressUseCase()).isEqualTo(updatedAddr) - } - - @Test - fun `IPアドレスの追加、更新_成功、失敗`() { - val host = "192.168.11.4" - val port = 5555 - val addr = "$host:$port" - assertThat(saveAddressUseCase(addr).getOrNull()).isNotNull() - assertThat(loadAddressUseCase()).isEqualTo(addr) - - val updatedHost = "192.168.11.2" - val updatedAddr = "$updatedHost:" - assertThat(saveAddressUseCase(updatedAddr).exceptionOrNull()).isNotNull() - assertThat(loadAddressUseCase()).isEqualTo(addr) - } - - @Test - fun `IPアドレスの追加_失敗_hostなし`() { - val port = 5555 - val addr = ":$port" - assertThat(saveAddressUseCase(addr).exceptionOrNull()).isNotNull() - } - - @Test - fun `IPアドレスの追加_失敗_portなし`() { - val host = "192.168.11.4" - val addr = "$host:" - assertThat(saveAddressUseCase(addr).exceptionOrNull()).isNotNull() - } - - @Test - fun `IPアドレスの追加_失敗_portが数値じゃない`() { - val host = "192.168.11.4" - val addr = "$host:test" - assertThat(saveAddressUseCase(addr).exceptionOrNull()).isNotNull() - } - - @Test - fun `通知送信_失敗`() { - runTest(testDispatcher) { - assertThat(notifyUseCase("通知テスト").exceptionOrNull()).isNotNull() - } - } - - @Test - @LocalOnly - fun `通知送信_成功`() { - // CI環境で実行しないようにする - assumeTrue("Local only", System.getenv("CI") == null) - - runTest(testDispatcher) { - val host = "192.168.10.18" // テスト環境のIPアドレスに変更する - val port = 8484 - val addr = "$host:$port" - saveAddressUseCase(addr) - assertThat(notifyUseCase("通知テスト").getOrNull()).isNotNull() - } - } - @Test fun `バックアップ、復元`() { val uri = Uri.fromFile(File.createTempFile(ExportFileName, null, exportFile)) diff --git a/AndroidApp/domain/src/test/java/me/nya_n/notificationnotifier/Annotations.kt b/AndroidApp/domain/src/test/java/me/nya_n/notificationnotifier/Annotations.kt new file mode 100644 index 00000000..1f222b1b --- /dev/null +++ b/AndroidApp/domain/src/test/java/me/nya_n/notificationnotifier/Annotations.kt @@ -0,0 +1,5 @@ +package me.nya_n.notificationnotifier + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.RUNTIME) +annotation class LocalOnly \ No newline at end of file diff --git a/AndroidApp/domain/src/test/java/me/nya_n/notificationnotifier/UseCaseTest.kt b/AndroidApp/domain/src/test/java/me/nya_n/notificationnotifier/UseCaseTest.kt new file mode 100644 index 00000000..15492f19 --- /dev/null +++ b/AndroidApp/domain/src/test/java/me/nya_n/notificationnotifier/UseCaseTest.kt @@ -0,0 +1,125 @@ +package me.nya_n.notificationnotifier + +import com.google.common.truth.Truth.assertThat +import io.mockk.Runs +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.mockkStatic +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runTest +import me.nya_n.notificationnotifier.data.repository.AppRepository +import me.nya_n.notificationnotifier.data.repository.UserSettingsRepository +import me.nya_n.notificationnotifier.domain.usecase.NotifyUseCase +import me.nya_n.notificationnotifier.domain.usecase.SaveAddressUseCase +import me.nya_n.notificationnotifier.domain.usecase.impl.LoadAppUseCaseImpl +import me.nya_n.notificationnotifier.domain.usecase.impl.NotifyUseCaseImpl +import me.nya_n.notificationnotifier.domain.usecase.impl.SaveAddressUseCaseImpl +import me.nya_n.notificationnotifier.model.AppException.PermissionDeniedException +import me.nya_n.notificationnotifier.model.InstalledApp +import me.nya_n.notificationnotifier.model.UserSettings +import org.junit.Assume.assumeTrue +import org.junit.Before +import org.junit.Test + +@Suppress("NonAsciiCharacters", "RemoveRedundantBackticks") +class UseCaseTest { + @OptIn(ExperimentalCoroutinesApi::class) + private val testDispatcher = UnconfinedTestDispatcher() + private val userSettingsRepository: UserSettingsRepository = mockk() + private val appRepository: AppRepository = mockk() + + private lateinit var loadAppUseCase: LoadAppUseCaseImpl + private lateinit var saveAddressUseCase: SaveAddressUseCase + private lateinit var notifyUseCase: NotifyUseCase + + @Before + fun setUp() { + loadAppUseCase = LoadAppUseCaseImpl(userSettingsRepository, appRepository, testDispatcher) + saveAddressUseCase = SaveAddressUseCaseImpl(userSettingsRepository) + notifyUseCase = NotifyUseCaseImpl(userSettingsRepository, testDispatcher) + + mockkStatic(android.text.TextUtils::class) + every { android.text.TextUtils.isDigitsOnly(any()) } answers { + val str = it.invocation.args[0] as? CharSequence + str?.all { char -> char.isDigit() } == true + } + } + + @Test + fun `インストール済みアプリの取得_許可あり`() { + every { userSettingsRepository.getUserSettings() } returns UserSettings("", 0, true) + every { appRepository.loadInstalledAppList() } returns listOf(InstalledApp("", "")) + + val ret = loadAppUseCase.loadInstalledAppList() + assertThat(ret.getOrNull()).apply { + isNotNull() + isNotEmpty() + } + } + + @Test + fun `インストール済みアプリの取得_許可なし`() { + every { userSettingsRepository.getUserSettings() } returns UserSettings("", 0, false) + every { appRepository.loadInstalledAppList() } throws PermissionDeniedException() + + val ret = loadAppUseCase.loadInstalledAppList() + assertThat(ret.exceptionOrNull()).apply { + isNotNull() + isInstanceOf(PermissionDeniedException::class.java) + } + } + + @Test + fun `IPアドレスの追加_成功`() { + every { userSettingsRepository.getUserSettings() } returns UserSettings( + "192.168.10.18", + 8484, + true + ) + every { userSettingsRepository.saveUserSettings(any()) } just Runs + + assertThat(saveAddressUseCase("192.168.10.18:8484").getOrNull()).isNotNull() + } + + @Test + fun `IPアドレスの追加_失敗_portなし`() { + assertThat(saveAddressUseCase("192.168.11.4").exceptionOrNull()).isNotNull() + } + + @Test + fun `IPアドレスの追加_失敗_hostなし`() { + assertThat(saveAddressUseCase(":8484").exceptionOrNull()).isNotNull() + } + + @Test + fun `IPアドレスの追加_失敗_portが数値じゃない`() { + assertThat(saveAddressUseCase("192.168.10.18:not_number").exceptionOrNull()).isNotNull() + } + + @Test + fun `通知送信_失敗`() { + runTest(testDispatcher) { + assertThat(notifyUseCase("通知テスト").exceptionOrNull()).isNotNull() + } + } + + @Test + @LocalOnly + fun `通知送信_成功`() { + // CI環境で実行しないようにする + assumeTrue("Local only", System.getenv("CI") == null) + + // テスト環境のIPアドレスに変更する + every { userSettingsRepository.getUserSettings() } returns UserSettings( + "192.168.10.18", + 8484, + true + ) + + runTest(testDispatcher) { + assertThat(notifyUseCase("通知テスト").getOrNull()).isNotNull() + } + } +} \ No newline at end of file From 44130158f6802bfc2e1153b5e07e1104b41dc605 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 04:30:30 +0900 Subject: [PATCH 12/14] =?UTF-8?q?androidTest=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nya_n/notificationnotifier/UseCaseTest.kt | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt b/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt index 2658f0f4..37027f28 100644 --- a/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt +++ b/AndroidApp/domain/src/androidTest/java/me/nya_n/notificationnotifier/UseCaseTest.kt @@ -1,16 +1,19 @@ package me.nya_n.notificationnotifier import android.net.Uri +import androidx.core.content.edit import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import com.google.common.truth.Truth.assertThat -import io.mockk.mockk import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest -import me.nya_n.notificationnotifier.data.repository.AppRepository -import me.nya_n.notificationnotifier.data.repository.UserSettingsRepository +import me.nya_n.notificationnotifier.data.repository.impl.AppRepositoryImpl import me.nya_n.notificationnotifier.data.repository.impl.BackupRepositoryImpl +import me.nya_n.notificationnotifier.data.repository.impl.UserSettingsRepositoryImpl +import me.nya_n.notificationnotifier.data.repository.source.DB +import me.nya_n.notificationnotifier.data.repository.source.UserSettingsDataStore +import me.nya_n.notificationnotifier.data.repository.util.SharedPreferenceProvider import me.nya_n.notificationnotifier.domain.usecase.AddTargetAppUseCase import me.nya_n.notificationnotifier.domain.usecase.ExportDataUseCase import me.nya_n.notificationnotifier.domain.usecase.ImportDataUseCase @@ -35,7 +38,7 @@ import org.junit.Test import org.junit.runner.RunWith import java.io.File -@Suppress("NonAsciiCharacters", "RemoveRedundantBackticks") +@Suppress("NonAsciiCharacters") @RunWith(AndroidJUnit4::class) class UseCaseTest { companion object { @@ -46,9 +49,6 @@ class UseCaseTest { private val testDispatcher = UnconfinedTestDispatcher() private lateinit var exportFile: File - private val userSettingsRepository: UserSettingsRepository = mockk() - private val appRepository: AppRepository = mockk() - private lateinit var addTargetAppUseCase: AddTargetAppUseCase private lateinit var loadAppUseCase: LoadAppUseCaseImpl private lateinit var saveFilterConditionUseCase: SaveFilterConditionUseCase @@ -68,6 +68,27 @@ class UseCaseTest { delete() } } + val userSettingsRepository = UserSettingsRepositoryImpl( + UserSettingsDataStore( + SharedPreferenceProvider.create( + appContext, + UserSettingsDataStore.DATA_STORE_NAME + ).apply { + edit { + clear() + } + } + ) + ) + val db = DB.get(appContext, isInMemory = true).apply { + clearAllTables() + } + val appRepository = AppRepositoryImpl( + appContext.packageManager, + db.filterConditionDao(), + db.targetAppDao(), + testDispatcher + ) val backupRepository = BackupRepositoryImpl(appContext, testDispatcher) addTargetAppUseCase = AddTargetAppUseCaseImpl(appRepository) loadAppUseCase = LoadAppUseCaseImpl(userSettingsRepository, appRepository, testDispatcher) From aac6226e1e010b38605ec56b653dc9a2033e5da4 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 04:39:29 +0900 Subject: [PATCH 13/14] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E4=BE=9D?= =?UTF-8?q?=E5=AD=98=E9=96=A2=E4=BF=82=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AndroidApp/data/repository/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/AndroidApp/data/repository/build.gradle.kts b/AndroidApp/data/repository/build.gradle.kts index c356a23c..58e4edd7 100644 --- a/AndroidApp/data/repository/build.gradle.kts +++ b/AndroidApp/data/repository/build.gradle.kts @@ -25,7 +25,6 @@ dependencies { androidTestImplementation(libs.junit) androidTestImplementation(libs.com.google.truth) androidTestImplementation(libs.androidx.test.ext.junit) - androidTestImplementation(libs.androidx.test.espresso.core) androidTestImplementation(libs.kotlinx.coroutines.test) } From b99d43b5dc299907f256e0bf9dff3aabb486cd3d Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 15 Jan 2026 04:45:09 +0900 Subject: [PATCH 14/14] =?UTF-8?q?viewmodel=E3=81=AE=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/screen/settings/SettingsScreen.kt | 6 ++---- .../ui/screen/settings/SettingsViewModel.kt | 9 ++++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/settings/SettingsScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/settings/SettingsScreen.kt index f1949c59..20bcdd4e 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/settings/SettingsScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/settings/SettingsScreen.kt @@ -36,7 +36,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.stringResource @@ -63,20 +62,19 @@ fun SettingsScreen( snackbarHostState: SnackbarHostState, viewModel: SettingsViewModel = koinViewModel() ) { - val context = LocalContext.current val uiState by viewModel.uiState.collectAsState() val uiEvents by viewModel.uiEvent.collectAsState() val exportLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.StartActivityForResult() ) { if (it.resultCode != AppCompatActivity.RESULT_OK) return@rememberLauncherForActivityResult - viewModel.exportData(context, it.data?.data) + viewModel.exportData(it.data?.data) } val importLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.StartActivityForResult() ) { if (it.resultCode != AppCompatActivity.RESULT_OK) return@rememberLauncherForActivityResult - viewModel.importData(context, it.data?.data) + viewModel.importData(it.data?.data) } uiEvents.firstOrNull()?.let { when (it) { diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/settings/SettingsViewModel.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/settings/SettingsViewModel.kt index 02129432..f32fc666 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/settings/SettingsViewModel.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/settings/SettingsViewModel.kt @@ -1,6 +1,5 @@ package me.nya_n.notificationnotifier.ui.screen.settings -import android.content.Context import android.net.Uri import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableStateFlow @@ -61,13 +60,13 @@ class SettingsViewModel( } /** バックアップのために外部ストレージにデータを保存 */ - fun exportData(context: Context, uri: Uri?) { + fun exportData(uri: Uri?) { if (uri == null) { _uiState.update { it.copy(message = Message.Error(R.string.export_failed)) } return } viewModelScope.launch { - val message = if (exportDataUseCase(context, uri).isSuccess) { + val message = if (exportDataUseCase(uri).isSuccess) { Message.Notice(R.string.export_succeeded) } else { Message.Error(R.string.export_failed) @@ -77,13 +76,13 @@ class SettingsViewModel( } /** 外部ストレージのバックアップからデータを復元 */ - fun importData(context: Context, uri: Uri?) { + fun importData(uri: Uri?) { if (uri == null) { _uiState.update { it.copy(message = Message.Error(R.string.import_failed)) } return } viewModelScope.launch { - val message = if (importDataUseCase(context, uri).isSuccess) { + val message = if (importDataUseCase(uri).isSuccess) { Message.Notice(R.string.import_succeeded) } else { Message.Error(R.string.import_failed)