pakstr 0.3.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/android-template/app/build.gradle.kts +71 -4
  2. package/android-template/app/proguard-rules.pro +21 -18
  3. package/android-template/app/src/main/AndroidManifest.xml +17 -0
  4. package/android-template/app/src/main/java/com/pakstr/app/ApplicationClass.kt +14 -0
  5. package/android-template/app/src/main/java/com/pakstr/app/LocalServer.kt +80 -21
  6. package/android-template/app/src/main/java/com/pakstr/app/MainActivity.kt +61 -11
  7. package/android-template/app/src/main/java/com/pakstr/app/RuntimeConfig.kt +81 -37
  8. package/android-template/app/src/main/java/com/pakstr/app/ShellRuntime.kt +100 -9
  9. package/android-template/app/src/main/java/com/pakstr/app/WebViewController.kt +280 -20
  10. package/android-template/app/src/main/java/com/pakstr/app/crypto/Bip340Verifier.kt +0 -5
  11. package/android-template/app/src/main/java/com/pakstr/app/debug/AppDebugLogger.kt +348 -3
  12. package/android-template/app/src/main/java/com/pakstr/app/debug/CrashHandler.kt +32 -0
  13. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugConfig.kt +11 -0
  14. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugConfigLoader.kt +36 -0
  15. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugConfigProvider.kt +29 -0
  16. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugLogStorage.kt +139 -0
  17. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugPreferences.kt +85 -0
  18. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugReportExporter.kt +149 -0
  19. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugReportShare.kt +52 -0
  20. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugRuntimeOverride.kt +55 -0
  21. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugSession.kt +16 -0
  22. package/android-template/app/src/main/java/com/pakstr/app/debug/DeveloperToolsManager.kt +63 -0
  23. package/android-template/app/src/main/java/com/pakstr/app/debug/WebViewDebugManager.kt +30 -0
  24. package/android-template/app/src/main/java/com/pakstr/app/debug/logging/PakstrLog.kt +16 -0
  25. package/android-template/app/src/main/java/com/pakstr/app/debug/logging/PakstrLogger.kt +154 -0
  26. package/android-template/app/src/main/java/com/pakstr/app/signer/AmberSigner.kt +1 -10
  27. package/android-template/app/src/main/java/com/pakstr/app/signer/NostrBridge.kt +163 -11
  28. package/android-template/app/src/main/java/com/pakstr/app/signer/SignerManager.kt +71 -0
  29. package/android-template/app/src/main/res/xml/file_paths.xml +9 -0
  30. package/android-template/gradle/libs.versions.toml +1 -0
  31. package/android-template/gradle.properties +2 -1
  32. package/dist/runners/LocalGradleRunner.js +12 -2
  33. package/dist/runtime/runtimeConfig.js +6 -1
  34. package/package.json +1 -1
@@ -1,21 +1,366 @@
1
1
  package com.pakstr.app.debug
2
2
 
3
+ import android.content.Context
3
4
  import android.util.Log
4
5
  import com.pakstr.app.BuildConfig
6
+ import com.pakstr.app.RuntimeConfig
7
+ import java.text.SimpleDateFormat
8
+ import java.util.Collections
9
+ import java.util.Date
10
+ import java.util.Locale
5
11
 
