Wear CWF put default watchfaces within assets folder

This commit is contained in:
Philoul 2023-09-11 22:37:34 +02:00
parent c73829faa8
commit 52bf463b6a
11 changed files with 40 additions and 19 deletions

View file

@ -265,13 +265,12 @@ class ZipWatchfaceFormat {
const val CWF_EXTENTION = ".zip" const val CWF_EXTENTION = ".zip"
const val CWF_JSON_FILE = "CustomWatchface.json" const val CWF_JSON_FILE = "CustomWatchface.json"
fun loadCustomWatchface(cwfFile: File, authorization: Boolean): CwfData? { fun loadCustomWatchface(zipInputStream: ZipInputStream, zipName: String, authorization: Boolean): CwfData? {
var json = JSONObject() var json = JSONObject()
var metadata: CwfMetadataMap = mutableMapOf() var metadata: CwfMetadataMap = mutableMapOf()
val resDatas: CwfResDataMap = mutableMapOf() val resDatas: CwfResDataMap = mutableMapOf()
try { try {
val zipInputStream = ZipInputStream(cwfFile.inputStream())
var zipEntry: ZipEntry? = zipInputStream.nextEntry var zipEntry: ZipEntry? = zipInputStream.nextEntry
while (zipEntry != null) { while (zipEntry != null) {
val entryName = zipEntry.name val entryName = zipEntry.name
@ -289,7 +288,7 @@ class ZipWatchfaceFormat {
val jsonString = byteArrayOutputStream.toByteArray().toString(Charsets.UTF_8) val jsonString = byteArrayOutputStream.toByteArray().toString(Charsets.UTF_8)
json = JSONObject(jsonString) json = JSONObject(jsonString)
metadata = loadMetadata(json) metadata = loadMetadata(json)
metadata[CwfMetadataKey.CWF_FILENAME] = cwfFile.name metadata[CwfMetadataKey.CWF_FILENAME] = zipName.substringBeforeLast(".")
metadata[CwfMetadataKey.CWF_AUTHORIZATION] = authorization.toString() metadata[CwfMetadataKey.CWF_AUTHORIZATION] = authorization.toString()
} else { } else {
val cwfResFileMap = ResFileMap.fromFileName(entryName) val cwfResFileMap = ResFileMap.fromFileName(entryName)

View file

@ -159,7 +159,8 @@ sealed class EventData : Event() {
@Serializable @Serializable
data class ActionGetCustomWatchface( data class ActionGetCustomWatchface(
val customWatchface: ActionSetCustomWatchface, val customWatchface: ActionSetCustomWatchface,
val exportFile: Boolean = false val exportFile: Boolean = false,
val withDate: Boolean = true
) : EventData() ) : EventData()
@Serializable @Serializable

View file

@ -11,7 +11,7 @@ interface ImportExportPrefs {
fun importSharedPreferences(fragment: Fragment) fun importSharedPreferences(fragment: Fragment)
fun importCustomWatchface(activity: FragmentActivity) fun importCustomWatchface(activity: FragmentActivity)
fun importCustomWatchface(fragment: Fragment) fun importCustomWatchface(fragment: Fragment)
fun exportCustomWatchface(customWatchface: CwfData) fun exportCustomWatchface(customWatchface: CwfData, withDate: Boolean = true)
fun prefsFileExists(): Boolean fun prefsFileExists(): Boolean
fun verifyStoragePermissions(fragment: Fragment, onGranted: Runnable) fun verifyStoragePermissions(fragment: Fragment, onGranted: Runnable)
fun exportSharedPreferences(f: Fragment) fun exportSharedPreferences(f: Fragment)

View file

@ -11,7 +11,7 @@ interface PrefFileListProvider {
fun ensureExtraDirExists(): File fun ensureExtraDirExists(): File
fun newExportFile(): File fun newExportFile(): File
fun newExportCsvFile(): File fun newExportCsvFile(): File
fun newCwfFile(filename: String): File fun newCwfFile(filename: String, withDate: Boolean = true): File
fun listPreferenceFiles(loadMetadata: Boolean = false): MutableList<PrefsFile> fun listPreferenceFiles(loadMetadata: Boolean = false): MutableList<PrefsFile>
fun listCustomWatchfaceFiles(): MutableList<CwfData> fun listCustomWatchfaceFiles(): MutableList<CwfData>
fun checkMetadata(metadata: Map<PrefsMetadataKey, PrefMetadata>): Map<PrefsMetadataKey, PrefMetadata> fun checkMetadata(metadata: Map<PrefsMetadataKey, PrefMetadata>): Map<PrefsMetadataKey, PrefMetadata>

View file

@ -315,9 +315,9 @@ class ImportExportPrefsImpl @Inject constructor(
} }
} }
override fun exportCustomWatchface(customWatchface: CwfData) { override fun exportCustomWatchface(customWatchface: CwfData, withDate: Boolean) {
prefFileList.ensureExportDirExists() prefFileList.ensureExportDirExists()
val newFile = prefFileList.newCwfFile(customWatchface.metadata[CwfMetadataKey.CWF_FILENAME] ?:"") val newFile = prefFileList.newCwfFile(customWatchface.metadata[CwfMetadataKey.CWF_FILENAME] ?:"", withDate)
ZipWatchfaceFormat.saveCustomWatchface(newFile, customWatchface) ZipWatchfaceFormat.saveCustomWatchface(newFile, customWatchface)
} }

View file

@ -17,7 +17,9 @@ import info.nightscout.interfaces.maintenance.PrefsMetadataKey
import info.nightscout.interfaces.maintenance.PrefsStatus import info.nightscout.interfaces.maintenance.PrefsStatus
import info.nightscout.interfaces.storage.Storage import info.nightscout.interfaces.storage.Storage
import info.nightscout.interfaces.versionChecker.VersionCheckerUtils import info.nightscout.interfaces.versionChecker.VersionCheckerUtils
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.weardata.CwfData import info.nightscout.rx.weardata.CwfData
import info.nightscout.rx.weardata.EventData
import info.nightscout.rx.weardata.ZipWatchfaceFormat import info.nightscout.rx.weardata.ZipWatchfaceFormat
import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
@ -27,6 +29,7 @@ import org.joda.time.Hours
import org.joda.time.LocalDateTime import org.joda.time.LocalDateTime
import org.joda.time.format.DateTimeFormat import org.joda.time.format.DateTimeFormat
import java.io.File import java.io.File
import java.util.zip.ZipInputStream
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.abs import kotlin.math.abs
@ -40,7 +43,8 @@ class PrefFileListProviderImpl @Inject constructor(
private val storage: Storage, private val storage: Storage,
private val versionCheckerUtils: VersionCheckerUtils, private val versionCheckerUtils: VersionCheckerUtils,
private val sp: SP, private val sp: SP,
context: Context private val context: Context,
private val rxBus: RxBus
) : PrefFileListProvider { ) : PrefFileListProvider {
private val path = File(Environment.getExternalStorageDirectory().toString()) private val path = File(Environment.getExternalStorageDirectory().toString())
@ -96,13 +100,28 @@ class PrefFileListProviderImpl @Inject constructor(
override fun listCustomWatchfaceFiles(): MutableList<CwfData> { override fun listCustomWatchfaceFiles(): MutableList<CwfData> {
val customWatchfaceFiles = mutableListOf<CwfData>() val customWatchfaceFiles = mutableListOf<CwfData>()
val customAwtchfaceAuthorization = sp.getBoolean(info.nightscout.core.utils.R.string.key_wear_custom_watchface_autorization, false) val customAwtchfaceAuthorization = sp.getBoolean(info.nightscout.core.utils.R.string.key_wear_custom_watchface_autorization, false)
// searching dedicated dir, only for new CWF format
exportsPath.walk().filter { it.isFile && it.name.endsWith(ZipWatchfaceFormat.CWF_EXTENTION) }.forEach { file -> exportsPath.walk().filter { it.isFile && it.name.endsWith(ZipWatchfaceFormat.CWF_EXTENTION) }.forEach { file ->
// Here loadCustomWatchface will unzip, check and load CustomWatchface ZipWatchfaceFormat.loadCustomWatchface(ZipInputStream(file.inputStream()), file.name, customAwtchfaceAuthorization)?.also { customWatchface ->
ZipWatchfaceFormat.loadCustomWatchface(file, customAwtchfaceAuthorization)?.also { customWatchface ->
customWatchfaceFiles.add(customWatchface) customWatchfaceFiles.add(customWatchface)
} }
} }
if (customWatchfaceFiles.isEmpty()) {
try {
val assetFiles = context.assets.list("") ?: arrayOf()
for (assetFileName in assetFiles) {
if (assetFileName.endsWith(ZipWatchfaceFormat.CWF_EXTENTION)) {
val assetInputStream = context.assets.open(assetFileName)
ZipWatchfaceFormat.loadCustomWatchface(ZipInputStream(assetInputStream), assetFileName, customAwtchfaceAuthorization)?.also { customWatchface ->
customWatchfaceFiles.add(customWatchface)
rxBus.send(EventData.ActionGetCustomWatchface(EventData.ActionSetCustomWatchface(customWatchface), exportFile = true, withDate = false))
}
assetInputStream.close()
}
}
} catch (e: Exception) {
// Handle any exceptions that may occur while accessing assets
}
}
return customWatchfaceFiles return customWatchfaceFiles
} }
@ -148,9 +167,9 @@ class PrefFileListProviderImpl @Inject constructor(
return File(exportsPath, timeLocal + "_UserEntry.csv") return File(exportsPath, timeLocal + "_UserEntry.csv")
} }
override fun newCwfFile(filename: String): File { override fun newCwfFile(filename: String, withDate: Boolean): File {
val timeLocal = LocalDateTime.now().toString(DateTimeFormat.forPattern("yyyy-MM-dd'_'HHmmss")) val timeLocal = LocalDateTime.now().toString(DateTimeFormat.forPattern("yyyy-MM-dd'_'HHmmss"))
return File(exportsPath, "${filename}_$timeLocal${ZipWatchfaceFormat.CWF_EXTENTION}") return if (withDate) File(exportsPath, "${filename}_$timeLocal${ZipWatchfaceFormat.CWF_EXTENTION}") else File(exportsPath,"${filename}${ZipWatchfaceFormat.CWF_EXTENTION}")
} }
// check metadata for known issues, change their status and add info with explanations // check metadata for known issues, change their status and add info with explanations

View file

@ -27,6 +27,7 @@ import info.nightscout.rx.weardata.CwfMetadataKey.CWF_NAME
import info.nightscout.rx.weardata.CwfMetadataKey.CWF_VERSION import info.nightscout.rx.weardata.CwfMetadataKey.CWF_VERSION
import info.nightscout.rx.weardata.CwfMetadataMap import info.nightscout.rx.weardata.CwfMetadataMap
import info.nightscout.rx.weardata.EventData import info.nightscout.rx.weardata.EventData
import info.nightscout.rx.weardata.ZipWatchfaceFormat
import info.nightscout.shared.extensions.toVisibility import info.nightscout.shared.extensions.toVisibility
import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
@ -91,7 +92,8 @@ class CustomWatchfaceImportListActivity: TranslatedDaggerAppCompatActivity() {
val metadata = customWatchfaceFile.metadata val metadata = customWatchfaceFile.metadata
val drawable = customWatchfaceFile.resDatas[ResFileMap.CUSTOM_WATCHFACE.fileName]?.toDrawable(resources) val drawable = customWatchfaceFile.resDatas[ResFileMap.CUSTOM_WATCHFACE.fileName]?.toDrawable(resources)
with(holder.customWatchfaceImportListItemBinding) { with(holder.customWatchfaceImportListItemBinding) {
filelistName.text = rh.gs(info.nightscout.shared.R.string.metadata_wear_import_filename, metadata[CWF_FILENAME]) val fileName = metadata[CWF_FILENAME]?.let { "$it${ZipWatchfaceFormat.CWF_EXTENTION}"} ?:""
filelistName.text = rh.gs(info.nightscout.shared.R.string.metadata_wear_import_filename, fileName)
filelistName.tag = customWatchfaceFile filelistName.tag = customWatchfaceFile
customWatchface.setImageDrawable(drawable) customWatchface.setImageDrawable(drawable)
customName.text = rh.gs(CWF_NAME.label, metadata[CWF_NAME]) customName.text = rh.gs(CWF_NAME.label, metadata[CWF_NAME])

View file

@ -91,7 +91,6 @@ class WearFragment : DaggerFragment() {
}, fabricPrivacy::logException) }, fabricPrivacy::logException)
if (wearPlugin.savedCustomWatchface == null) if (wearPlugin.savedCustomWatchface == null)
rxBus.send(EventMobileToWear(EventData.ActionrequestCustomWatchface(false))) rxBus.send(EventMobileToWear(EventData.ActionrequestCustomWatchface(false)))
//EventMobileDataToWear
updateGui() updateGui()
} }

View file

@ -26,6 +26,7 @@ import info.nightscout.rx.weardata.CwfMetadataMap
import info.nightscout.rx.weardata.JsonKeyValues import info.nightscout.rx.weardata.JsonKeyValues
import info.nightscout.rx.weardata.JsonKeys import info.nightscout.rx.weardata.JsonKeys
import info.nightscout.rx.weardata.ViewKeys import info.nightscout.rx.weardata.ViewKeys
import info.nightscout.rx.weardata.ZipWatchfaceFormat
import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
@ -92,7 +93,8 @@ class CwfInfosActivity : TranslatedDaggerAppCompatActivity() {
metadata[CwfMetadataKey.CWF_AUTHOR_VERSION]?.let { authorVersion -> metadata[CwfMetadataKey.CWF_AUTHOR_VERSION]?.let { authorVersion ->
title = "${metadata[CwfMetadataKey.CWF_NAME]} ($authorVersion)" title = "${metadata[CwfMetadataKey.CWF_NAME]} ($authorVersion)"
} }
binding.filelistName.text = rh.gs(CwfMetadataKey.CWF_FILENAME.label, metadata[CwfMetadataKey.CWF_FILENAME] ?: "") val fileName = metadata[CwfMetadataKey.CWF_FILENAME]?.let { "$it${ZipWatchfaceFormat.CWF_EXTENTION}"} ?:""
binding.filelistName.text = rh.gs(CwfMetadataKey.CWF_FILENAME.label, fileName)
binding.author.text = rh.gs(CwfMetadataKey.CWF_AUTHOR.label, metadata[CwfMetadataKey.CWF_AUTHOR] ?: "") binding.author.text = rh.gs(CwfMetadataKey.CWF_AUTHOR.label, metadata[CwfMetadataKey.CWF_AUTHOR] ?: "")
binding.createdAt.text = rh.gs(CwfMetadataKey.CWF_CREATED_AT.label, metadata[CwfMetadataKey.CWF_CREATED_AT] ?: "") binding.createdAt.text = rh.gs(CwfMetadataKey.CWF_CREATED_AT.label, metadata[CwfMetadataKey.CWF_CREATED_AT] ?: "")
binding.cwfVersion.text = rh.gs(CwfMetadataKey.CWF_VERSION.label, metadata[CwfMetadataKey.CWF_VERSION] ?: "") binding.cwfVersion.text = rh.gs(CwfMetadataKey.CWF_VERSION.label, metadata[CwfMetadataKey.CWF_VERSION] ?: "")

View file

@ -1266,8 +1266,7 @@ class DataHandlerMobile @Inject constructor(
aapsLogger.debug(LTag.WEAR, "Custom Watchface received from ${command.sourceNodeId}: ${customWatchface.customWatchfaceData.json}") aapsLogger.debug(LTag.WEAR, "Custom Watchface received from ${command.sourceNodeId}: ${customWatchface.customWatchfaceData.json}")
rxBus.send(EventWearUpdateGui(customWatchface.customWatchfaceData, command.exportFile)) rxBus.send(EventWearUpdateGui(customWatchface.customWatchfaceData, command.exportFile))
if (command.exportFile) if (command.exportFile)
importExportPrefs.exportCustomWatchface(customWatchface.customWatchfaceData) importExportPrefs.exportCustomWatchface(customWatchface.customWatchfaceData, command.withDate)
} }
} }