diff --git a/buildSrc/src/main/kotlin/com/example/util/simpletimetracker/Versions.kt b/buildSrc/src/main/kotlin/com/example/util/simpletimetracker/Versions.kt index c6e98608f..724203b55 100644 --- a/buildSrc/src/main/kotlin/com/example/util/simpletimetracker/Versions.kt +++ b/buildSrc/src/main/kotlin/com/example/util/simpletimetracker/Versions.kt @@ -9,7 +9,7 @@ object Versions { const val timber = "4.7.1" const val javax = "1" - const val appcompat = "1.6.0" + const val appcompat = "1.7.0" const val constraintLayout = "2.1.4" const val recyclerView = "1.1.0" const val lifecycleExtensions = "2.2.0" diff --git a/core/src/main/java/com/example/util/simpletimetracker/core/utils/TestUtils.kt b/core/src/main/java/com/example/util/simpletimetracker/core/utils/TestUtils.kt index 94c0c67be..5b1cf2213 100644 --- a/core/src/main/java/com/example/util/simpletimetracker/core/utils/TestUtils.kt +++ b/core/src/main/java/com/example/util/simpletimetracker/core/utils/TestUtils.kt @@ -67,6 +67,7 @@ class TestUtils @Inject constructor( text: String? = null, goals: List = emptyList(), archived: Boolean = false, + instant: Boolean = false, categories: List = emptyList(), ) = runBlocking { val icons = iconImageMapper @@ -87,6 +88,7 @@ class TestUtils @Inject constructor( color = AppColor(colorId = colorId, colorInt = colorInt?.toString().orEmpty()), icon = iconId, hidden = archived, + instant = instant, ) val typeId = recordTypeInteractor.add(data) diff --git a/data_local/schemas/com.example.util.simpletimetracker.data_local.database.AppDatabase/20.json b/data_local/schemas/com.example.util.simpletimetracker.data_local.database.AppDatabase/20.json new file mode 100644 index 000000000..5bba22082 --- /dev/null +++ b/data_local/schemas/com.example.util.simpletimetracker.data_local.database.AppDatabase/20.json @@ -0,0 +1,613 @@ +{ + "formatVersion": 1, + "database": { + "version": 20, + "identityHash": "ec09bca1a31028101411c036ae29e63a", + "entities": [ + { + "tableName": "records", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `type_id` INTEGER NOT NULL, `time_started` INTEGER NOT NULL, `time_ended` INTEGER NOT NULL, `comment` TEXT NOT NULL, `tag_id` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "typeId", + "columnName": "type_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timeStarted", + "columnName": "time_started", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timeEnded", + "columnName": "time_ended", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "comment", + "columnName": "comment", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tagId", + "columnName": "tag_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "recordTypes", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` INTEGER NOT NULL, `color_int` TEXT NOT NULL, `hidden` INTEGER NOT NULL, `instant` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "colorInt", + "columnName": "color_int", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hidden", + "columnName": "hidden", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "instant", + "columnName": "instant", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "runningRecords", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `time_started` INTEGER NOT NULL, `comment` TEXT NOT NULL, `tag_id` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timeStarted", + "columnName": "time_started", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "comment", + "columnName": "comment", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tagId", + "columnName": "tag_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "categories", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `color` INTEGER NOT NULL, `color_int` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "colorInt", + "columnName": "color_int", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "recordTypeCategory", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`record_type_id` INTEGER NOT NULL, `category_id` INTEGER NOT NULL, PRIMARY KEY(`record_type_id`, `category_id`))", + "fields": [ + { + "fieldPath": "recordTypeId", + "columnName": "record_type_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "categoryId", + "columnName": "category_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "record_type_id", + "category_id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "recordTags", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `type_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` INTEGER NOT NULL, `color_int` TEXT NOT NULL, `icon_color_source` INTEGER NOT NULL, `archived` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "typeId", + "columnName": "type_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "colorInt", + "columnName": "color_int", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iconColorSource", + "columnName": "icon_color_source", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "archived", + "columnName": "archived", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "recordToRecordTag", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`record_id` INTEGER NOT NULL, `record_tag_id` INTEGER NOT NULL, PRIMARY KEY(`record_id`, `record_tag_id`))", + "fields": [ + { + "fieldPath": "recordId", + "columnName": "record_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "recordTagId", + "columnName": "record_tag_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "record_id", + "record_tag_id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "runningRecordToRecordTag", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`running_record_id` INTEGER NOT NULL, `record_tag_id` INTEGER NOT NULL, PRIMARY KEY(`running_record_id`, `record_tag_id`))", + "fields": [ + { + "fieldPath": "runningRecordId", + "columnName": "running_record_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "recordTagId", + "columnName": "record_tag_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "running_record_id", + "record_tag_id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "recordTypeToTag", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`record_type_id` INTEGER NOT NULL, `record_tag_id` INTEGER NOT NULL, PRIMARY KEY(`record_type_id`, `record_tag_id`))", + "fields": [ + { + "fieldPath": "recordTypeId", + "columnName": "record_type_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "tagId", + "columnName": "record_tag_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "record_type_id", + "record_tag_id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "recordTypeToDefaultTag", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`record_type_id` INTEGER NOT NULL, `record_tag_id` INTEGER NOT NULL, PRIMARY KEY(`record_type_id`, `record_tag_id`))", + "fields": [ + { + "fieldPath": "recordTypeId", + "columnName": "record_type_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "tagId", + "columnName": "record_tag_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "record_type_id", + "record_tag_id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "activityFilters", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `selectedIds` TEXT NOT NULL, `type` INTEGER NOT NULL, `name` TEXT NOT NULL, `color` INTEGER NOT NULL, `color_int` TEXT NOT NULL, `selected` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "selectedIds", + "columnName": "selectedIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "colorInt", + "columnName": "color_int", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "selected", + "columnName": "selected", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "favouriteComments", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `comment` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "comment", + "columnName": "comment", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "recordTypeGoals", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `type_id` INTEGER NOT NULL, `range` INTEGER NOT NULL, `type` INTEGER NOT NULL, `value` INTEGER NOT NULL, `category_id` INTEGER NOT NULL, `days_of_week` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "typeId", + "columnName": "type_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "range", + "columnName": "range", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "categoryId", + "columnName": "category_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "daysOfWeek", + "columnName": "days_of_week", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "favouriteIcons", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `icon` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "complexRules", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `disabled` INTEGER NOT NULL, `actionType` INTEGER NOT NULL, `actionSetTagIds` TEXT NOT NULL, `conditionStartingTypeIds` TEXT NOT NULL, `conditionCurrentTypeIds` TEXT NOT NULL, `conditionDaysOfWeek` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "disabled", + "columnName": "disabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "action", + "columnName": "actionType", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "actionSetTagIds", + "columnName": "actionSetTagIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "conditionStartingTypeIds", + "columnName": "conditionStartingTypeIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "conditionCurrentTypeIds", + "columnName": "conditionCurrentTypeIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "conditionDaysOfWeek", + "columnName": "conditionDaysOfWeek", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'ec09bca1a31028101411c036ae29e63a')" + ] + } +} \ No newline at end of file diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/ActivityFilterDao.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/ActivityFilterDao.kt index 4ab925ac1..bd9bbf774 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/ActivityFilterDao.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/ActivityFilterDao.kt @@ -18,6 +18,10 @@ interface ActivityFilterDao { @Query("SELECT * FROM activityFilters WHERE id = :id LIMIT 1") suspend fun get(id: Long): ActivityFilterDBO? + @Transaction + @Query("SELECT * FROM activityFilters WHERE :typeId in (selectedIds)") + suspend fun getByTypeId(typeId: Long): List + @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(activityFilter: ActivityFilterDBO): Long diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabase.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabase.kt index c4347903e..5c79e9db2 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabase.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabase.kt @@ -36,7 +36,7 @@ import com.example.util.simpletimetracker.data_local.model.RunningRecordToRecord FavouriteIconDBO::class, ComplexRuleDBO::class, ], - version = 19, + version = 20, exportSchema = true, ) abstract class AppDatabase : RoomDatabase() { diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabaseMigrations.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabaseMigrations.kt index 94b44ab65..680405794 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabaseMigrations.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabaseMigrations.kt @@ -26,6 +26,7 @@ class AppDatabaseMigrations { migration_16_17, migration_17_18, migration_18_19, + migration_19_20, ) private val migration_1_2 = object : Migration(1, 2) { @@ -255,5 +256,13 @@ class AppDatabaseMigrations { ) } } + + private val migration_19_20 = object : Migration(19, 20) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( + "ALTER TABLE recordTypes ADD COLUMN instant INTEGER NOT NULL DEFAULT 0", + ) + } + } } } \ No newline at end of file diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/mapper/RecordTypeDataLocalMapper.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/mapper/RecordTypeDataLocalMapper.kt index f171476ea..b4ae7b681 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/mapper/RecordTypeDataLocalMapper.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/mapper/RecordTypeDataLocalMapper.kt @@ -16,6 +16,7 @@ class RecordTypeDataLocalMapper @Inject constructor() { colorId = dbo.color, colorInt = dbo.colorInt, ), + instant = dbo.instant, hidden = dbo.hidden, ) } @@ -27,6 +28,7 @@ class RecordTypeDataLocalMapper @Inject constructor() { icon = domain.icon, color = domain.color.colorId, colorInt = domain.color.colorInt, + instant = domain.instant, hidden = domain.hidden, ) } diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/model/RecordTypeDBO.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/model/RecordTypeDBO.kt index e2c330aef..bc4c19b91 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/model/RecordTypeDBO.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/model/RecordTypeDBO.kt @@ -25,4 +25,7 @@ data class RecordTypeDBO( @ColumnInfo(name = "hidden") val hidden: Boolean, + + @ColumnInfo(name = "instant") + val instant: Boolean, ) \ No newline at end of file diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/ActivityFilterRepoImpl.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/ActivityFilterRepoImpl.kt index 06fafa0fd..26a181348 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/ActivityFilterRepoImpl.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/ActivityFilterRepoImpl.kt @@ -32,6 +32,12 @@ class ActivityFilterRepoImpl @Inject constructor( accessSource = { activityFilterDao.get(id)?.let(activityFilterDataLocalMapper::map) }, ) + override suspend fun getByTypeId(typeId: Long): List = mutex.withLockedCache( + logMessage = "getByTypeId", + accessCache = { cache?.filter { typeId in it.selectedIds } }, + accessSource = { activityFilterDao.getByTypeId(typeId).map(activityFilterDataLocalMapper::map) }, + ) + override suspend fun add(activityFilter: ActivityFilter): Long = mutex.withLockedCache( logMessage = "add", accessSource = { activityFilterDao.insert(activityFilter.let(activityFilterDataLocalMapper::map)) }, diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/resolver/BackupRepoImpl.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/resolver/BackupRepoImpl.kt index e8d2fa416..72998a8f5 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/resolver/BackupRepoImpl.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/resolver/BackupRepoImpl.kt @@ -286,7 +286,7 @@ class BackupRepoImpl @Inject constructor( private fun toBackupString(recordType: RecordType): String { return String.format( - "$ROW_RECORD_TYPE\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", + "$ROW_RECORD_TYPE\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", recordType.id.toString(), recordType.name.clean(), recordType.icon, @@ -296,7 +296,8 @@ class BackupRepoImpl @Inject constructor( recordType.color.colorInt, "", // daily goal time is moved to separate table "", // weekly goal time is moved to separate table - "", // monthly goal time is moved to separate table + "", // monthly goal time is moved to separate table, + (if (recordType.instant) 1 else 0).toString(), ) } @@ -508,7 +509,8 @@ class BackupRepoImpl @Inject constructor( // parts[6] - goal time is moved to separate table // parts[8] - daily time is moved to separate table // parts[9] - weekly time is moved to separate table - // parts[10] - monthly time is moved to separate table + // parts[10] - monthly time is moved to separate table, + instant = parts.getOrNull(11)?.toIntOrNull() == 1, ) to goalTimes } diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/resolver/CsvRepoImpl.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/resolver/CsvRepoImpl.kt index 099a758d5..28f8e71a3 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/resolver/CsvRepoImpl.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/resolver/CsvRepoImpl.kt @@ -150,6 +150,7 @@ class CsvRepoImpl @Inject constructor( colorInt = "", ), hidden = false, + instant = false, ) val newTypeId = recordTypeRepo.add(newType) newType.copy(id = newTypeId).let(newAddedTypes::add) diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/ActivityFilterInteractor.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/ActivityFilterInteractor.kt index bcade7289..049d2572a 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/ActivityFilterInteractor.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/ActivityFilterInteractor.kt @@ -18,6 +18,10 @@ class ActivityFilterInteractor @Inject constructor( return activityFilterRepo.get(id) } + suspend fun getByTypeId(id: Long): List { + return activityFilterRepo.getByTypeId(id) + } + suspend fun add(record: ActivityFilter) { activityFilterRepo.add(record) } @@ -33,4 +37,15 @@ class ActivityFilterInteractor @Inject constructor( suspend fun remove(id: Long) { activityFilterRepo.remove(id) } + + suspend fun removeTypeId(id: Long) { + getByTypeId(id).forEach { filter -> + val newFilter = filter.copy( + selectedIds = filter.selectedIds + .toMutableList() + .apply { removeAll { it == id } }, + ) + add(newFilter) + } + } } \ No newline at end of file diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/RecordTypeInteractor.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/RecordTypeInteractor.kt index 324802c68..afe949ca2 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/RecordTypeInteractor.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/RecordTypeInteractor.kt @@ -2,6 +2,7 @@ package com.example.util.simpletimetracker.domain.interactor import com.example.util.simpletimetracker.domain.model.CardOrder import com.example.util.simpletimetracker.domain.model.RecordType +import com.example.util.simpletimetracker.domain.repo.ActivityFilterRepo import com.example.util.simpletimetracker.domain.repo.RecordRepo import com.example.util.simpletimetracker.domain.repo.RecordTagRepo import com.example.util.simpletimetracker.domain.repo.RecordToRecordTagRepo @@ -22,6 +23,7 @@ class RecordTypeInteractor @Inject constructor( private val recordTypeToDefaultTagRepo: RecordTypeToDefaultTagRepo, private val recordTypeGoalRepo: RecordTypeGoalRepo, private val complexRuleInteractor: ComplexRuleInteractor, + private val activityFilterInteractor: ActivityFilterInteractor, private val prefsInteractor: PrefsInteractor, private val sortCardsInteractor: SortCardsInteractor, ) { @@ -82,6 +84,7 @@ class RecordTypeInteractor @Inject constructor( recordTypeToDefaultTagRepo.removeAllByType(id) recordTypeGoalRepo.removeByType(id) complexRuleInteractor.removeTypeId(id) + activityFilterInteractor.removeTypeId(id) recordTypeRepo.remove(id) } diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/model/RecordType.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/model/RecordType.kt index c4056970c..3bf12c788 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/model/RecordType.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/model/RecordType.kt @@ -5,5 +5,6 @@ data class RecordType( val name: String, val icon: String, val color: AppColor, + val instant: Boolean, val hidden: Boolean = false, ) \ No newline at end of file diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/repo/ActivityFilterRepo.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/repo/ActivityFilterRepo.kt index a3470199d..dd3ecb099 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/repo/ActivityFilterRepo.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/repo/ActivityFilterRepo.kt @@ -8,6 +8,8 @@ interface ActivityFilterRepo { suspend fun get(id: Long): ActivityFilter? + suspend fun getByTypeId(typeId: Long): List + suspend fun add(activityFilter: ActivityFilter): Long suspend fun changeSelected(id: Long, selected: Boolean) diff --git a/features/feature_change_category/build.gradle.kts b/features/feature_change_category/build.gradle.kts index c441ffde2..785f6c1c8 100644 --- a/features/feature_change_category/build.gradle.kts +++ b/features/feature_change_category/build.gradle.kts @@ -17,6 +17,7 @@ android { dependencies { implementation(project(":core")) + // TODO remove feature dependency implementation(project(":feature_change_record_type")) implementation(Deps.Google.dagger) kapt(Deps.Kapt.dagger) diff --git a/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/view/ChangeRecordTypeFragment.kt b/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/view/ChangeRecordTypeFragment.kt index ba179d348..3488f7f75 100644 --- a/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/view/ChangeRecordTypeFragment.kt +++ b/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/view/ChangeRecordTypeFragment.kt @@ -49,9 +49,11 @@ import com.example.util.simpletimetracker.feature_base_adapter.info.createInfoAd import com.example.util.simpletimetracker.feature_base_adapter.loader.createLoaderAdapterDelegate import com.example.util.simpletimetracker.feature_base_adapter.recordType.RecordTypeViewData import com.example.util.simpletimetracker.feature_change_record_type.goals.GoalsViewDelegate +import com.example.util.simpletimetracker.feature_change_record_type.viewData.ChangeRecordTypeAdditionalState import com.example.util.simpletimetracker.feature_change_record_type.viewData.ChangeRecordTypeCategoriesViewData import com.example.util.simpletimetracker.feature_change_record_type.viewData.ChangeRecordTypeChooserState import com.example.util.simpletimetracker.feature_change_record_type.viewData.ChangeRecordTypeChooserState.State +import com.example.util.simpletimetracker.feature_change_record_type.viewData.ChangeRecordTypeChooserState.State.Additional import com.example.util.simpletimetracker.feature_change_record_type.viewData.ChangeRecordTypeChooserState.State.Category import com.example.util.simpletimetracker.feature_change_record_type.viewData.ChangeRecordTypeChooserState.State.Closed import com.example.util.simpletimetracker.feature_change_record_type.viewData.ChangeRecordTypeChooserState.State.Color @@ -194,9 +196,14 @@ class ChangeRecordTypeFragment : fieldChangeRecordTypeIcon.setOnClick(viewModel::onIconChooserClick) fieldChangeRecordTypeCategory.setOnClick(viewModel::onCategoryChooserClick) fieldChangeRecordTypeGoalTime.setOnClick(viewModel::onGoalTimeChooserClick) + fieldChangeRecordTypeAdditional.setOnClick(viewModel::onAdditionalChooserClick) btnChangeRecordTypeSave.setOnClick(viewModel::onSaveClick) btnChangeRecordTypeDelete.setOnClick(viewModel::onDeleteClick) btnChangeRecordTypeStatistics.setOnClick(viewModel::onStatisticsClick) + layoutChangeRecordTypeAdditional.btnChangeRecordTypeAdditionalDuplicate + .setOnClick(viewModel::onDuplicateClick) + layoutChangeRecordTypeAdditional.checkboxChangeRecordTypeAdditionalInstant + .setOnClick(viewModel::onInstantClick) IconSelectionViewDelegate.initUx( viewModel = viewModel, layout = containerChangeRecordTypeIcon, @@ -227,6 +234,10 @@ class ChangeRecordTypeFragment : categories.observe(::updateCategories) goalsViewData.observe(::updateGoalsState) nameErrorMessage.observe(::updateNameErrorMessage) + additionalState.observe(::updateAdditionalState) + duplicateButtonEnabled.observe( + layoutChangeRecordTypeAdditional.btnChangeRecordTypeAdditionalDuplicate::setEnabled, + ) notificationsHintVisible.observe( layoutChangeRecordTypeGoals.containerChangeRecordTypeGoalNotificationsHint::visible::set, ) @@ -362,6 +373,12 @@ class ChangeRecordTypeFragment : chooserView = fieldChangeRecordTypeGoalTime, chooserArrow = arrowChangeRecordTypeGoalTime, ) + updateChooser( + state = state, + chooserData = containerChangeRecordTypeAdditional, + chooserView = fieldChangeRecordTypeAdditional, + chooserArrow = arrowChangeRecordTypeAdditional, + ) val isClosed = state.current is Closed inputChangeRecordTypeName.isVisible = isClosed @@ -376,6 +393,7 @@ class ChangeRecordTypeFragment : fieldChangeRecordTypeIcon.isVisible = isClosed || state.current is Icon fieldChangeRecordTypeCategory.isVisible = isClosed || state.current is Category fieldChangeRecordTypeGoalTime.isVisible = isClosed || state.current is GoalTime + fieldChangeRecordTypeAdditional.isVisible = isClosed || state.current is Additional } private fun updateGoalsState(state: ChangeRecordTypeGoalsViewData) = with(binding) { @@ -437,6 +455,15 @@ class ChangeRecordTypeFragment : inputChangeRecordTypeName.isErrorEnabled = error.isNotEmpty() } + private fun updateAdditionalState( + data: ChangeRecordTypeAdditionalState, + ) = with(binding.layoutChangeRecordTypeAdditional) { + btnChangeRecordTypeAdditionalDuplicate.isVisible = data.isDuplicateVisible + if (data.isInstantChecked != checkboxChangeRecordTypeAdditionalInstant.isChecked) { + checkboxChangeRecordTypeAdditionalInstant.isChecked = data.isInstantChecked + } + } + private inline fun updateChooser( state: ChangeRecordTypeChooserState, chooserData: View, diff --git a/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/viewData/ChangeRecordTypeAdditionalState.kt b/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/viewData/ChangeRecordTypeAdditionalState.kt new file mode 100644 index 000000000..afd450c67 --- /dev/null +++ b/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/viewData/ChangeRecordTypeAdditionalState.kt @@ -0,0 +1,6 @@ +package com.example.util.simpletimetracker.feature_change_record_type.viewData + +data class ChangeRecordTypeAdditionalState( + val isDuplicateVisible: Boolean, + val isInstantChecked: Boolean, +) \ No newline at end of file diff --git a/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/viewData/ChangeRecordTypeChooserState.kt b/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/viewData/ChangeRecordTypeChooserState.kt index 964cc1c99..2cc48b279 100644 --- a/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/viewData/ChangeRecordTypeChooserState.kt +++ b/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/viewData/ChangeRecordTypeChooserState.kt @@ -11,6 +11,7 @@ data class ChangeRecordTypeChooserState( object Icon : State object Category : State object GoalTime : State + object Additional : State object Type : State } } diff --git a/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/viewModel/ChangeRecordTypeViewModel.kt b/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/viewModel/ChangeRecordTypeViewModel.kt index 5a99538f8..66604426c 100644 --- a/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/viewModel/ChangeRecordTypeViewModel.kt +++ b/features/feature_change_record_type/src/main/java/com/example/util/simpletimetracker/feature_change_record_type/viewModel/ChangeRecordTypeViewModel.kt @@ -8,13 +8,14 @@ import com.example.util.simpletimetracker.core.delegates.colorSelection.ColorSel import com.example.util.simpletimetracker.core.delegates.colorSelection.ColorSelectionViewModelDelegateImpl import com.example.util.simpletimetracker.core.delegates.iconSelection.viewModelDelegate.IconSelectionViewModelDelegate import com.example.util.simpletimetracker.core.delegates.iconSelection.viewModelDelegate.IconSelectionViewModelDelegateImpl -import com.example.util.simpletimetracker.domain.extension.addOrRemove import com.example.util.simpletimetracker.core.extension.set import com.example.util.simpletimetracker.core.interactor.SnackBarMessageNavigationInteractor import com.example.util.simpletimetracker.core.interactor.StatisticsDetailNavigationInteractor import com.example.util.simpletimetracker.core.mapper.RecordTypeViewDataMapper import com.example.util.simpletimetracker.core.repo.ResourceRepo +import com.example.util.simpletimetracker.domain.extension.addOrRemove import com.example.util.simpletimetracker.domain.extension.orZero +import com.example.util.simpletimetracker.domain.interactor.ActivityFilterInteractor import com.example.util.simpletimetracker.domain.interactor.NotificationGoalTimeInteractor import com.example.util.simpletimetracker.domain.interactor.NotificationTypeInteractor import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor @@ -34,6 +35,7 @@ import com.example.util.simpletimetracker.feature_change_record_type.R import com.example.util.simpletimetracker.feature_change_record_type.goals.GoalsViewModelDelegate import com.example.util.simpletimetracker.feature_change_record_type.goals.GoalsViewModelDelegateImpl import com.example.util.simpletimetracker.feature_change_record_type.interactor.ChangeRecordTypeViewDataInteractor +import com.example.util.simpletimetracker.feature_change_record_type.viewData.ChangeRecordTypeAdditionalState import com.example.util.simpletimetracker.feature_change_record_type.viewData.ChangeRecordTypeCategoriesViewData import com.example.util.simpletimetracker.feature_change_record_type.viewData.ChangeRecordTypeChooserState import com.example.util.simpletimetracker.navigation.Router @@ -54,6 +56,7 @@ class ChangeRecordTypeViewModel @Inject constructor( private val runningRecordInteractor: RunningRecordInteractor, private val viewDataInteractor: ChangeRecordTypeViewDataInteractor, private val recordTypeCategoryInteractor: RecordTypeCategoryInteractor, + private val activityFilterInteractor: ActivityFilterInteractor, private val widgetInteractor: WidgetInteractor, private val wearInteractor: WearInteractor, private val notificationTypeInteractor: NotificationTypeInteractor, @@ -96,8 +99,15 @@ class ChangeRecordTypeViewModel @Inject constructor( previous = ChangeRecordTypeChooserState.State.Closed, ), ) + val additionalState: LiveData = MutableLiveData( + ChangeRecordTypeAdditionalState( + isDuplicateVisible = false, + isInstantChecked = false, + ), + ) val deleteButtonEnabled: LiveData = MutableLiveData(true) val saveButtonEnabled: LiveData = MutableLiveData(true) + val duplicateButtonEnabled: LiveData = MutableLiveData(true) val nameErrorMessage: LiveData = MutableLiveData("") val deleteIconVisibility: LiveData by lazy { MutableLiveData(recordTypeId != 0L) } val statsIconVisibility: LiveData by lazy { MutableLiveData(recordTypeId != 0L) } @@ -107,6 +117,7 @@ class ChangeRecordTypeViewModel @Inject constructor( private var initialCategories: Set = emptySet() private var newName: String = "" private var newCategories: MutableList = mutableListOf() + private var newIsInstant: Boolean = false init { colorSelectionViewModelDelegateImpl.attach(getColorSelectionDelegateParent()) @@ -162,6 +173,10 @@ class ChangeRecordTypeViewModel @Inject constructor( onNewChooserState(ChangeRecordTypeChooserState.State.GoalTime) } + fun onAdditionalChooserClick() { + onNewChooserState(ChangeRecordTypeChooserState.State.Additional) + } + fun onCategoryClick(item: CategoryViewData) { viewModelScope.launch { newCategories.addOrRemove(item.id) @@ -229,10 +244,7 @@ class ChangeRecordTypeViewModel @Inject constructor( } fun onSaveClick() { - if (newName.isEmpty()) { - showMessage(coreR.string.change_record_message_choose_name) - return - } + if (isNameEmpty()) return saveButtonEnabled.set(false) viewModelScope.launch { val addedId = saveRecordType() @@ -255,6 +267,38 @@ class ChangeRecordTypeViewModel @Inject constructor( } } + // TODO INSTANT add translations + fun onDuplicateClick() { + if (isNameEmpty()) return + duplicateButtonEnabled.set(false) + viewModelScope.launch { + val addedId = duplicateRecordType() + recordTypeCategoryInteractor.addCategories(addedId, newCategories) + goalsViewModelDelegate.saveGoals(RecordTypeGoal.IdData.Type(addedId)) + activityFilterInteractor.getByTypeId(recordTypeId).forEach { filter -> + val newFilter = filter.copy( + selectedIds = (filter.selectedIds + addedId).toSet().toList(), + ) + activityFilterInteractor.add(newFilter) + } + onSaveClick() + } + } + + fun onInstantClick() = viewModelScope.launch { + newIsInstant = !newIsInstant + updateAdditionalState() + } + + private fun isNameEmpty(): Boolean { + return if (newName.isEmpty()) { + showMessage(coreR.string.change_record_message_choose_name) + true + } else { + false + } + } + private fun onNewChooserState( newState: ChangeRecordTypeChooserState.State, ) { @@ -285,6 +329,33 @@ class ChangeRecordTypeViewModel @Inject constructor( name = newName, icon = iconSelectionViewModelDelegateImpl.newIcon, color = colorSelectionViewModelDelegateImpl.newColor, + instant = newIsInstant, + ) + + return recordTypeInteractor.add(recordType) + } + + private suspend fun duplicateRecordType(): Long { + // Copy will have a name like "type (2)", + // if already exist - "type (3)" etc. + val typeNames = recordTypeInteractor.getAll().map { it.name } + var index = 2 + var name: String + + while (true) { + name = "$newName ($index)" + if (name in typeNames && index < 100) { + index += 1 + } else { + break + } + } + + val recordType = RecordType( + name = name, + icon = iconSelectionViewModelDelegateImpl.newIcon, + color = colorSelectionViewModelDelegateImpl.newColor, + instant = newIsInstant ) return recordTypeInteractor.add(recordType) @@ -301,11 +372,13 @@ class ChangeRecordTypeViewModel @Inject constructor( private suspend fun initializeRecordTypeData() { recordTypeInteractor.get(recordTypeId)?.let { newName = it.name + newIsInstant = it.instant iconSelectionViewModelDelegateImpl.newIcon = it.icon colorSelectionViewModelDelegateImpl.newColor = it.color goalsViewModelDelegate.initialize(RecordTypeGoal.IdData.Type(it.id)) iconSelectionViewModelDelegateImpl.update() colorSelectionViewModelDelegateImpl.update() + updateAdditionalState() } } @@ -342,6 +415,14 @@ class ChangeRecordTypeViewModel @Inject constructor( } } + private fun showMessage(stringResId: Int) { + snackBarMessageNavigationInteractor.showMessage(stringResId) + } + + private fun showArchivedMessage(stringResId: Int) { + snackBarMessageNavigationInteractor.showArchiveMessage(stringResId) + } + private suspend fun updateRecordPreviewViewData() { val data = loadRecordPreviewViewData() recordType.set(data) @@ -354,6 +435,7 @@ class ChangeRecordTypeViewModel @Inject constructor( name = newName, icon = iconSelectionViewModelDelegateImpl.newIcon, color = colorSelectionViewModelDelegateImpl.newColor, + instant = newIsInstant, ).let { recordTypeViewDataMapper.map(it, isDarkTheme) } } @@ -366,11 +448,15 @@ class ChangeRecordTypeViewModel @Inject constructor( return viewDataInteractor.getCategoriesViewData(newCategories) } - private fun showMessage(stringResId: Int) { - snackBarMessageNavigationInteractor.showMessage(stringResId) + private fun updateAdditionalState() { + val data = loadAdditionalState() + additionalState.set(data) } - private fun showArchivedMessage(stringResId: Int) { - snackBarMessageNavigationInteractor.showArchiveMessage(stringResId) + private fun loadAdditionalState(): ChangeRecordTypeAdditionalState { + return ChangeRecordTypeAdditionalState( + isDuplicateVisible = extra is ChangeRecordTypeParams.Change, + isInstantChecked = newIsInstant, + ) } } diff --git a/features/feature_change_record_type/src/main/res/layout/change_record_type_additional_layout.xml b/features/feature_change_record_type/src/main/res/layout/change_record_type_additional_layout.xml new file mode 100644 index 000000000..aa8c264e6 --- /dev/null +++ b/features/feature_change_record_type/src/main/res/layout/change_record_type_additional_layout.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/features/feature_change_record_type/src/main/res/layout/change_record_type_fragment.xml b/features/feature_change_record_type/src/main/res/layout/change_record_type_fragment.xml index 55e75d18e..b2991d1f7 100644 --- a/features/feature_change_record_type/src/main/res/layout/change_record_type_fragment.xml +++ b/features/feature_change_record_type/src/main/res/layout/change_record_type_fragment.xml @@ -352,12 +352,48 @@ + + + + + + + + + + + + + app:layout_constraintTop_toBottomOf="@id/fieldChangeRecordTypeAdditional" /> @@ -423,6 +459,25 @@ + + + + + + () { } private fun onDeleteClick() { - MainScope().launch { archiveDialogListener?.onDeleteClick(params) } dismiss() + MainScope().launch { archiveDialogListener?.onDeleteClick(params) } } private fun onRestoreClick() { - MainScope().launch { archiveDialogListener?.onRestoreClick(params) } dismiss() + MainScope().launch { archiveDialogListener?.onRestoreClick(params) } } companion object { diff --git a/features/feature_dialogs/src/main/java/com/example/util/simpletimetracker/feature_dialogs/defaultTypesSelection/interactor/GetDefaultRecordTypesInteractor.kt b/features/feature_dialogs/src/main/java/com/example/util/simpletimetracker/feature_dialogs/defaultTypesSelection/interactor/GetDefaultRecordTypesInteractor.kt index 14ace1553..f8338c81d 100644 --- a/features/feature_dialogs/src/main/java/com/example/util/simpletimetracker/feature_dialogs/defaultTypesSelection/interactor/GetDefaultRecordTypesInteractor.kt +++ b/features/feature_dialogs/src/main/java/com/example/util/simpletimetracker/feature_dialogs/defaultTypesSelection/interactor/GetDefaultRecordTypesInteractor.kt @@ -15,6 +15,7 @@ class GetDefaultRecordTypesInteractor @Inject constructor() { name = type.name, icon = type.icon, color = AppColor(colorId = type.colorId, colorInt = ""), + instant = false, ) } } diff --git a/resources/src/main/res/values-ar/strings.xml b/resources/src/main/res/values-ar/strings.xml index fba6aaa4f..1dd4dca4e 100644 --- a/resources/src/main/res/values-ar/strings.xml +++ b/resources/src/main/res/values-ar/strings.xml @@ -149,6 +149,9 @@ لا توجد تصنيفات مضافة غير مفعل الهدف + إضافي + فوري + الأنشطة الفورية ليس لها مدة ويتم تتبعها فورًا عند النقر. سيظهر الإخطار بعد الوصول إلى الهدف الجلسة @string/range_day diff --git a/resources/src/main/res/values-ca/strings.xml b/resources/src/main/res/values-ca/strings.xml index dafc35281..987ba3194 100644 --- a/resources/src/main/res/values-ca/strings.xml +++ b/resources/src/main/res/values-ca/strings.xml @@ -149,6 +149,9 @@ No s\'han afegit categories Desactivat Objectiu + Addicional + Instant + Les activitats instantànies no tenen durada i es fan un seguiment immediatament en fer clic. La notificació es mostrarà després d\'arribar a l\'objectiu Sessió @string/range_day diff --git a/resources/src/main/res/values-de/strings.xml b/resources/src/main/res/values-de/strings.xml index dc2173230..1085851ed 100644 --- a/resources/src/main/res/values-de/strings.xml +++ b/resources/src/main/res/values-de/strings.xml @@ -149,6 +149,9 @@ Keine Kategorien hinzugefügt Deaktiviert Ziel + Zusätzlich + Sofort + Sofortige Aktivitäten haben keine Dauer und werden sofort beim Klicken verfolgt. Nach Erreichen des Ziels wird eine Benachrichtigung angezeigt Session @string/range_day diff --git a/resources/src/main/res/values-es/strings.xml b/resources/src/main/res/values-es/strings.xml index d299fdd32..845cf9f83 100644 --- a/resources/src/main/res/values-es/strings.xml +++ b/resources/src/main/res/values-es/strings.xml @@ -149,6 +149,9 @@ No se añadieron categorías Deshabilitado Objetivo + Adicional + Instante + Las actividades instantáneas no tienen duración y se rastrean inmediatamente al hacer clic. La notificación se mostrará después de alcanzar la meta. Sesión @string/range_day diff --git a/resources/src/main/res/values-fa/strings.xml b/resources/src/main/res/values-fa/strings.xml index c2084f3b6..8a87cfb8f 100644 --- a/resources/src/main/res/values-fa/strings.xml +++ b/resources/src/main/res/values-fa/strings.xml @@ -149,6 +149,9 @@ دسته بندی ای اضافه نشد غیر فعال هدف + اضافی + فوری + فعالیت های فوری مدت زمان ندارند و بلافاصله با کلیک ردیابی می شوند. اعلان پس از رسیدن به هدف نشان داده می شود جلسه @string/range_day diff --git a/resources/src/main/res/values-fr/strings.xml b/resources/src/main/res/values-fr/strings.xml index 32abb072a..e63409e7f 100644 --- a/resources/src/main/res/values-fr/strings.xml +++ b/resources/src/main/res/values-fr/strings.xml @@ -149,6 +149,9 @@ Aucune catégorie ajoutée Désactivé Objectif + Supplémentaire + Instantané + Les activités instantanées n\'ont pas de durée et sont suivies immédiatement au clic. Une notification sera affichée après avoir atteint l\'objectif Session @string/range_day diff --git a/resources/src/main/res/values-hi/strings.xml b/resources/src/main/res/values-hi/strings.xml index d189e05a9..1ce3da65c 100644 --- a/resources/src/main/res/values-hi/strings.xml +++ b/resources/src/main/res/values-hi/strings.xml @@ -149,6 +149,9 @@ कोई श्रेणियां नहीं जोड़ी अक्षम लक्ष्य + अतिरिक्त + तुरंत + त्वरित गतिविधियों की कोई अवधि नहीं होती और क्लिक पर तुरंत ट्रैक किया जाता है। लक्ष्य तक पहुंचने के बाद अधिसूचना दिखाई जाएगी सत्र @string/range_day diff --git a/resources/src/main/res/values-in/strings.xml b/resources/src/main/res/values-in/strings.xml index d162c99ab..f770a9b32 100644 --- a/resources/src/main/res/values-in/strings.xml +++ b/resources/src/main/res/values-in/strings.xml @@ -149,6 +149,9 @@ Tidak ada kategori yang ditambahkan Dinonaktifkan Tujuan + Tambahan + Instan + Aktivitas instan tidak memiliki durasi dan langsung dilacak saat diklik. Pemberitahuan akan ditampilkan setelah mencapai tujuan Sidang @string/range_day diff --git a/resources/src/main/res/values-it/strings.xml b/resources/src/main/res/values-it/strings.xml index be95497de..b2370acf7 100644 --- a/resources/src/main/res/values-it/strings.xml +++ b/resources/src/main/res/values-it/strings.xml @@ -149,6 +149,9 @@ Nessuna categoria aggiunta Disabilitato Obiettivo + Ulteriori + Istantaneo + Le attività istantanee non hanno durata e vengono tracciate immediatamente al clic. La notifica verrà mostrata dopo aver raggiunto l\'obiettivo Sessione @string/range_day diff --git a/resources/src/main/res/values-ja/strings.xml b/resources/src/main/res/values-ja/strings.xml index b241c7c13..916530851 100644 --- a/resources/src/main/res/values-ja/strings.xml +++ b/resources/src/main/res/values-ja/strings.xml @@ -149,6 +149,9 @@ カテゴリが追加されていません 未設定 目標 + 追加 + インスタント + インスタントアクティビティには期間がなく、クリックするとすぐに追跡されます。 目標達成後に通知が表示されます セッション @string/range_day diff --git a/resources/src/main/res/values-ko/strings.xml b/resources/src/main/res/values-ko/strings.xml index 0b97f00cb..946ea0e10 100644 --- a/resources/src/main/res/values-ko/strings.xml +++ b/resources/src/main/res/values-ko/strings.xml @@ -149,6 +149,9 @@ 카테고리 추가되지 않음 비활성화됨 목표 + 추가의 + 즉각적인 + 인스턴트 활동에는 기간이 없으며 클릭 시 즉시 추적됩니다. 목표 달성시 알림을 보냅니다. 세션 @string/range_day diff --git a/resources/src/main/res/values-nl/strings.xml b/resources/src/main/res/values-nl/strings.xml index 02d58670f..2d1006a08 100644 --- a/resources/src/main/res/values-nl/strings.xml +++ b/resources/src/main/res/values-nl/strings.xml @@ -149,6 +149,9 @@ Geen categorieën toegevoegd Uitgeschakeld Doel + Aanvullend + Direct + Instantactiviteiten hebben geen duur en worden onmiddellijk bijgehouden na klikken. Melding wordt getoond na het bereiken van het doel Sessie @string/range_day diff --git a/resources/src/main/res/values-pl/strings.xml b/resources/src/main/res/values-pl/strings.xml index 20fa012ec..62a37ee35 100644 --- a/resources/src/main/res/values-pl/strings.xml +++ b/resources/src/main/res/values-pl/strings.xml @@ -149,6 +149,9 @@ Brak dodanej kategorii Wyłączony Cel + Dodatkowy + Natychmiastowy + Działania natychmiastowe nie mają czasu trwania i są śledzone natychmiast po kliknięciu. Powiadomienie wyświetli się po osiągnięciu celu Sesja @string/range_day diff --git a/resources/src/main/res/values-pt-rPT/strings.xml b/resources/src/main/res/values-pt-rPT/strings.xml index a01d68361..b68e040a9 100644 --- a/resources/src/main/res/values-pt-rPT/strings.xml +++ b/resources/src/main/res/values-pt-rPT/strings.xml @@ -149,6 +149,9 @@ Nenhuma categoria adicionada Desativado Meta + Adicional + Instantâneo + As atividades instantâneas não têm duração e são rastreadas imediatamente ao clicar. A notificação será exibida depois da meta atingida Sessão @string/range_day diff --git a/resources/src/main/res/values-pt/strings.xml b/resources/src/main/res/values-pt/strings.xml index d925e7772..3c8596244 100644 --- a/resources/src/main/res/values-pt/strings.xml +++ b/resources/src/main/res/values-pt/strings.xml @@ -149,6 +149,9 @@ Nenhuma categoria adicionada Desativado Meta + Adicional + Instantâneo + As atividades instantâneas não têm duração e são rastreadas imediatamente ao clicar. A notificação será exibida após atingir a meta Sessão @string/range_day diff --git a/resources/src/main/res/values-ro/strings.xml b/resources/src/main/res/values-ro/strings.xml index 6090ecf10..ddc84a396 100644 --- a/resources/src/main/res/values-ro/strings.xml +++ b/resources/src/main/res/values-ro/strings.xml @@ -149,6 +149,9 @@ Nu au fost categorii adăugate Dezactivat Țel + Adiţional + Instant + Activitățile instantanee nu au durată și sunt urmărite imediat la clic. Notificările vor fi vizibile după atingerea țelului Sesiune @string/range_day diff --git a/resources/src/main/res/values-ru/strings.xml b/resources/src/main/res/values-ru/strings.xml index 86cc3cd31..d8c8ac279 100644 --- a/resources/src/main/res/values-ru/strings.xml +++ b/resources/src/main/res/values-ru/strings.xml @@ -149,6 +149,9 @@ Категории не добавлены Выкл. Цель + Дополнительно + Мгновенный + Мгновенные действия не имеют продолжительности и отслеживаются сразу по клику. Уведомление будет показано после достижения цели Сессия @string/range_day diff --git a/resources/src/main/res/values-sv/strings.xml b/resources/src/main/res/values-sv/strings.xml index 62f49080c..7581ece95 100644 --- a/resources/src/main/res/values-sv/strings.xml +++ b/resources/src/main/res/values-sv/strings.xml @@ -149,6 +149,9 @@ Inga kategorier har lagts till Inaktiverad Mål + Ytterligare + Omedelbar + Omedelbara aktiviteter har ingen varaktighet och spåras direkt vid klick. Avisering kommer att visas efter att du har nått målet Session @string/range_day diff --git a/resources/src/main/res/values-tr/strings.xml b/resources/src/main/res/values-tr/strings.xml index 1ddf3f48e..89982b646 100644 --- a/resources/src/main/res/values-tr/strings.xml +++ b/resources/src/main/res/values-tr/strings.xml @@ -149,6 +149,9 @@ Kategori eklenmedi Devre dışı Hedef + Ek olarak + Ani + Anlık aktivitelerin süresi yoktur ve tıklandığında anında izlenir. Hedefe ulaştıktan sonra bildirim gösterilecek Dönem @string/range_day diff --git a/resources/src/main/res/values-uk/strings.xml b/resources/src/main/res/values-uk/strings.xml index 0bcbed713..b9e4cb158 100644 --- a/resources/src/main/res/values-uk/strings.xml +++ b/resources/src/main/res/values-uk/strings.xml @@ -149,6 +149,9 @@ Категорії не додано Вимкнено Ціль + Додатковий + Миттєво + Миттєві дії не мають тривалості та відстежуються одразу після натискання. Сповіщення буде показано після досягнення мети Сесія @string/range_day diff --git a/resources/src/main/res/values-vi/strings.xml b/resources/src/main/res/values-vi/strings.xml index 678458442..dff7afcff 100644 --- a/resources/src/main/res/values-vi/strings.xml +++ b/resources/src/main/res/values-vi/strings.xml @@ -149,6 +149,9 @@ Chưa thêm danh mục nào Đã tắt Mục tiêu + Thêm vào + Lập tức + Hoạt động tức thì không có thời lượng và được theo dõi ngay lập tức khi nhấp chuột. Thông báo sẽ được hiển thị sau khi đạt được mục tiêu Phiên @string/range_day diff --git a/resources/src/main/res/values-zh-rTW/strings.xml b/resources/src/main/res/values-zh-rTW/strings.xml index 110fe4326..cb762e1e2 100644 --- a/resources/src/main/res/values-zh-rTW/strings.xml +++ b/resources/src/main/res/values-zh-rTW/strings.xml @@ -149,6 +149,9 @@ 沒有新增分類 關閉 目標 + 額外的 + 立即的 + 即時活動沒有持續時間,點擊後立即進行追蹤。 達到目標後將顯示通知 節段 @string/range_day diff --git a/resources/src/main/res/values-zh/strings.xml b/resources/src/main/res/values-zh/strings.xml index efb2adf84..66c098307 100644 --- a/resources/src/main/res/values-zh/strings.xml +++ b/resources/src/main/res/values-zh/strings.xml @@ -149,6 +149,9 @@ 未添加任何类别 不启用 目标 + 额外的 + 立即的 + 即时活动没有持续时间,点击后立即进行跟踪。 达到目标后将显示通知 阶段 @string/range_day diff --git a/resources/src/main/res/values/strings.xml b/resources/src/main/res/values/strings.xml index 9dfb9e25b..d2d2bd7ae 100644 --- a/resources/src/main/res/values/strings.xml +++ b/resources/src/main/res/values/strings.xml @@ -149,6 +149,9 @@ No categories added Disabled Goal + Additional + Instant + Instant activities have no duration and tracked immediately on click. Notification will be shown after reaching the goal Session @string/range_day