@@ -19,17 +19,22 @@ package com.esri.arcgismaps.kotlin.sampleviewer.model
19
19
import android.content.Context
20
20
import android.util.Log
21
21
import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample.Companion.loadActivityPath
22
+ import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample.Companion.loadCodeFiles
22
23
import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample.Companion.loadReadMe
23
24
import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample.Companion.loadScreenshot
24
25
import com.esri.arcgismaps.kotlin.sampleviewer.model.room.AppDatabase
25
26
import com.esri.arcgismaps.kotlin.sampleviewer.model.room.Converters
26
27
import kotlinx.coroutines.Dispatchers
28
+ import kotlinx.coroutines.flow.Flow
29
+ import kotlinx.coroutines.flow.MutableStateFlow
30
+ import kotlinx.coroutines.flow.asStateFlow
31
+ import kotlinx.coroutines.flow.map
27
32
import kotlinx.coroutines.withContext
28
33
import kotlinx.serialization.json.Json
29
34
import java.util.concurrent.atomic.AtomicBoolean
30
35
31
36
/* *
32
- * The single source of truth for app wide data. It reads the sample metadata to create as list of
37
+ * The single source of truth for app wide data. It reads the sample metadata to create a list of
33
38
* [Sample] objects and populates the database used for search.
34
39
* It also provides functions to get samples by category, name, or all samples.
35
40
*/
@@ -39,55 +44,59 @@ object DefaultSampleInfoRepository : SampleInfoRepository {
39
44
40
45
private val json = Json { ignoreUnknownKeys = true }
41
46
42
- private val sampleList = mutableListOf<Sample >()
47
+ private val _sampleData = MutableStateFlow <List <Sample >>(emptyList())
48
+ private val sampleData = _sampleData .asStateFlow()
43
49
44
50
/* *
45
- * Load the sample metadata from the metadata folder in the assets directory and updates sampleList
51
+ * Load the sample metadata from 'samples.json' in the assets directory and updates sampleList
46
52
* of [Sample] objects.
47
53
*/
48
54
suspend fun load (context : Context ) {
49
55
if (isInitialized.compareAndSet(false , true )) {
50
- // Iterate through the metadata folder for all metadata files
56
+ // List that will be populated with samples
57
+ val sampleList = mutableListOf<Sample >()
51
58
52
- context.assets.list(" samples" )?.forEach { samplePath ->
53
- // Get this metadata files as a string
54
- context.assets.open(" samples/$samplePath /README.metadata.json" ).use { inputStream ->
55
- val metadataJsonString = inputStream.bufferedReader().use { it.readText() }
56
- try {
57
- val metadata = json.decodeFromString<SampleMetadata >(metadataJsonString)
59
+ // Read the entire 'samples.json' from build/sampleAssets/samples/
60
+ val samplesJsonString = context.assets.open(" samples/samples.json" ).use { stream ->
61
+ stream.bufferedReader().use { it.readText() }
62
+ }
63
+
64
+ // Parse it into a map of: sampleFolderName -> mapOf( filename -> fileContent )
65
+ val allSamplesData = json.decodeFromString<Map <String , Map <String , String >>>(samplesJsonString)
66
+
67
+ // Build each Sample using the metadata from "README.metadata.json"
68
+ allSamplesData.forEach { (sampleFolderName, fileMap) ->
69
+ val metadataJsonString = fileMap[" README.metadata.json" ]
70
+ ? : throw Exception (" README.metadata.json not found in sample: $sampleFolderName " )
71
+ try {
72
+ val metadata = json.decodeFromString<SampleMetadata >(metadataJsonString)
58
73
59
- // Create and add a new sample metadata data class object to the list
60
- val sample = Sample (
61
- name = metadata.title,
62
- codeFiles = Sample .loadCodeFiles(
63
- context = context,
64
- sampleName = metadata.title
65
- ),
66
- url = " https://developers.arcgis.com/kotlin/sample-code/" +
67
- metadata.title.replace(" " , " -" ).lowercase(),
68
- readMe = loadReadMe(
69
- context = context,
70
- sampleName = samplePath
71
- ),
72
- screenshotURL = loadScreenshot(
73
- sampleName = metadata.title,
74
- imageArray = metadata.imagePaths
75
- ),
76
- mainActivity = loadActivityPath(
77
- codePaths = metadata.codePaths
78
- ),
79
- metadata = metadata,
80
- )
81
- // Add the new sample to the list
82
- sampleList.add(sample)
83
- } catch (e: Exception ) {
84
- Log .e(
85
- DefaultSampleInfoRepository ::class .simpleName,
86
- " Exception at $samplePath : " + e.printStackTrace()
87
- )
88
- }
74
+ // Create and add a new sample metadata data class object to the list
75
+ val sample = Sample (
76
+ name = metadata.title,
77
+ codeFiles = loadCodeFiles(fileMap),
78
+ url = " https://developers.arcgis.com/kotlin/sample-code/" +
79
+ metadata.title.replace(" " , " -" ).lowercase(),
80
+ readMe = loadReadMe(fileMap),
81
+ screenshotURL = loadScreenshot(
82
+ sampleName = metadata.title,
83
+ imageArray = metadata.imagePaths
84
+ ),
85
+ mainActivity = loadActivityPath(
86
+ codePaths = metadata.codePaths
87
+ ),
88
+ metadata = metadata
89
+ )
90
+ // Add the new sample to the list
91
+ sampleList.add(sample)
92
+ } catch (e: Exception ) {
93
+ Log .e(
94
+ DefaultSampleInfoRepository ::class .simpleName,
95
+ " Exception at $sampleFolderName : ${e.stackTraceToString()} "
96
+ )
89
97
}
90
98
}
99
+ _sampleData .value = sampleList
91
100
withContext(Dispatchers .IO ) {
92
101
// Populates the Room SQL database
93
102
populateDatabase(context)
@@ -99,22 +108,22 @@ object DefaultSampleInfoRepository : SampleInfoRepository {
99
108
* Populates the Room SQL database with all samples and sample info
100
109
*/
101
110
private suspend fun populateDatabase (context : Context ) {
102
- val sampleEntities = sampleList .map { Converters ().convertToEntity(sample = it) }
111
+ val sampleEntities = sampleData.value .map { Converters ().convertToEntity(sample = it) }
103
112
AppDatabase .getDatabase(context).clearAllTables()
104
113
AppDatabase .getDatabase(context).sampleDao().insertAll(samples = sampleEntities)
105
114
}
106
115
107
116
/* *
108
117
* Get a sample by its name. Either the formal name or title.
109
118
*/
110
- override fun getSampleByName (sampleName : String ): Sample {
111
- return sampleList.first { it.metadata.formalName == sampleName || it .metadata.title == sampleName }
119
+ override fun getSampleByName (sampleName : String ): Flow < Sample > {
120
+ return sampleData.map { it.first { sample -> sample. metadata.formalName == sampleName || sample .metadata.title == sampleName } }
112
121
}
113
122
114
123
/* *
115
124
* Get a list of samples for the given [SampleCategory].
116
125
*/
117
- override fun getSamplesInCategory (sampleCategory : SampleCategory ): List <Sample > {
118
- return sampleList.filter { it.metadata.sampleCategory == sampleCategory }
126
+ override fun getSamplesInCategory (sampleCategory : SampleCategory ): Flow < List <Sample > > {
127
+ return sampleData.map { it.filter { sample -> sample. metadata.sampleCategory == sampleCategory } }
119
128
}
120
129
}
0 commit comments