diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/rx/weardata/CustomWatchfaceFormat.kt b/app-wear-shared/shared/src/main/java/info/nightscout/rx/weardata/CustomWatchfaceFormat.kt index 010c9ca095..15ec1802d5 100644 --- a/app-wear-shared/shared/src/main/java/info/nightscout/rx/weardata/CustomWatchfaceFormat.kt +++ b/app-wear-shared/shared/src/main/java/info/nightscout/rx/weardata/CustomWatchfaceFormat.kt @@ -265,13 +265,12 @@ class ZipWatchfaceFormat { const val CWF_EXTENTION = ".zip" 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 metadata: CwfMetadataMap = mutableMapOf() val resDatas: CwfResDataMap = mutableMapOf() try { - val zipInputStream = ZipInputStream(cwfFile.inputStream()) var zipEntry: ZipEntry? = zipInputStream.nextEntry while (zipEntry != null) { val entryName = zipEntry.name @@ -289,7 +288,7 @@ class ZipWatchfaceFormat { val jsonString = byteArrayOutputStream.toByteArray().toString(Charsets.UTF_8) json = JSONObject(jsonString) metadata = loadMetadata(json) - metadata[CwfMetadataKey.CWF_FILENAME] = cwfFile.name + metadata[CwfMetadataKey.CWF_FILENAME] = zipName.substringBeforeLast(".") metadata[CwfMetadataKey.CWF_AUTHORIZATION] = authorization.toString() } else { val cwfResFileMap = ResFileMap.fromFileName(entryName) diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/rx/weardata/EventData.kt b/app-wear-shared/shared/src/main/java/info/nightscout/rx/weardata/EventData.kt index 81a292aa12..b7b09742e9 100644 --- a/app-wear-shared/shared/src/main/java/info/nightscout/rx/weardata/EventData.kt +++ b/app-wear-shared/shared/src/main/java/info/nightscout/rx/weardata/EventData.kt @@ -159,7 +159,8 @@ sealed class EventData : Event() { @Serializable data class ActionGetCustomWatchface( val customWatchface: ActionSetCustomWatchface, - val exportFile: Boolean = false + val exportFile: Boolean = false, + val withDate: Boolean = true ) : EventData() @Serializable diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/ImportExportPrefs.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/ImportExportPrefs.kt index 129ca50447..c3d7ffdbca 100644 --- a/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/ImportExportPrefs.kt +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/ImportExportPrefs.kt @@ -11,7 +11,7 @@ interface ImportExportPrefs { fun importSharedPreferences(fragment: Fragment) fun importCustomWatchface(activity: FragmentActivity) fun importCustomWatchface(fragment: Fragment) - fun exportCustomWatchface(customWatchface: CwfData) + fun exportCustomWatchface(customWatchface: CwfData, withDate: Boolean = true) fun prefsFileExists(): Boolean fun verifyStoragePermissions(fragment: Fragment, onGranted: Runnable) fun exportSharedPreferences(f: Fragment) diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefFileListProvider.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefFileListProvider.kt index 5b97972d99..e8f78dfb6f 100644 --- a/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefFileListProvider.kt +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/maintenance/PrefFileListProvider.kt @@ -11,7 +11,7 @@ interface PrefFileListProvider { fun ensureExtraDirExists(): File fun newExportFile(): File fun newExportCsvFile(): File - fun newCwfFile(filename: String): File + fun newCwfFile(filename: String, withDate: Boolean = true): File fun listPreferenceFiles(loadMetadata: Boolean = false): MutableList fun listCustomWatchfaceFiles(): MutableList fun checkMetadata(metadata: Map): Map diff --git a/plugins/configuration/src/main/assets/Default Watchface.zip b/plugins/configuration/src/main/assets/Default Watchface.zip new file mode 100644 index 0000000000..a75db9f747 Binary files /dev/null and b/plugins/configuration/src/main/assets/Default Watchface.zip differ diff --git a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/ImportExportPrefsImpl.kt b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/ImportExportPrefsImpl.kt index 40b289404f..e3aae49ae9 100644 --- a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/ImportExportPrefsImpl.kt +++ b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/ImportExportPrefsImpl.kt @@ -315,9 +315,9 @@ class ImportExportPrefsImpl @Inject constructor( } } - override fun exportCustomWatchface(customWatchface: CwfData) { + override fun exportCustomWatchface(customWatchface: CwfData, withDate: Boolean) { 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) } diff --git a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/PrefFileListProviderImpl.kt b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/PrefFileListProviderImpl.kt index 93e23dee1b..ebef240c4b 100644 --- a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/PrefFileListProviderImpl.kt +++ b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/PrefFileListProviderImpl.kt @@ -17,7 +17,9 @@ import info.nightscout.interfaces.maintenance.PrefsMetadataKey import info.nightscout.interfaces.maintenance.PrefsStatus import info.nightscout.interfaces.storage.Storage import info.nightscout.interfaces.versionChecker.VersionCheckerUtils +import info.nightscout.rx.bus.RxBus import info.nightscout.rx.weardata.CwfData +import info.nightscout.rx.weardata.EventData import info.nightscout.rx.weardata.ZipWatchfaceFormat import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.sharedPreferences.SP @@ -27,6 +29,7 @@ import org.joda.time.Hours import org.joda.time.LocalDateTime import org.joda.time.format.DateTimeFormat import java.io.File +import java.util.zip.ZipInputStream import javax.inject.Inject import kotlin.math.abs @@ -40,7 +43,8 @@ class PrefFileListProviderImpl @Inject constructor( private val storage: Storage, private val versionCheckerUtils: VersionCheckerUtils, private val sp: SP, - context: Context + private val context: Context, + private val rxBus: RxBus ) : PrefFileListProvider { private val path = File(Environment.getExternalStorageDirectory().toString()) @@ -96,13 +100,28 @@ class PrefFileListProviderImpl @Inject constructor( override fun listCustomWatchfaceFiles(): MutableList { val customWatchfaceFiles = mutableListOf() 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 -> - // Here loadCustomWatchface will unzip, check and load CustomWatchface - ZipWatchfaceFormat.loadCustomWatchface(file, customAwtchfaceAuthorization)?.also { customWatchface -> + ZipWatchfaceFormat.loadCustomWatchface(ZipInputStream(file.inputStream()), file.name, customAwtchfaceAuthorization)?.also { 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 } @@ -148,9 +167,9 @@ class PrefFileListProviderImpl @Inject constructor( 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")) - 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 diff --git a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/activities/CustomWatchfaceImportListActivity.kt b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/activities/CustomWatchfaceImportListActivity.kt index d8bc43c362..6a4bbc8b2a 100644 --- a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/activities/CustomWatchfaceImportListActivity.kt +++ b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/activities/CustomWatchfaceImportListActivity.kt @@ -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.CwfMetadataMap import info.nightscout.rx.weardata.EventData +import info.nightscout.rx.weardata.ZipWatchfaceFormat import info.nightscout.shared.extensions.toVisibility import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.sharedPreferences.SP @@ -91,7 +92,8 @@ class CustomWatchfaceImportListActivity: TranslatedDaggerAppCompatActivity() { val metadata = customWatchfaceFile.metadata val drawable = customWatchfaceFile.resDatas[ResFileMap.CUSTOM_WATCHFACE.fileName]?.toDrawable(resources) 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 customWatchface.setImageDrawable(drawable) customName.text = rh.gs(CWF_NAME.label, metadata[CWF_NAME]) diff --git a/plugins/main/src/main/java/info/nightscout/plugins/general/wear/WearFragment.kt b/plugins/main/src/main/java/info/nightscout/plugins/general/wear/WearFragment.kt index e9aa8f6987..354d3026e2 100644 --- a/plugins/main/src/main/java/info/nightscout/plugins/general/wear/WearFragment.kt +++ b/plugins/main/src/main/java/info/nightscout/plugins/general/wear/WearFragment.kt @@ -91,7 +91,6 @@ class WearFragment : DaggerFragment() { }, fabricPrivacy::logException) if (wearPlugin.savedCustomWatchface == null) rxBus.send(EventMobileToWear(EventData.ActionrequestCustomWatchface(false))) - //EventMobileDataToWear updateGui() } diff --git a/plugins/main/src/main/java/info/nightscout/plugins/general/wear/activities/CwfInfosActivity.kt b/plugins/main/src/main/java/info/nightscout/plugins/general/wear/activities/CwfInfosActivity.kt index ce414654ee..8b60d77a12 100644 --- a/plugins/main/src/main/java/info/nightscout/plugins/general/wear/activities/CwfInfosActivity.kt +++ b/plugins/main/src/main/java/info/nightscout/plugins/general/wear/activities/CwfInfosActivity.kt @@ -26,6 +26,7 @@ import info.nightscout.rx.weardata.CwfMetadataMap import info.nightscout.rx.weardata.JsonKeyValues import info.nightscout.rx.weardata.JsonKeys import info.nightscout.rx.weardata.ViewKeys +import info.nightscout.rx.weardata.ZipWatchfaceFormat import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.sharedPreferences.SP import io.reactivex.rxjava3.disposables.CompositeDisposable @@ -92,7 +93,8 @@ class CwfInfosActivity : TranslatedDaggerAppCompatActivity() { metadata[CwfMetadataKey.CWF_AUTHOR_VERSION]?.let { 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.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] ?: "") diff --git a/plugins/main/src/main/java/info/nightscout/plugins/general/wear/wearintegration/DataHandlerMobile.kt b/plugins/main/src/main/java/info/nightscout/plugins/general/wear/wearintegration/DataHandlerMobile.kt index c461fbab26..2f9e46f04b 100644 --- a/plugins/main/src/main/java/info/nightscout/plugins/general/wear/wearintegration/DataHandlerMobile.kt +++ b/plugins/main/src/main/java/info/nightscout/plugins/general/wear/wearintegration/DataHandlerMobile.kt @@ -1266,8 +1266,7 @@ class DataHandlerMobile @Inject constructor( aapsLogger.debug(LTag.WEAR, "Custom Watchface received from ${command.sourceNodeId}: ${customWatchface.customWatchfaceData.json}") rxBus.send(EventWearUpdateGui(customWatchface.customWatchfaceData, command.exportFile)) if (command.exportFile) - importExportPrefs.exportCustomWatchface(customWatchface.customWatchfaceData) - + importExportPrefs.exportCustomWatchface(customWatchface.customWatchfaceData, command.withDate) } }