Skip to content

Commit

Permalink
[feature|optimize] Support HEIF/HEIC format images; optimize code
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyD666 committed Nov 19, 2023
1 parent f6517d8 commit 4f12db0
Show file tree
Hide file tree
Showing 14 changed files with 102 additions and 25 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ android {
applicationId "com.skyd.rays"
minSdk 24
targetSdk 34
versionCode 44
versionName "1.6-rc03"
versionCode 45
versionName "1.6-rc04"
flavorDimensions = ["versionName"]

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/skyd/rays/ext/PreferenceExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import com.skyd.rays.model.preference.search.QueryPreference
import com.skyd.rays.model.preference.search.SearchResultReversePreference
import com.skyd.rays.model.preference.search.SearchResultSortPreference
import com.skyd.rays.model.preference.search.UseRegexSearchPreference
import com.skyd.rays.model.preference.share.CopyStickerToClipboardPreference
import com.skyd.rays.model.preference.share.CopyStickerToClipboardWhenSharingPreference
import com.skyd.rays.model.preference.share.StickerExtNamePreference
import com.skyd.rays.model.preference.share.UriStringSharePreference
import com.skyd.rays.model.preference.theme.CustomPrimaryColorPreference
Expand Down Expand Up @@ -64,7 +64,7 @@ fun Preferences.toSettings(): Settings {
// Share
uriStringShare = UriStringSharePreference.fromPreferences(this),
stickerExtName = StickerExtNamePreference.fromPreferences(this),
copyStickerToClipboard = CopyStickerToClipboardPreference.fromPreferences(this),
copyStickerToClipboardWhenSharing = CopyStickerToClipboardWhenSharingPreference.fromPreferences(this),
autoShareIgnoreStrategy = AutoShareIgnoreStrategyPreference.fromPreferences(this),

// Api
Expand Down
8 changes: 4 additions & 4 deletions app/src/main/java/com/skyd/rays/model/preference/Settings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import com.skyd.rays.model.preference.search.QueryPreference
import com.skyd.rays.model.preference.search.SearchResultReversePreference
import com.skyd.rays.model.preference.search.SearchResultSortPreference
import com.skyd.rays.model.preference.search.UseRegexSearchPreference
import com.skyd.rays.model.preference.share.CopyStickerToClipboardPreference
import com.skyd.rays.model.preference.share.CopyStickerToClipboardWhenSharingPreference
import com.skyd.rays.model.preference.share.StickerExtNamePreference
import com.skyd.rays.model.preference.share.UriStringSharePreference
import com.skyd.rays.model.preference.theme.CustomPrimaryColorPreference
Expand All @@ -26,7 +26,7 @@ import com.skyd.rays.model.preference.theme.ThemeNamePreference
import com.skyd.rays.ui.local.LocalApiGrant
import com.skyd.rays.ui.local.LocalAutoShareIgnoreStrategy
import com.skyd.rays.ui.local.LocalClassificationThreshold
import com.skyd.rays.ui.local.LocalCopyStickerToClipboard
import com.skyd.rays.ui.local.LocalCopyStickerToClipboardWhenSharing
import com.skyd.rays.ui.local.LocalCurrentStickerUuid
import com.skyd.rays.ui.local.LocalCustomPrimaryColor
import com.skyd.rays.ui.local.LocalDarkMode
Expand Down Expand Up @@ -79,7 +79,7 @@ data class Settings(
// Share
val uriStringShare: Boolean = UriStringSharePreference.default,
val stickerExtName: Boolean = StickerExtNamePreference.default,
val copyStickerToClipboard: Boolean = CopyStickerToClipboardPreference.default,
val copyStickerToClipboardWhenSharing: Boolean = CopyStickerToClipboardWhenSharingPreference.default,
val autoShareIgnoreStrategy: String = AutoShareIgnoreStrategyPreference.default,
// Api
val apiGrant: Boolean = ApiGrantPreference.default,
Expand Down Expand Up @@ -126,7 +126,7 @@ fun SettingsProvider(
// Share
LocalUriStringShare provides settings.uriStringShare,
LocalStickerExtName provides settings.stickerExtName,
LocalCopyStickerToClipboard provides settings.copyStickerToClipboard,
LocalCopyStickerToClipboardWhenSharing provides settings.copyStickerToClipboardWhenSharing,
LocalAutoShareIgnoreStrategy provides settings.autoShareIgnoreStrategy,
// Api
LocalApiGrant provides settings.apiGrant,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

object CopyStickerToClipboardPreference : BasePreference<Boolean> {
private const val COPY_STICKER_TO_CLIPBOARD = "copyStickerToClipboard"
object CopyStickerToClipboardWhenSharingPreference : BasePreference<Boolean> {
private const val COPY_STICKER_TO_CLIPBOARD_WHEN_SHARING = "copyStickerToClipboardWhenSharing"
override val default = true

val key = booleanPreferencesKey(COPY_STICKER_TO_CLIPBOARD)
val key = booleanPreferencesKey(COPY_STICKER_TO_CLIPBOARD_WHEN_SHARING)

fun put(context: Context, scope: CoroutineScope, value: Boolean) {
scope.launch(Dispatchers.IO) {
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/skyd/rays/ui/local/LocalValue.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import com.skyd.rays.model.preference.search.QueryPreference
import com.skyd.rays.model.preference.search.SearchResultReversePreference
import com.skyd.rays.model.preference.search.SearchResultSortPreference
import com.skyd.rays.model.preference.search.UseRegexSearchPreference
import com.skyd.rays.model.preference.share.CopyStickerToClipboardPreference
import com.skyd.rays.model.preference.share.CopyStickerToClipboardWhenSharingPreference
import com.skyd.rays.model.preference.share.StickerExtNamePreference
import com.skyd.rays.model.preference.share.UriStringSharePreference
import com.skyd.rays.model.preference.theme.CustomPrimaryColorPreference
Expand Down Expand Up @@ -73,7 +73,7 @@ val LocalHomeShareButtonAlignment =
// Share
val LocalUriStringShare = compositionLocalOf { UriStringSharePreference.default }
val LocalStickerExtName = compositionLocalOf { StickerExtNamePreference.default }
val LocalCopyStickerToClipboard = compositionLocalOf { CopyStickerToClipboardPreference.default }
val LocalCopyStickerToClipboardWhenSharing = compositionLocalOf { CopyStickerToClipboardWhenSharingPreference.default }
val LocalAutoShareIgnoreStrategy = compositionLocalOf { AutoShareIgnoreStrategyPreference.default }

// Api
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -48,6 +50,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
Expand Down Expand Up @@ -206,9 +209,8 @@ private fun DarkModeSheet(onDismissRequest: () -> Unit) {
.selectableGroup()
) {
DarkModePreference.values.forEach {
Card(
colors = CardDefaults.cardColors(containerColor = Color.Transparent)
) {
Card(colors = CardDefaults.cardColors(containerColor = Color.Transparent)) {
val interactionSource = remember { MutableInteractionSource() }
Row(
Modifier
.fillMaxWidth()
Expand All @@ -221,13 +223,16 @@ private fun DarkModeSheet(onDismissRequest: () -> Unit) {
value = it
)
},
interactionSource = interactionSource,
indication = LocalIndication.current,
role = Role.RadioButton
)
.padding(horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically
) {
RadioButton(
selected = (it == darkMode),
interactionSource = interactionSource,
onClick = null // null recommended for accessibility with screen readers
)
Text(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import com.skyd.rays.R
import com.skyd.rays.model.preference.share.CopyStickerToClipboardPreference
import com.skyd.rays.model.preference.share.CopyStickerToClipboardWhenSharingPreference
import com.skyd.rays.model.preference.share.StickerExtNamePreference
import com.skyd.rays.ui.component.BaseSettingsItem
import com.skyd.rays.ui.component.RaysTopBar
import com.skyd.rays.ui.component.RaysTopBarStyle
import com.skyd.rays.ui.component.SwitchSettingsItem
import com.skyd.rays.ui.local.LocalCopyStickerToClipboard
import com.skyd.rays.ui.local.LocalCopyStickerToClipboardWhenSharing
import com.skyd.rays.ui.local.LocalNavController
import com.skyd.rays.ui.local.LocalStickerExtName
import com.skyd.rays.ui.screen.settings.shareconfig.autoshare.AUTO_SHARE_SCREEN_ROUTE
Expand Down Expand Up @@ -74,12 +74,12 @@ fun ShareConfigScreen() {
item {
SwitchSettingsItem(
icon = Icons.Default.FileCopy,
checked = LocalCopyStickerToClipboard.current,
checked = LocalCopyStickerToClipboardWhenSharing.current,
text = stringResource(R.string.share_config_screen_copy_sticker_to_clipboard),
description = stringResource(R.string.share_config_screen_copy_sticker_to_clipboard_description),
onCheckedChange = {
scope.launch {
CopyStickerToClipboardPreference.put(
CopyStickerToClipboardWhenSharingPreference.put(
scope = scope,
context = context,
value = it
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/java/com/skyd/rays/util/StickerUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.skyd.rays.ext.dataStore
import com.skyd.rays.ext.getOrDefault
import com.skyd.rays.model.bean.StickerWithTags
import com.skyd.rays.model.db.AppDatabase
import com.skyd.rays.model.preference.share.CopyStickerToClipboardWhenSharingPreference
import com.skyd.rays.model.preference.share.StickerExtNamePreference
import com.skyd.rays.model.preference.share.UriStringSharePreference
import com.skyd.rays.ui.service.RaysAccessibilityService
Expand Down Expand Up @@ -107,7 +108,9 @@ fun Context.sendStickersByFiles(
)
}

copyStickerToClipboard(*contentUris.toTypedArray())
if (dataStore.getOrDefault(CopyStickerToClipboardWhenSharingPreference)) {
copyStickerToClipboard(*contentUris.toTypedArray())
}

with(AppDatabase.getInstance(this@sendStickersByFiles)) {
if (dataStore.getOrDefault(UriStringSharePreference)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ sealed class FormatStandard(
) {
companion object {
val formatStandards by lazy {
arrayOf(PngFormat, JpgFormat, GifFormat, BmpFormat, WebpFormat)
arrayOf(PngFormat, JpgFormat, GifFormat, BmpFormat, WebpFormat, HeifFormat, HeicFormat)
}
}

Expand Down Expand Up @@ -179,6 +179,63 @@ sealed class FormatStandard(
return true
}
}

/**
* https://github.com/nokiatech/heif/issues/74
* https://zh.wikipedia.org/wiki/%E9%AB%98%E6%95%88%E7%8E%87%E5%9B%BE%E5%83%8F%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F#
*/
data object HeifFormat : FormatStandard(
format = ImageFormat.HEIF,
requiredByteArraySize = 12,
) {
private val ftyp = byteArrayOf(0x66.toByte(), 0x74.toByte(), 0x79.toByte(), 0x70.toByte())
private val mif1 = byteArrayOf(0x6d.toByte(), 0x69.toByte(), 0x66.toByte(), 0x31.toByte())
private val msf1 = byteArrayOf(0x6d.toByte(), 0x73.toByte(), 0x66.toByte(), 0x31.toByte())
private val m = arrayOf(mif1, msf1)

override fun check(tested: ByteArray): Boolean {
for (i in 4..7) {
if (tested[i] != ftyp[i - 4]) return false
}

m.forEach {
if (baseCheck(it, byteArrayOf(tested[8], tested[9], tested[10], tested[11]))) {
return true
}
}
return false
}
}

data object HeicFormat : FormatStandard(
format = ImageFormat.HEIC,
requiredByteArraySize = 12,
) {
private val ftyp = byteArrayOf(0x66.toByte(), 0x74.toByte(), 0x79.toByte(), 0x70.toByte())
private val he = byteArrayOf(0x68.toByte(), 0x65.toByte())
private val icIxIsVcVx = arrayOf(
byteArrayOf(0x69.toByte(), 0x63.toByte()),
byteArrayOf(0x69.toByte(), 0x78.toByte()),
byteArrayOf(0x69.toByte(), 0x73.toByte()),
byteArrayOf(0x76.toByte(), 0x63.toByte()),
byteArrayOf(0x76.toByte(), 0x78.toByte()),
)

override fun check(tested: ByteArray): Boolean {
for (i in 4..7) {
if (tested[i] != ftyp[i - 4]) return false
}
for (i in 8..9) {
if (tested[i] != he[i - 8]) return false
}
icIxIsVcVx.forEach {
if (baseCheck(it, byteArrayOf(tested[10], tested[11]))) {
return true
}
}
return false
}
}
}

object FormatStandardUtil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ enum class ImageFormat {
GIF,
WEBP,
BMP,
HEIF,
HEIC,
UNDEFINED;

override fun toString(): String {
Expand All @@ -15,6 +17,8 @@ enum class ImageFormat {
GIF -> ".gif"
WEBP -> ".webp"
BMP -> ".bmp"
HEIF -> ".heif"
HEIC -> ".heic"
UNDEFINED -> ""
}
}
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -289,4 +289,8 @@
<string name="privacy_screen_disable_screenshot_description">禁止在应用内截图</string>
<string name="expand">展开</string>
<string name="collapse">收起</string>
<string name="share_sheet_action_copy">复制</string>
<string name="share_sheet_action_save">保存</string>
<string name="share_sheet_action_save_toast_success">已保存到“Pictures/Rays”</string>
<string name="share_sheet_action_save_toast_failed">保存失败</string>
</resources>
4 changes: 4 additions & 0 deletions app/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -289,4 +289,8 @@
<string name="data_screen_import_export_description">同步表情包數據</string>
<string name="image_scale_fill_width">填滿寬度</string>
<string name="classification_screen_name">表情包分類</string>
<string name="share_sheet_action_copy">複製</string>
<string name="share_sheet_action_save">儲存</string>
<string name="share_sheet_action_save_toast_success">已儲存到「Pictures/Rays」</string>
<string name="share_sheet_action_save_toast_failed">保存失敗</string>
</resources>
2 changes: 1 addition & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,6 @@
<string name="collapse">Collapse</string>
<string name="share_sheet_action_copy">Copy</string>
<string name="share_sheet_action_save">Save</string>
<string name="share_sheet_action_save_toast_success">Saved to Pictures/Rays</string>
<string name="share_sheet_action_save_toast_success">Saved to \"Pictures/Rays\"</string>
<string name="share_sheet_action_save_toast_failed">Save failed</string>
</resources>
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ buildscript {
}
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '8.1.3' apply false
id 'com.android.library' version '8.1.3' apply false
id 'com.android.application' version '8.1.4' apply false
id 'com.android.library' version '8.1.4' apply false
id 'org.jetbrains.kotlin.android' version '1.9.20' apply false
id 'com.google.dagger.hilt.android' version '2.48.1' apply false
id 'com.google.devtools.ksp' version '1.9.20-1.0.14' apply false
Expand Down

0 comments on commit 4f12db0

Please sign in to comment.