From a675e18f15a7fc707c30c3804e7eb805d19ad5e5 Mon Sep 17 00:00:00 2001 From: sameerasw Date: Fri, 23 Jan 2026 19:58:40 +0530 Subject: [PATCH] Watermark logo support --- .../domain/watermark/WatermarkEngine.kt | 130 +++++++++++----- .../domain/watermark/WatermarkRepository.kt | 23 ++- .../composables/watermark/WatermarkScreen.kt | 110 +++++++++++++ .../viewmodels/WatermarkViewModel.kt | 89 ++++++++++- app/src/main/res/drawable/apple.xml | 9 ++ app/src/main/res/drawable/cmf.xml | 145 ++++++++++++++++++ app/src/main/res/drawable/google.xml | 9 ++ app/src/main/res/drawable/moto.xml | 14 ++ app/src/main/res/drawable/nothing.xml | 11 ++ app/src/main/res/drawable/oppo.xml | 10 ++ app/src/main/res/drawable/samsung.xml | 9 ++ app/src/main/res/drawable/sony.xml | 10 ++ app/src/main/res/drawable/vivo.xml | 22 +++ app/src/main/res/drawable/xiaomi.xml | 9 ++ app/src/main/res/values/strings.xml | 3 + 15 files changed, 557 insertions(+), 46 deletions(-) create mode 100644 app/src/main/res/drawable/apple.xml create mode 100644 app/src/main/res/drawable/cmf.xml create mode 100644 app/src/main/res/drawable/google.xml create mode 100644 app/src/main/res/drawable/moto.xml create mode 100644 app/src/main/res/drawable/nothing.xml create mode 100644 app/src/main/res/drawable/oppo.xml create mode 100644 app/src/main/res/drawable/samsung.xml create mode 100644 app/src/main/res/drawable/sony.xml create mode 100644 app/src/main/res/drawable/vivo.xml create mode 100644 app/src/main/res/drawable/xiaomi.xml diff --git a/app/src/main/java/com/sameerasw/essentials/domain/watermark/WatermarkEngine.kt b/app/src/main/java/com/sameerasw/essentials/domain/watermark/WatermarkEngine.kt index a158e316..6813670e 100644 --- a/app/src/main/java/com/sameerasw/essentials/domain/watermark/WatermarkEngine.kt +++ b/app/src/main/java/com/sameerasw/essentials/domain/watermark/WatermarkEngine.kt @@ -54,7 +54,10 @@ data class WatermarkOptions( val customTextSize: Int = 50, val padding: Int = 50, val borderStroke: Int = 0, - val borderCorner: Int = 0 + val borderCorner: Int = 0, + val showLogo: Boolean = false, + val logoResId: Int? = null, + val logoSize: Int = 50 ) class WatermarkEngine( @@ -161,74 +164,95 @@ class WatermarkEngine( setShadowLayer(4f, 2f, 2f, shadowColor) } - val margin = bitmap.width * (options.padding / 1000f) + val strokeSpacer = (bitmap.width * (options.borderStroke / 1000f)) + val margin = (bitmap.width * (options.padding / 1000f)) + strokeSpacer var yPos = bitmap.height - margin // Apply scaling val brandScale = 0.5f + (options.brandTextSize / 100f) val dataScale = 0.5f + (options.dataTextSize / 100f) - - // Base text size was 3% of width val baseSize = bitmap.width * 0.03f - paint.textSize = baseSize * dataScale + // Logo Calculation + var logoBitmap: Bitmap? = null + var logoWidth = 0f + var logoHeight = 0f + + if (options.showLogo && options.logoResId != null) { + val logoScale = options.logoSize / 100f + val logoSizePx = baseSize * 4f * logoScale + logoBitmap = loadVectorBitmap(context, options.logoResId, overlayTextColor) + if (logoBitmap != null) { + val ratio = logoBitmap.width.toFloat() / logoBitmap.height.toFloat() + logoHeight = logoSizePx + logoWidth = logoHeight * ratio + } + } + + // Draw EXIF if (options.showExif) { + val exifPaint = Paint(paint).apply { textSize = baseSize * dataScale } val exifItems = buildExifList(exifData, options) if (exifItems.isNotEmpty()) { - val maxWidth = bitmap.width - (margin * 2) - - // Wrap items with icons - val rows = wrapExifItems(exifItems, paint, maxWidth) + val maxWidth = bitmap.width - (margin * 2) + val rows = wrapExifItems(exifItems, exifPaint, maxWidth) val reversedRows = rows.reversed() for (row in reversedRows) { - val rowWidth = measureRowWidth(row, paint) - val rowHeight = measureRowHeight(row, paint) - - var xPos = if (options.leftAlignOverlay) margin else (bitmap.width - margin - rowWidth) - - drawExifRow(canvas, row, xPos, yPos, paint, shadowColor) - + val rowWidth = measureRowWidth(row, exifPaint) + val rowHeight = measureRowHeight(row, exifPaint) + val xPos = if (options.leftAlignOverlay) margin else (bitmap.width - margin - rowWidth) + drawExifRow(canvas, row, xPos, yPos, exifPaint, shadowColor) yPos -= rowHeight * 1.2f } } } - + // Draw Custom Text if (options.showCustomText && options.customText.isNotEmpty()) { val customScale = 0.5f + (options.customTextSize / 100f) val customPaint = Paint(paint).apply { textSize = baseSize * customScale typeface = Typeface.DEFAULT } - val textBounds = Rect() customPaint.getTextBounds(options.customText, 0, options.customText.length, textBounds) - - if (options.showExif) { - yPos -= (customPaint.textSize * 0.5f) - } - + if (options.showExif) yPos -= (customPaint.textSize * 0.5f) val xPos = if (options.leftAlignOverlay) margin else (bitmap.width - margin - textBounds.width()) - - // Draw Custom Text canvas.drawText(options.customText, xPos, yPos, customPaint) - yPos -= customPaint.textSize * 1.2f } + // Draw Brand if (options.showDeviceBrand) { val brandString = buildBrandString(exifData) val brandPaint = Paint(paint).apply { typeface = Typeface.DEFAULT_BOLD - textSize = baseSize * brandScale // Use brand scale + textSize = baseSize * brandScale } val textBounds = Rect() brandPaint.getTextBounds(brandString, 0, brandString.length, textBounds) - val xPos = if (options.leftAlignOverlay) margin else (bitmap.width - margin - textBounds.width()) - canvas.drawText(brandString, xPos, yPos, brandPaint) + yPos -= brandPaint.textSize * 1.2f + } + + // Draw the Logo at the TOP of text content + if (logoBitmap != null) { + val logoX = if (options.leftAlignOverlay) margin else (bitmap.width - margin - logoWidth) + val logoY = yPos - logoHeight - (baseSize * 0.2f) // Increased spacing + + val destRect = RectF(logoX, logoY, logoX + logoWidth, logoY + logoHeight) + + if (shadowColor != null) { + val shadowPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { + colorFilter = android.graphics.PorterDuffColorFilter(shadowColor, android.graphics.PorterDuff.Mode.SRC_IN) + alpha = 128 + } + val shadowRect = RectF(destRect).apply { offset(2f, 2f) } + canvas.drawBitmap(logoBitmap, null, shadowRect, shadowPaint) + } + canvas.drawBitmap(logoBitmap, null, destRect, null) } return bitmap @@ -300,7 +324,8 @@ class WatermarkEngine( val minHeight = max(brandPaint.textSize, exifPaint.textSize) * 2f - val calculatedHeight = max(contentHeightLeft, contentHeightRight) + (margin * 2) + val strokeSpacer = (bitmap.width * (options.borderStroke / 1000f)).toInt() + val calculatedHeight = max(contentHeightLeft, contentHeightRight) + (margin * 2) + strokeSpacer val finalFrameHeight = max(minHeight.roundToInt(), calculatedHeight.roundToInt()) @@ -336,7 +361,7 @@ class WatermarkEngine( canvas.drawBitmap(sourceToDraw, 0f, finalFrameHeight.toFloat(), null) // Draw Text in "Forehead" - val centerY = finalFrameHeight / 2f + val centerY = (finalFrameHeight - strokeSpacer) / 2f drawFrameContent( canvas, exifData, options, margin, centerY, brandPaint, exifPaint, exifRows, bitmap.width @@ -347,7 +372,7 @@ class WatermarkEngine( canvas.drawBitmap(sourceToDraw, 0f, 0f, null) // Draw Text in "Chin" - val centerY = bitmap.height + (finalFrameHeight / 2f) + val centerY = bitmap.height + strokeSpacer + ((finalFrameHeight - strokeSpacer) / 2f) drawFrameContent( canvas, exifData, options, margin, centerY, brandPaint, exifPaint, exifRows, bitmap.width @@ -368,15 +393,33 @@ class WatermarkEngine( exifRows: List>, canvasWidth: Int ) { + val colors = deriveColors(options) + val textColor = colors.textColor + // Logo Calculation + var logoBitmap: Bitmap? = null + var logoWidth = 0f + var logoHeight = 0f + val logoSpacing = brandPaint.textSize * 0.5f + + if (options.showLogo && options.logoResId != null) { + val logoScale = options.logoSize / 100f + val logoSizePx = brandPaint.textSize * 2.5f * logoScale + logoBitmap = loadVectorBitmap(context, options.logoResId, textColor) + if (logoBitmap != null) { + val ratio = logoBitmap.width.toFloat() / logoBitmap.height.toFloat() + logoHeight = logoSizePx + logoWidth = logoHeight * ratio + } + } + + val logoAreaWidth = if (logoBitmap != null) logoWidth + logoSpacing else 0f + // Brand & Custom Text on Left var currentLeftY = centerY - var totalLeftHeight = 0f - val customScale = 0.5f + (options.customTextSize / 100f) + val customScale = 0.5f + (options.customTextSize / 100f) val customPaint = Paint(brandPaint).apply { - textSize = (brandPaint.textSize / (0.5f + (options.brandTextSize / 100f))) * customScale - textSize = brandPaint.textSize * (customScale / (0.5f + (options.brandTextSize / 100f))) typeface = Typeface.DEFAULT } @@ -389,25 +432,30 @@ class WatermarkEngine( currentLeftY = centerY - (totalLeftHeight / 2f) + (brandPaint.textSize / 1.5f) - currentLeftY = centerY - (totalLeftHeight / 2f) + brandPaint.textSize + // Draw Logo + if (logoBitmap != null) { + val logoX = margin + val logoY = centerY - (logoHeight / 2f) + canvas.drawBitmap(logoBitmap, null, RectF(logoX, logoY, logoX + logoWidth, logoY + logoHeight), null) + } + + val textX = margin + logoAreaWidth if (options.showDeviceBrand) { val brandString = buildBrandString(exifData) - canvas.drawText(brandString, margin, currentLeftY, brandPaint) + canvas.drawText(brandString, textX, currentLeftY, brandPaint) currentLeftY += (brandPaint.textSize * 0.2f) + customPaint.textSize } else if (options.showCustomText && options.customText.isNotEmpty()) { currentLeftY = centerY - (totalLeftHeight / 2f) + customPaint.textSize } if (options.showCustomText && options.customText.isNotEmpty()) { - - canvas.drawText(options.customText, margin, currentLeftY, customPaint) + canvas.drawText(options.customText, textX, currentLeftY, customPaint) } // Exif on Right if (options.showExif && exifRows.isNotEmpty()) { val lineHeight = exifPaint.textSize * 1.5f - val centeringOffset = (exifRows.size - 1) * lineHeight / 2f var currentY = (centerY + exifPaint.textSize / 3f) - centeringOffset diff --git a/app/src/main/java/com/sameerasw/essentials/domain/watermark/WatermarkRepository.kt b/app/src/main/java/com/sameerasw/essentials/domain/watermark/WatermarkRepository.kt index 12a8a622..094d8d87 100644 --- a/app/src/main/java/com/sameerasw/essentials/domain/watermark/WatermarkRepository.kt +++ b/app/src/main/java/com/sameerasw/essentials/domain/watermark/WatermarkRepository.kt @@ -34,6 +34,8 @@ class WatermarkRepository( private val PREF_PADDING = androidx.datastore.preferences.core.intPreferencesKey("padding") private val PREF_BORDER_STROKE = androidx.datastore.preferences.core.intPreferencesKey("border_stroke") private val PREF_BORDER_CORNER = androidx.datastore.preferences.core.intPreferencesKey("border_corner") + private val PREF_SHOW_LOGO = booleanPreferencesKey("show_logo") + private val PREF_LOGO_SIZE = androidx.datastore.preferences.core.intPreferencesKey("logo_size") val watermarkOptions: Flow = context.dataStore.data .map { preferences -> @@ -68,7 +70,10 @@ class WatermarkRepository( customTextSize = preferences[PREF_CUSTOM_TEXT_SIZE] ?: 50, padding = preferences[PREF_PADDING] ?: 50, borderStroke = preferences[PREF_BORDER_STROKE] ?: 0, - borderCorner = preferences[PREF_BORDER_CORNER] ?: 0 + borderCorner = preferences[PREF_BORDER_CORNER] ?: 0, + showLogo = preferences[PREF_SHOW_LOGO] ?: false, + logoResId = null, + logoSize = preferences[PREF_LOGO_SIZE] ?: 50 ) } @@ -147,4 +152,20 @@ class WatermarkRepository( suspend fun updateBorderCorner(corner: Int) { context.dataStore.edit { it[PREF_BORDER_CORNER] = corner } } + + suspend fun updateLogoSettings(show: Boolean, size: Int) { + context.dataStore.edit { + it[PREF_SHOW_LOGO] = show + it[PREF_LOGO_SIZE] = size + } + } + + suspend fun updateLogoShow(show: Boolean) { + context.dataStore.edit { it[PREF_SHOW_LOGO] = show } + } + + + suspend fun updateLogoSize(size: Int) { + context.dataStore.edit { it[PREF_LOGO_SIZE] = size } + } } diff --git a/app/src/main/java/com/sameerasw/essentials/ui/composables/watermark/WatermarkScreen.kt b/app/src/main/java/com/sameerasw/essentials/ui/composables/watermark/WatermarkScreen.kt index e7a7cbae..497a8f42 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/composables/watermark/WatermarkScreen.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/composables/watermark/WatermarkScreen.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -45,6 +46,9 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.carousel.HorizontalMultiBrowseCarousel import com.sameerasw.essentials.R import com.sameerasw.essentials.domain.watermark.ColorMode import com.sameerasw.essentials.domain.watermark.WatermarkStyle @@ -602,7 +606,51 @@ fun WatermarkScreen( } } + + // Logo Section + Text( + text = stringResource(R.string.watermark_logo_section), + style = MaterialTheme.typography.titleMedium, + modifier = Modifier.padding(start = 16.dp, top = 8.dp, bottom = 8.dp), + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + + val logoResId by viewModel.logoResId.collectAsState() + val showLogo by viewModel.showLogo.collectAsState() + RoundedCardContainer( + modifier = Modifier.fillMaxWidth() + ) { + IconToggleItem( + iconRes = R.drawable.rounded_image_24, + title = stringResource(R.string.watermark_logo_show), + isChecked = showLogo, + onCheckedChange = { checked -> viewModel.setShowLogo(checked) } + ) + + if (showLogo) { + LogoCarouselPicker( + selectedResId = logoResId, + onLogoSelected = { resId -> viewModel.setLogoResId(resId) }, + modifier = Modifier + .fillMaxWidth() + ) + + var logoSizeValue by androidx.compose.runtime.remember(options.logoSize) { androidx.compose.runtime.mutableFloatStateOf(options.logoSize.toFloat()) } + ConfigSliderItem( + title = stringResource(R.string.watermark_logo_size), + value = logoSizeValue, + onValueChange = { + logoSizeValue = it + performSliderHaptic(view) + }, + onValueChangeFinished = { viewModel.setLogoSize(logoSizeValue.toInt()) }, + valueRange = 1f..100f, + increment = 1f, + valueFormatter = { "${it.toInt()}%" } + ) + } + } // Border Section Text( @@ -910,3 +958,65 @@ private fun ColorModeOption( } } } + +@OptIn(androidx.compose.material3.ExperimentalMaterial3Api::class) +@Composable +private fun LogoCarouselPicker( + selectedResId: Int?, + onLogoSelected: (Int) -> Unit, + modifier: Modifier = Modifier +) { + val logos = listOf( + R.drawable.apple, + R.drawable.cmf, + R.drawable.google, + R.drawable.moto, + R.drawable.nothing, + R.drawable.oppo, + R.drawable.samsung, + R.drawable.sony, + R.drawable.vivo, + R.drawable.xiaomi + ) + + val carouselState = androidx.compose.material3.carousel.rememberCarouselState { logos.size } + val view = androidx.compose.ui.platform.LocalView.current + + HorizontalMultiBrowseCarousel( + state = carouselState, + preferredItemWidth = 80.dp, + minSmallItemWidth = 5.dp, + maxSmallItemWidth = 200.dp, + itemSpacing = 2.dp, + modifier = modifier + .clip(RoundedCornerShape(4.dp)) + .background(MaterialTheme.colorScheme.surfaceBright) + .height(84.dp), + contentPadding = PaddingValues(4.dp) + ) { index -> + val resId = logos[index] + val isSelected = selectedResId == resId + val containerColor = if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surfaceContainerHigh + val contentColor = if (isSelected) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface + + Box( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 1.dp) + .clip(RoundedCornerShape(8.dp)) + .background(containerColor) + .clickable { + performUIHaptic(view) + onLogoSelected(resId) + }, + contentAlignment = Alignment.Center + ) { + Icon( + painter = androidx.compose.ui.res.painterResource(id = resId), + contentDescription = null, + modifier = Modifier.size(36.dp), + tint = contentColor + ) + } + } +} diff --git a/app/src/main/java/com/sameerasw/essentials/viewmodels/WatermarkViewModel.kt b/app/src/main/java/com/sameerasw/essentials/viewmodels/WatermarkViewModel.kt index fd3a82a1..866b03d7 100644 --- a/app/src/main/java/com/sameerasw/essentials/viewmodels/WatermarkViewModel.kt +++ b/app/src/main/java/com/sameerasw/essentials/viewmodels/WatermarkViewModel.kt @@ -9,6 +9,7 @@ import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import com.sameerasw.essentials.R import com.sameerasw.essentials.domain.watermark.ColorMode +import com.sameerasw.essentials.domain.watermark.ExifData import com.sameerasw.essentials.domain.watermark.MetadataProvider import com.sameerasw.essentials.domain.watermark.WatermarkEngine import com.sameerasw.essentials.domain.watermark.WatermarkOptions @@ -33,6 +34,7 @@ sealed class WatermarkUiState { class WatermarkViewModel( private val watermarkEngine: WatermarkEngine, private val watermarkRepository: WatermarkRepository, + private val metadataProvider: MetadataProvider, private val context: Context ) : ViewModel() { @@ -44,7 +46,7 @@ class WatermarkViewModel( val metadataProvider = MetadataProvider(appContext) val engine = WatermarkEngine(appContext, metadataProvider) val repository = WatermarkRepository(appContext) - return WatermarkViewModel(engine, repository, appContext) as T + return WatermarkViewModel(engine, repository, metadataProvider, appContext) as T } } } @@ -58,6 +60,13 @@ class WatermarkViewModel( private val _options = MutableStateFlow(WatermarkOptions()) val options: StateFlow = _options.asStateFlow() + // Transient logo state (not persisted, depends on image EXIF) + private val _logoResId = MutableStateFlow(null) + val logoResId: StateFlow = _logoResId.asStateFlow() + + private val _showLogo = MutableStateFlow(false) + val showLogo: StateFlow = _showLogo.asStateFlow() + private var previewSourceBitmap: android.graphics.Bitmap? = null private var currentUri: Uri? = null @@ -70,6 +79,25 @@ class WatermarkViewModel( } } + private fun detectOemLogo(exif: ExifData): Int? { + val make = exif.make?.lowercase() ?: "" + val model = exif.model?.lowercase() ?: "" + + return when { + make.contains("apple") || model.contains("iphone") -> R.drawable.apple + make.contains("google") || model.contains("pixel") -> R.drawable.google + make.contains("samsung") -> R.drawable.samsung + make.contains("xiaomi") || make.contains("redmi") || make.contains("poco") -> R.drawable.xiaomi + make.contains("oppo") -> R.drawable.oppo + make.contains("vivo") -> R.drawable.vivo + make.contains("sony") -> R.drawable.sony + make.contains("nothing") -> R.drawable.nothing + make.contains("cmf") -> R.drawable.cmf + make.contains("motorola") || make.contains("moto") -> R.drawable.moto + else -> null + } + } + fun loadPreview(uri: Uri) { currentUri = uri viewModelScope.launch(kotlinx.coroutines.Dispatchers.IO) { @@ -104,6 +132,13 @@ class WatermarkViewModel( if (bitmap != null) { previewSourceBitmap = bitmap + + // Always derive logo from EXIF on load + val exif = metadataProvider.extractExif(uri) + val detected = detectOemLogo(exif) + _logoResId.value = detected + _showLogo.value = detected != null + extractColorFromUri(uri) updatePreview() } @@ -155,7 +190,13 @@ class WatermarkViewModel( kotlinx.coroutines.delay(600) val workingBitmap = bitmap.copy(bitmap.config ?: android.graphics.Bitmap.Config.ARGB_8888, true) - val result = watermarkEngine.processBitmap(workingBitmap, uri, _options.value) + // Merge transient logo settings with base options + val currentOptions = _options.value.copy( + logoResId = _logoResId.value, + showLogo = _showLogo.value + ) + + val result = watermarkEngine.processBitmap(workingBitmap, uri, currentOptions) val timestamp = System.currentTimeMillis() val file = File(context.cacheDir, "preview_watermark_$timestamp.jpg") @@ -278,12 +319,47 @@ class WatermarkViewModel( } } + fun setLogoSettings(show: Boolean, resId: Int?, size: Int) { + _showLogo.value = show + _logoResId.value = resId + viewModelScope.launch { + watermarkRepository.updateLogoSize(size) + watermarkRepository.updateLogoShow(show) + updatePreview() + } + } + + fun setShowLogo(show: Boolean) { + _showLogo.value = show + viewModelScope.launch { + watermarkRepository.updateLogoShow(show) + updatePreview() + } + } + + fun setLogoResId(resId: Int?) { + _logoResId.value = resId + updatePreview() + } + + fun setLogoSize(size: Int) { + viewModelScope.launch { + watermarkRepository.updateLogoSize(size) + previewSourceBitmap?.let { updatePreview() } + } + } + fun saveImage(uri: Uri) { viewModelScope.launch { _uiState.value = WatermarkUiState.Processing try { + // Merge transient logo options + val finalOptions = _options.value.copy( + logoResId = _logoResId.value, + showLogo = _showLogo.value + ) // Process image to a temporary file first - val tempFile = watermarkEngine.processImage(uri, _options.value) + val tempFile = watermarkEngine.processImage(uri, finalOptions) // Save to MediaStore (Gallery) val values = android.content.ContentValues().apply { @@ -333,8 +409,13 @@ class WatermarkViewModel( viewModelScope.launch { _uiState.value = WatermarkUiState.Processing try { + // Merge transient logo options + val finalOptions = _options.value.copy( + logoResId = _logoResId.value, + showLogo = _showLogo.value + ) // Process image to a temporary file - val tempFile = watermarkEngine.processImage(uri, _options.value) + val tempFile = watermarkEngine.processImage(uri, finalOptions) val savedUri = saveToMediaStore(tempFile) if (savedUri != null) { _uiState.value = WatermarkUiState.Idle diff --git a/app/src/main/res/drawable/apple.xml b/app/src/main/res/drawable/apple.xml new file mode 100644 index 00000000..1c20b800 --- /dev/null +++ b/app/src/main/res/drawable/apple.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/cmf.xml b/app/src/main/res/drawable/cmf.xml new file mode 100644 index 00000000..464772b2 --- /dev/null +++ b/app/src/main/res/drawable/cmf.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/google.xml b/app/src/main/res/drawable/google.xml new file mode 100644 index 00000000..c0496e45 --- /dev/null +++ b/app/src/main/res/drawable/google.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/moto.xml b/app/src/main/res/drawable/moto.xml new file mode 100644 index 00000000..e5683641 --- /dev/null +++ b/app/src/main/res/drawable/moto.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/nothing.xml b/app/src/main/res/drawable/nothing.xml new file mode 100644 index 00000000..b4153c1b --- /dev/null +++ b/app/src/main/res/drawable/nothing.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/oppo.xml b/app/src/main/res/drawable/oppo.xml new file mode 100644 index 00000000..1875ee4f --- /dev/null +++ b/app/src/main/res/drawable/oppo.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/samsung.xml b/app/src/main/res/drawable/samsung.xml new file mode 100644 index 00000000..7fc874f3 --- /dev/null +++ b/app/src/main/res/drawable/samsung.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/sony.xml b/app/src/main/res/drawable/sony.xml new file mode 100644 index 00000000..cded39ab --- /dev/null +++ b/app/src/main/res/drawable/sony.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/vivo.xml b/app/src/main/res/drawable/vivo.xml new file mode 100644 index 00000000..8d6174fe --- /dev/null +++ b/app/src/main/res/drawable/vivo.xml @@ -0,0 +1,22 @@ + + + + diff --git a/app/src/main/res/drawable/xiaomi.xml b/app/src/main/res/drawable/xiaomi.xml new file mode 100644 index 00000000..95cd9fc4 --- /dev/null +++ b/app/src/main/res/drawable/xiaomi.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7a423e50..9fe02a56 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -359,6 +359,9 @@ Dark Accent Light Accent Dark + Logo + Show Logo + Logo Size Save Changes