6
12
  object AppDebugLogger {
7
13
 
14
+ private const val TAG = "PakstrDebug"
15
+
16
+ private const val MAX_LOGS = 500
17
+
18
+ private val logs =
19
+
20
+ Collections.synchronizedList(
21
+
22
+ mutableListOf<String>()
23
+
24
+ )
25
+
8
26
  fun log(
27
+ context: Context,
9
28
  tag: String,
10
29
  message: String
11
30
  ) {
12
31
 
13
- if (BuildConfig.DEBUG) {
32
+ if (!isDebugEnabled(context)) {
33
+ return
34
+ }
14
35
 
15
- Log.d(
16
- tag,
36
+ save(
37
+ context,
38
+ "DEBUG",
39
+ tag,
40
+ message
41
+ )
42
+
43
+ Log.d(
44
+ TAG,
45
+ "[$tag] $message"
46
+ )
47
+ }
48
+
49
+ fun error(
50
+ context: Context,
51
+ tag: String,
52
+ message: String,
53
+ throwable: Throwable? = null
54
+ ) {
55
+ if (!isDebugEnabled(context)) {
56
+ return
57
+ }
58
+ val fullMessage =
59
+ if (throwable != null) {
60
+ "$message\n${Log.getStackTraceString(throwable)}"
61
+ } else {
17
62
  message
63
+ }
64
+
65
+
66
+ save(
67
+ context,
68
+ "ERROR",
69
+ tag,
70
+ fullMessage
71
+ )
72
+
73
+
74
+ Log.e(
75
+ TAG,
76
+ "[$tag] $message",
77
+ throwable
78
+ )
79
+ }
80
+
81
+ private fun save(
82
+ context: Context,
83
+ level: String,
84
+ tag: String,
85
+ message: String
86
+ ) {
87
+
88
+ val sanitized =
89
+ sanitize(message)
90
+
91
+ val entry =
92
+ format(
93
+ level,
94
+ tag,
95
+ sanitized
18
96
  )
97
+
98
+
99
+ logs.add(entry)
100
+
101
+
102
+ DebugLogStorage.append(
103
+ context,
104
+ entry
105
+ )
106
+
107
+
108
+ trim()
109
+ }
110
+
111
+ fun getLogs(): List<String> {
112
+
113
+ return logs.toList()
114
+
115
+ }
116
+
117
+ fun clear(
118
+ context: Context
119
+ ) {
120
+
121
+ logs.clear()
122
+
123
+ DebugLogStorage.clear(context)
124
+
125
+ }
126
+
127
+ private fun isDebugEnabled(
128
+
129
+ context: Context
130
+
131
+ ): Boolean {
132
+
133
+ return BuildConfig.DEBUG ||
134
+
135
+ config(context).enabled
136
+
137
+ }
138
+
139
+ private fun sanitize(
140
+ message: String
141
+ ): String {
142
+
143
+ // Debug build može vidjeti sve
144
+ if (BuildConfig.DEBUG) {
145
+ return message
19
146
  }
147
+
148
+ // Release build uvijek sanitizira
149
+ return message
150
+ .replace(
151
+ Regex(
152
+ "\"plaintext\"\\s*:\\s*\".*?\""
153
+ ),
154
+ "\"plaintext\":\"***\""
155
+ )
156
+ .replace(
157
+ Regex(
158
+ "\"ciphertext\"\\s*:\\s*\".*?\""
159
+ ),
160
+ "\"ciphertext\":\"***\""
161
+ )
162
+ .replace(
163
+ Regex(
164
+ "\"sig\"\\s*:\\s*\".*?\""
165
+ ),
166
+ "\"sig\":\"***\""
167
+ )
168
+ .replace(
169
+ Regex(
170
+ "\"event\"\\s*:\\s*\".*?\""
171
+ ),
172
+ "\"event\":\"***\""
173
+ )
174
+ .replace(
175
+ Regex(
176
+ "(?i)authorization: .*"
177
+ ),
178
+ "authorization: ***"
179
+ )
180
+ .replace(
181
+ Regex(
182
+ "(?i)bearer\\s+[A-Za-z0-9._-]+"
183
+ ),
184
+ "Bearer ***"
185
+ )
186
+ .replace(
187
+ Regex(
188
+ "(?i)token=[^\\s&]+"
189
+ ),
190
+ "token=***"
191
+ )
192
+ .replace(
193
+ Regex(
194
+ "(?i)password=[^\\s&]+"
195
+ ),
196
+ "password=***"
197
+ )
198
+ }
199
+
200
+ private fun format(
201
+ level: String,
202
+ tag: String,
203
+ message: String
204
+ ): String {
205
+
206
+ val time =
207
+ SimpleDateFormat(
208
+ "yyyy-MM-dd HH:mm:ss",
209
+ Locale.US
210
+ )
211
+ .format(Date())
212
+
213
+
214
+ return "$time [$level] $tag: $message"
215
+
216
+ }
217
+
218
+ private fun trim() {
219
+
220
+ while (logs.size > MAX_LOGS) {
221
+
222
+ logs.removeAt(0)
223
+
224
+ }
225
+
226
+ }
227
+
228
+ private fun isDevelopmentBuild(): Boolean {
229
+ return BuildConfig.DEBUG
230
+ }
231
+
232
+ private fun isProductionDebug(context: Context): Boolean {
233
+ return !BuildConfig.DEBUG &&
234
+ RuntimeConfig.debugEnabled(context)
235
+ }
236
+
237
+ fun isNetworkLoggingEnabled(
238
+
239
+ context: Context
240
+
241
+ ): Boolean {
242
+
243
+ return BuildConfig.DEBUG ||
244
+
245
+ config(context).networkLogs
246
+
247
+ }
248
+
249
+ fun isWebViewLoggingEnabled(
250
+
251
+ context: Context
252
+
253
+ ): Boolean {
254
+
255
+ return BuildConfig.DEBUG ||
256
+
257
+ config(context).webViewLogs
258
+
259
+ }
260
+
261
+ fun network(
262
+ context: Context,
263
+ message: String
264
+ ) {
265
+ if (!isNetworkLoggingEnabled(context)) {
266
+ return
267
+ }
268
+
269
+ log(
270
+ context,
271
+ "HTTP",
272
+ message
273
+ )
274
+ }
275
+
276
+
277
+ fun webView(
278
+ context: Context,
279
+ message: String
280
+ ) {
281
+ if (!isWebViewLoggingEnabled(context)) {
282
+ return
283
+ }
284
+
285
+ log(
286
+ context,
287
+ "WEBVIEW",
288
+ message
289
+ )
290
+ }
291
+
292
+ private fun config(
293
+ context: Context
294
+ ): DebugConfig {
295
+
296
+
297
+ val runtime =
298
+ DebugRuntimeOverride.get(context)
299
+
300
+
301
+ if (runtime != null) {
302
+ return runtime
303
+ }
304
+
305
+
306
+ val stored =
307
+ DebugPreferences.load(
308
+ context
309
+ )
310
+
311
+
312
+ if (stored.enabled) {
313
+ return stored
314
+ }
315
+
316
+
317
+ return RuntimeConfig.debugConfig(
318
+ context
319
+ )
320
+
321
+ }
322
+
323
+ fun exportLogs(
324
+ context: Context
325
+ ): String {
326
+
327
+ return buildString {
328
+
329
+ appendLine(
330
+ "===== PAKSTR DEBUG LOG ====="
331
+ )
332
+
333
+ appendLine(
334
+ "Version: ${BuildConfig.VERSION_NAME}"
335
+ )
336
+
337
+ appendLine(
338
+ "Debug: ${isDebugEnabled(context)}"
339
+ )
340
+
341
+ appendLine()
342
+
343
+
344
+ getLogs().forEach {
345
+ appendLine(it)
346
+ }
347
+
348
+ }
349
+ }
350
+
351
+ fun load(
352
+
353
+ context: Context
354
+
355
+ ) {
356
+
357
+ logs.clear()
358
+
359
+ logs.addAll(
360
+
361
+ DebugLogStorage.read(context)
362
+
363
+ )
364
+
20
365
  }
21
366
  }
@@ -0,0 +1,32 @@
1
+ package com.pakstr.app.debug
2
+
3
+ import android.content.Context
4
+
5
+ object CrashHandler {
6
+
7
+ fun install(
8
+ context: Context
9
+ ) {
10
+
11
+ val defaultHandler =
12
+ Thread.getDefaultUncaughtExceptionHandler()
13
+
14
+
15
+ Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
16
+
17
+
18
+ AppDebugLogger.error(
19
+ context,
20
+ "CRASH",
21
+ "Unhandled exception in ${thread.name}",
22
+ throwable
23
+ )
24
+
25
+
26
+ defaultHandler?.uncaughtException(
27
+ thread,
28
+ throwable
29
+ )
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,11 @@
1
+ package com.pakstr.app.debug
2
+
3
+ data class DebugConfig(
4
+
5
+ val enabled: Boolean = false,
6
+
7
+ val networkLogs: Boolean = false,
8
+
9
+ val webViewLogs: Boolean = false,
10
+
11
+ )
@@ -0,0 +1,36 @@
1
+ package com.pakstr.app.debug
2
+
3
+ import org.json.JSONObject
4
+
5
+ object DebugConfigLoader {
6
+
7
+ fun load(
8
+ manifest: JSONObject
9
+ ): DebugConfig {
10
+
11
+ val debug =
12
+ manifest.optJSONObject("debug")
13
+ ?: return DebugConfig()
14
+
15
+ return DebugConfig(
16
+
17
+ enabled =
18
+ debug.optBoolean(
19
+ "enabled",
20
+ false
21
+ ),
22
+
23
+ networkLogs =
24
+ debug.optBoolean(
25
+ "networkLogs",
26
+ false
27
+ ),
28
+
29
+ webViewLogs =
30
+ debug.optBoolean(
31
+ "webViewLogs",
32
+ false
33
+ )
34
+ )
35
+ }
36
+ }
@@ -0,0 +1,29 @@
1
+ package com.pakstr.app.debug
2
+
3
+ import android.content.Context
4
+
5
+ object DebugConfigProvider {
6
+
7
+ private var manifestConfig =
8
+ DebugConfig()
9
+
10
+
11
+ fun initialize(
12
+ config: DebugConfig
13
+ ) {
14
+
15
+ manifestConfig = config
16
+
17
+ }
18
+
19
+
20
+ fun current(
21
+ context: Context
22
+ ): DebugConfig {
23
+
24
+ return DebugRuntimeOverride.get(context)
25
+ ?: manifestConfig
26
+
27
+ }
28
+
29
+ }
@@ -0,0 +1,139 @@
1
+ package com.pakstr.app.debug
2
+
3
+ import android.content.Context
4
+ import java.io.File
5
+
6
+ object DebugLogStorage {
7
+
8
+ private const val FILE_NAME =
9
+ "pakstr-debug.log"
10
+
11
+ private const val MAX_FILE_SIZE =
12
+ 1024 * 1024 // 1 MB
13
+
14
+ private const val MAX_LINES = 5000
15
+
16
+ fun append(
17
+ context: Context,
18
+ entry: String
19
+ ) {
20
+
21
+ try {
22
+
23
+ val file =
24
+ getFile(context)
25
+
26
+
27
+ rotateIfNeeded(file)
28
+
29
+
30
+ file.appendText(
31
+
32
+ entry + "\n"
33
+
34
+ )
35
+
36
+ trimFile(file)
37
+
38
+ } catch (_: Exception) {
39
+
40
+ // Logging must never crash the app
41
+
42
+ }
43
+ }
44
+
45
+ fun read(
46
+ context: Context
47
+ ): List<String> {
48
+
49
+ return try {
50
+
51
+ val file = getFile(context)
52
+
53
+ if (file.exists()) {
54
+ file.readLines()
55
+ } else {
56
+ emptyList()
57
+ }
58
+
59
+ } catch (_: Exception) {
60
+
61
+ emptyList()
62
+
63
+ }
64
+ }
65
+
66
+ fun clear(
67
+ context: Context
68
+ ) {
69
+
70
+ try {
71
+
72
+ getFile(context)
73
+ .delete()
74
+
75
+ } catch (_: Exception) {
76
+
77
+ }
78
+ }
79
+
80
+ private fun rotateIfNeeded(
81
+ file: File
82
+ ) {
83
+
84
+ if (!file.exists()) {
85
+ return
86
+ }
87
+
88
+
89
+ if (file.length() >= MAX_FILE_SIZE) {
90
+
91
+ file.writeText("")
92
+
93
+ }
94
+
95
+ }
96
+
97
+ private fun getFile(
98
+ context: Context
99
+ ): File {
100
+
101
+ return File(
102
+ context.cacheDir,
103
+ FILE_NAME
104
+ )
105
+
106
+ }
107
+
108
+ private fun trimFile(
109
+
110
+ file: File
111
+
112
+ ) {
113
+
114
+ try {
115
+
116
+ val lines =
117
+
118
+ file.readLines()
119
+
120
+ if (lines.size > MAX_LINES) {
121
+
122
+ file.writeText(
123
+
124
+ lines
125
+
126
+ .takeLast(MAX_LINES)
127
+
128
+ .joinToString("\n") + "\n"
129
+
130
+ )
131
+
132
+ }
133
+
134
+ } catch (_: Exception) {
135
+
136
+ }
137
+
138
+ }
139
+ }
@@ -0,0 +1,85 @@
1
+ package com.pakstr.app.debug
2
+
3
+ import android.content.Context
4
+
5
+ object DebugPreferences {
6
+
7
+ private const val PREFS_NAME = "pakstr_debug"
8
+
9
+ private const val KEY_ENABLED = "enabled"
10
+ private const val KEY_NETWORK = "networkLogs"
11
+ private const val KEY_WEBVIEW = "webViewLogs"
12
+
13
+
14
+ private fun prefs(context: Context) =
15
+ context.getSharedPreferences(
16
+ PREFS_NAME,
17
+ Context.MODE_PRIVATE
18
+ )
19
+
20
+
21
+ fun save(
22
+ context: Context,
23
+ config: DebugConfig
24
+ ) {
25
+
26
+ prefs(context)
27
+ .edit()
28
+ .putBoolean(
29
+ KEY_ENABLED,
30
+ config.enabled
31
+ )
32
+ .putBoolean(
33
+ KEY_NETWORK,
34
+ config.networkLogs
35
+ )
36
+ .putBoolean(
37
+ KEY_WEBVIEW,
38
+ config.webViewLogs
39
+ )
40
+ .apply()
41
+
42
+ }
43
+
44
+
45
+ fun load(
46
+ context: Context
47
+ ): DebugConfig {
48
+
49
+ val prefs = prefs(context)
50
+
51
+ return DebugConfig(
52
+
53
+ enabled =
54
+ prefs.getBoolean(
55
+ KEY_ENABLED,
56
+ false
57
+ ),
58
+
59
+ networkLogs =
60
+ prefs.getBoolean(
61
+ KEY_NETWORK,
62
+ false
63
+ ),
64
+
65
+ webViewLogs =
66
+ prefs.getBoolean(
67
+ KEY_WEBVIEW,
68
+ false
69
+ )
70
+
71
+ )
72
+ }
73
+
74
+
75
+ fun clear(
76
+ context: Context
77
+ ) {
78
+
79
+ prefs(context)
80
+ .edit()
81
+ .clear()
82
+ .apply()
83
+
84
+ }
85
+ }