Loading src/com/android/customization/model/grid/DefaultShapeGridManager.kt +69 −34 Original line number Diff line number Diff line Loading @@ -39,14 +39,11 @@ constructor( context.getString(R.string.grid_control_metadata_name) private val previewUtils: PreviewUtils = PreviewUtils(context, authorityMetadataKey) override suspend fun isGridOptionAvailable(): Boolean { return previewUtils.supportsPreview() && (getGridOptions()?.size ?: 0) > 1 } override suspend fun getGridOptions(): List<GridOptionModel>? = withContext(bgDispatcher) { if (previewUtils.supportsPreview()) { context.contentResolver .query(previewUtils.getUri(LIST_OPTIONS), null, null, null, null) .query(previewUtils.getUri(GRID_OPTIONS), null, null, null, null) ?.use { cursor -> buildList { while (cursor.moveToNext()) { Loading @@ -54,7 +51,7 @@ constructor( val cols = cursor.getInt(cursor.getColumnIndex(COL_COLS)) add( GridOptionModel( key = cursor.getString(cursor.getColumnIndex(COL_NAME)), key = cursor.getString(cursor.getColumnIndex(COL_GRID_KEY)), title = context.getString( com.android.themepicker.R.string.grid_title_pattern, Loading @@ -72,23 +69,61 @@ constructor( } } } } else { null } } override suspend fun getShapeOptions(): List<ShapeOptionModel>? = withContext(bgDispatcher) { if (previewUtils.supportsPreview()) { context.contentResolver .query(previewUtils.getUri(SHAPE_OPTIONS), null, null, null, null) ?.use { cursor -> buildList { while (cursor.moveToNext()) { add( ShapeOptionModel( key = cursor.getString(cursor.getColumnIndex(COL_SHAPE_KEY)), title = cursor.getString(cursor.getColumnIndex(COL_TITLE)), path = cursor.getString(cursor.getColumnIndex(COL_PATH)), isCurrent = cursor .getString(cursor.getColumnIndex(COL_IS_DEFAULT)) .toBoolean(), ) ) } } } } else { null } } override fun applyGridOption(gridName: String): Int { override fun applyShapeGridOption(shapeKey: String, gridKey: String): Int { return context.contentResolver.update( previewUtils.getUri(DEFAULT_GRID), ContentValues().apply { put("name", gridName) }, previewUtils.getUri(SHAPE_GRID), ContentValues().apply { put(COL_SHAPE_KEY, shapeKey) put(COL_GRID_KEY, gridKey) }, null, null, ) } companion object { const val LIST_OPTIONS: String = "list_options" const val DEFAULT_GRID: String = "default_grid" const val COL_NAME: String = "name" const val SHAPE_OPTIONS: String = "shape_options" const val GRID_OPTIONS: String = "grid_options" const val SHAPE_GRID: String = "default_grid" const val COL_SHAPE_KEY: String = "shape_key" const val COL_GRID_KEY: String = "name" const val COL_ROWS: String = "rows" const val COL_COLS: String = "cols" const val COL_IS_DEFAULT: String = "is_default" const val COL_TITLE: String = "title" const val COL_PATH: String = "path" } } src/com/android/customization/model/grid/ShapeGridManager.kt +3 −3 Original line number Diff line number Diff line Loading @@ -18,9 +18,9 @@ package com.android.customization.model.grid interface ShapeGridManager { suspend fun isGridOptionAvailable(): Boolean suspend fun getGridOptions(): List<GridOptionModel>? fun applyGridOption(gridName: String): Int suspend fun getShapeOptions(): List<ShapeOptionModel>? fun applyShapeGridOption(shapeKey: String, gridKey: String): Int } src/com/android/customization/model/grid/ShapeOptionModel.kt 0 → 100644 +24 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.customization.model.grid data class ShapeOptionModel( val key: String, val title: String, val path: String, val isCurrent: Boolean, ) src/com/android/customization/picker/grid/data/repository/ShapeGridRepository.kt +13 −8 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.customization.picker.grid.data.repository import com.android.customization.model.grid.GridOptionModel import com.android.customization.model.grid.ShapeGridManager import com.android.customization.model.grid.ShapeOptionModel import com.android.wallpaper.picker.di.modules.BackgroundDispatcher import javax.inject.Inject import javax.inject.Singleton Loading @@ -41,27 +42,31 @@ constructor( @BackgroundDispatcher private val bgDispatcher: CoroutineDispatcher, ) { suspend fun isGridOptionAvailable(): Boolean = withContext(bgDispatcher) { manager.isGridOptionAvailable() } private val _shapeOptions = MutableStateFlow<List<ShapeOptionModel>?>(null) private val _gridOptions = MutableStateFlow<List<GridOptionModel>?>(null) init { bgScope.launch { val options = manager.getGridOptions() _gridOptions.value = options _gridOptions.value = manager.getGridOptions() _shapeOptions.value = manager.getShapeOptions() } } val shapeOptions: StateFlow<List<ShapeOptionModel>?> = _shapeOptions.asStateFlow() val selectedShapeOption: Flow<ShapeOptionModel?> = shapeOptions.map { shapeOptions -> shapeOptions?.firstOrNull { it.isCurrent } } val gridOptions: StateFlow<List<GridOptionModel>?> = _gridOptions.asStateFlow() val selectedGridOption: Flow<GridOptionModel?> = gridOptions.map { gridOptions -> gridOptions?.firstOrNull { it.isCurrent } } suspend fun applySelectedOption(key: String) = suspend fun applySelectedOption(shapeKey: String, gridKey: String) = withContext(bgDispatcher) { manager.applyGridOption(key) // After applying new grid option, we should query and update the grid options again. manager.applyShapeGridOption(shapeKey, gridKey) // After applying, we should query and update shape and grid options again. _gridOptions.value = manager.getGridOptions() _shapeOptions.value = manager.getShapeOptions() } } src/com/android/customization/picker/grid/domain/interactor/ShapeGridInteractor.kt +6 −2 Original line number Diff line number Diff line Loading @@ -23,11 +23,15 @@ import javax.inject.Singleton @Singleton class ShapeGridInteractor @Inject constructor(private val repository: ShapeGridRepository) { suspend fun isGridOptionAvailable(): Boolean = repository.isGridOptionAvailable() val shapeOptions = repository.shapeOptions val selectedShapeOption = repository.selectedShapeOption val gridOptions = repository.gridOptions val selectedGridOption = repository.selectedGridOption suspend fun applySelectedOption(key: String) = repository.applySelectedOption(key) suspend fun applySelectedOption(shapeKey: String, gridKey: String) = repository.applySelectedOption(shapeKey, gridKey) } Loading
src/com/android/customization/model/grid/DefaultShapeGridManager.kt +69 −34 Original line number Diff line number Diff line Loading @@ -39,14 +39,11 @@ constructor( context.getString(R.string.grid_control_metadata_name) private val previewUtils: PreviewUtils = PreviewUtils(context, authorityMetadataKey) override suspend fun isGridOptionAvailable(): Boolean { return previewUtils.supportsPreview() && (getGridOptions()?.size ?: 0) > 1 } override suspend fun getGridOptions(): List<GridOptionModel>? = withContext(bgDispatcher) { if (previewUtils.supportsPreview()) { context.contentResolver .query(previewUtils.getUri(LIST_OPTIONS), null, null, null, null) .query(previewUtils.getUri(GRID_OPTIONS), null, null, null, null) ?.use { cursor -> buildList { while (cursor.moveToNext()) { Loading @@ -54,7 +51,7 @@ constructor( val cols = cursor.getInt(cursor.getColumnIndex(COL_COLS)) add( GridOptionModel( key = cursor.getString(cursor.getColumnIndex(COL_NAME)), key = cursor.getString(cursor.getColumnIndex(COL_GRID_KEY)), title = context.getString( com.android.themepicker.R.string.grid_title_pattern, Loading @@ -72,23 +69,61 @@ constructor( } } } } else { null } } override suspend fun getShapeOptions(): List<ShapeOptionModel>? = withContext(bgDispatcher) { if (previewUtils.supportsPreview()) { context.contentResolver .query(previewUtils.getUri(SHAPE_OPTIONS), null, null, null, null) ?.use { cursor -> buildList { while (cursor.moveToNext()) { add( ShapeOptionModel( key = cursor.getString(cursor.getColumnIndex(COL_SHAPE_KEY)), title = cursor.getString(cursor.getColumnIndex(COL_TITLE)), path = cursor.getString(cursor.getColumnIndex(COL_PATH)), isCurrent = cursor .getString(cursor.getColumnIndex(COL_IS_DEFAULT)) .toBoolean(), ) ) } } } } else { null } } override fun applyGridOption(gridName: String): Int { override fun applyShapeGridOption(shapeKey: String, gridKey: String): Int { return context.contentResolver.update( previewUtils.getUri(DEFAULT_GRID), ContentValues().apply { put("name", gridName) }, previewUtils.getUri(SHAPE_GRID), ContentValues().apply { put(COL_SHAPE_KEY, shapeKey) put(COL_GRID_KEY, gridKey) }, null, null, ) } companion object { const val LIST_OPTIONS: String = "list_options" const val DEFAULT_GRID: String = "default_grid" const val COL_NAME: String = "name" const val SHAPE_OPTIONS: String = "shape_options" const val GRID_OPTIONS: String = "grid_options" const val SHAPE_GRID: String = "default_grid" const val COL_SHAPE_KEY: String = "shape_key" const val COL_GRID_KEY: String = "name" const val COL_ROWS: String = "rows" const val COL_COLS: String = "cols" const val COL_IS_DEFAULT: String = "is_default" const val COL_TITLE: String = "title" const val COL_PATH: String = "path" } }
src/com/android/customization/model/grid/ShapeGridManager.kt +3 −3 Original line number Diff line number Diff line Loading @@ -18,9 +18,9 @@ package com.android.customization.model.grid interface ShapeGridManager { suspend fun isGridOptionAvailable(): Boolean suspend fun getGridOptions(): List<GridOptionModel>? fun applyGridOption(gridName: String): Int suspend fun getShapeOptions(): List<ShapeOptionModel>? fun applyShapeGridOption(shapeKey: String, gridKey: String): Int }
src/com/android/customization/model/grid/ShapeOptionModel.kt 0 → 100644 +24 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.customization.model.grid data class ShapeOptionModel( val key: String, val title: String, val path: String, val isCurrent: Boolean, )
src/com/android/customization/picker/grid/data/repository/ShapeGridRepository.kt +13 −8 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.customization.picker.grid.data.repository import com.android.customization.model.grid.GridOptionModel import com.android.customization.model.grid.ShapeGridManager import com.android.customization.model.grid.ShapeOptionModel import com.android.wallpaper.picker.di.modules.BackgroundDispatcher import javax.inject.Inject import javax.inject.Singleton Loading @@ -41,27 +42,31 @@ constructor( @BackgroundDispatcher private val bgDispatcher: CoroutineDispatcher, ) { suspend fun isGridOptionAvailable(): Boolean = withContext(bgDispatcher) { manager.isGridOptionAvailable() } private val _shapeOptions = MutableStateFlow<List<ShapeOptionModel>?>(null) private val _gridOptions = MutableStateFlow<List<GridOptionModel>?>(null) init { bgScope.launch { val options = manager.getGridOptions() _gridOptions.value = options _gridOptions.value = manager.getGridOptions() _shapeOptions.value = manager.getShapeOptions() } } val shapeOptions: StateFlow<List<ShapeOptionModel>?> = _shapeOptions.asStateFlow() val selectedShapeOption: Flow<ShapeOptionModel?> = shapeOptions.map { shapeOptions -> shapeOptions?.firstOrNull { it.isCurrent } } val gridOptions: StateFlow<List<GridOptionModel>?> = _gridOptions.asStateFlow() val selectedGridOption: Flow<GridOptionModel?> = gridOptions.map { gridOptions -> gridOptions?.firstOrNull { it.isCurrent } } suspend fun applySelectedOption(key: String) = suspend fun applySelectedOption(shapeKey: String, gridKey: String) = withContext(bgDispatcher) { manager.applyGridOption(key) // After applying new grid option, we should query and update the grid options again. manager.applyShapeGridOption(shapeKey, gridKey) // After applying, we should query and update shape and grid options again. _gridOptions.value = manager.getGridOptions() _shapeOptions.value = manager.getShapeOptions() } }
src/com/android/customization/picker/grid/domain/interactor/ShapeGridInteractor.kt +6 −2 Original line number Diff line number Diff line Loading @@ -23,11 +23,15 @@ import javax.inject.Singleton @Singleton class ShapeGridInteractor @Inject constructor(private val repository: ShapeGridRepository) { suspend fun isGridOptionAvailable(): Boolean = repository.isGridOptionAvailable() val shapeOptions = repository.shapeOptions val selectedShapeOption = repository.selectedShapeOption val gridOptions = repository.gridOptions val selectedGridOption = repository.selectedGridOption suspend fun applySelectedOption(key: String) = repository.applySelectedOption(key) suspend fun applySelectedOption(shapeKey: String, gridKey: String) = repository.applySelectedOption(shapeKey, gridKey) }