Wear CWF put default watchfaces within assets folder
This commit is contained in:
parent
c73829faa8
commit
52bf463b6a
11 changed files with 40 additions and 19 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
||||||
|
|
BIN
plugins/configuration/src/main/assets/Default Watchface.zip
Normal file
BIN
plugins/configuration/src/main/assets/Default Watchface.zip
Normal file
Binary file not shown.
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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])
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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] ?: "")
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue