pakstr 0.3.4 → 0.4.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 (23) hide show
  1. package/android-template/app/src/main/AndroidManifest.xml +17 -0
  2. package/android-template/app/src/main/java/com/pakstr/app/LocalServer.kt +80 -21
  3. package/android-template/app/src/main/java/com/pakstr/app/MainActivity.kt +46 -9
  4. package/android-template/app/src/main/java/com/pakstr/app/RuntimeConfig.kt +81 -37
  5. package/android-template/app/src/main/java/com/pakstr/app/ShellRuntime.kt +99 -8
  6. package/android-template/app/src/main/java/com/pakstr/app/WebViewController.kt +145 -20
  7. package/android-template/app/src/main/java/com/pakstr/app/crypto/Bip340Verifier.kt +0 -5
  8. package/android-template/app/src/main/java/com/pakstr/app/debug/AppDebugLogger.kt +275 -3
  9. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugConfig.kt +11 -0
  10. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugConfigLoader.kt +36 -0
  11. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugConfigProvider.kt +24 -0
  12. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugLogStorage.kt +107 -0
  13. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugReportExporter.kt +139 -0
  14. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugReportShare.kt +52 -0
  15. package/android-template/app/src/main/java/com/pakstr/app/debug/DebugRuntimeOverride.kt +29 -0
  16. package/android-template/app/src/main/java/com/pakstr/app/debug/DeveloperToolsManager.kt +34 -0
  17. package/android-template/app/src/main/java/com/pakstr/app/signer/AmberSigner.kt +1 -10
  18. package/android-template/app/src/main/java/com/pakstr/app/signer/NostrBridge.kt +163 -11
  19. package/android-template/app/src/main/java/com/pakstr/app/signer/SignerManager.kt +71 -0
  20. package/android-template/app/src/main/res/xml/file_paths.xml +9 -0
  21. package/dist/runners/LocalGradleRunner.js +12 -2
  22. package/dist/runtime/runtimeConfig.js +6 -1
  23. package/package.json +1 -1
@@ -26,6 +26,12 @@ class ShellRuntime(
26
26
 
27
27
  fun start() {
28
28
 
29
+ AppDebugLogger.log(
30
+ context,
31
+ "RUNTIME",
32
+ "Starting ShellRuntime"
33
+ )
34
+
29
35
  controller = WebViewController(
30
36
  context,
31
37
  webView,
@@ -34,14 +40,28 @@ class ShellRuntime(
34
40
  permissionHandler
35
41
  )
36
42
 
43
+ AppDebugLogger.log(
44
+ context,
45
+ "RUNTIME",
46
+ "WebViewController created"
47
+ )
48
+
49
+
37
50
  CoroutineScope(Dispatchers.IO).launch {
38
51
 
52
+ AppDebugLogger.log(
53
+ context,
54
+ "RUNTIME",
55
+ "Starting background initialization"
56
+ )
57
+
39
58
  val ok = startServer()
40
59
 
41
60
 
42
61
  if (!ok) {
43
62
 
44
- AppDebugLogger.log(
63
+ AppDebugLogger.error(
64
+ context,
45
65
  "RUNTIME",
46
66
  "Server failed"
47
67
  )
@@ -51,22 +71,53 @@ class ShellRuntime(
51
71
  }
52
72
 
53
73
 
74
+ AppDebugLogger.log(
75
+ context,
76
+ "RUNTIME",
77
+ "Server ready, switching to main thread"
78
+ )
79
+
80
+
54
81
  withContext(Dispatchers.Main) {
55
82
 
83
+ AppDebugLogger.log(
84
+ context,
85
+ "WEBVIEW",
86
+ "Setting up WebView controller"
87
+ )
88
+
56
89
  controller.setup()
57
90
 
91
+ AppDebugLogger.log(
92
+ context,
93
+ "WEBVIEW",
94
+ "WebView controller setup completed"
95
+ )
96
+
58
97
  }
59
98
 
60
99
  }
61
100
 
62
101
  }
63
102
 
64
-
65
103
  private fun startServer(): Boolean {
66
104
 
67
- if (server != null)
105
+ if (server != null) {
106
+
107
+ AppDebugLogger.log(
108
+
109
+ context,
110
+
111
+ "SERVER",
112
+
113
+ "Already running"
114
+
115
+ )
116
+
68
117
  return true
69
118
 
119
+ }
120
+
70
121
  return try {
71
122
 
72
123
  server = LocalServer(
@@ -80,32 +131,72 @@ class ShellRuntime(
80
131
  )
81
132
 
82
133
  AppDebugLogger.log(
134
+
135
+ context,
136
+
83
137
  "SERVER",
84
- "Started OK"
138
+
139
+ "Starting NanoHTTPD on port $port"
140
+
85
141
  )
86
142
 
87
143
  true
88
144
 
89
145
  } catch (e: Exception) {
90
146
 
91
- AppDebugLogger.log(
147
+ AppDebugLogger.error(
148
+
149
+ context,
150
+
92
151
  "SERVER",
93
- "Failed to start: ${e.message}"
152
+
153
+ "Failed to start",
154
+
155
+ e
156
+
94
157
  )
95
158
 
96
159
  false
97
160
  }
98
161
  }
99
162
 
100
-
101
163
  fun stop() {
102
164
 
165
+ AppDebugLogger.log(
166
+
167
+ context,
168
+
169
+ "RUNTIME",
170
+
171
+ "Stopping ShellRuntime"
172
+
173
+ )
174
+
103
175
  server?.stop()
104
176
 
177
+ AppDebugLogger.log(
178
+
179
+ context,
180
+
181
+ "SERVER",
182
+
183
+ "Server stopped"
184
+
185
+ )
186
+
105
187
  controller.destroy()
106
188
 
107
- }
189
+ AppDebugLogger.log(
190
+
191
+ context,
192
+
193
+ "WEBVIEW",
108
194
 
195
+ "WebView destroyed"
196
+
197
+ )
198
+
199
+ }
109
200
 
110
201
  fun getWebview(): WebView {
111
202
 
@@ -43,6 +43,7 @@ class WebViewController(
43
43
  private val loadRunnable = Runnable {
44
44
  webView.loadUrl("http://127.0.0.1:$port/")
45
45
  //webView.loadUrl("https://sigit.io")
46
+ //webView.loadUrl("http://127.0.0.1:$port/not-found.html")
46
47
  }
47
48
 
48
49
  private var nip07Injected = false
@@ -84,17 +85,105 @@ class WebViewController(
84
85
  webViewClient = object : WebViewClient() {
85
86
 
86
87
  override fun onPageFinished(
87
- view: WebView?,
88
- url: String?
88
+ view: WebView?, url: String?
89
89
  ) {
90
90
  super.onPageFinished(view, url)
91
91
 
92
92
  hideLoader()
93
93
 
94
94
  if (!nip07Injected) {
95
- nip07Injected =
96
- injectNip07()
95
+ nip07Injected = injectNip07()
96
+
97
+ }
98
+ }
99
+
100
+ override fun onReceivedHttpError(
101
+
102
+ view: WebView?,
103
+
104
+ request: WebResourceRequest?,
105
+
106
+ errorResponse: WebResourceResponse?
107
+
108
+ ) {
109
+
110
+ super.onReceivedHttpError(
111
+
112
+ view,
113
+
114
+ request,
115
+
116
+ errorResponse
117
+
118
+ )
119
+
120
+ val url =
121
+
122
+ request?.url?.toString()
123
+
124
+ ?: return
125
+
126
+ if (url.endsWith("favicon.ico")) {
127
+
128
+ return
129
+
130
+ }
131
+ if (AppDebugLogger.isWebViewLoggingEnabled(context)) {
132
+ AppDebugLogger.error(
133
+
134
+ context,
135
+
136
+ "WEBVIEW",
137
+
138
+ "HTTP error: $url status=${errorResponse?.statusCode}"
139
+
140
+ )
141
+ }
142
+ }
143
+
144
+ override fun onReceivedError(
145
+
146
+ view: WebView?,
147
+
148
+ request: WebResourceRequest?,
149
+
150
+ error: android.webkit.WebResourceError?
151
+
152
+ ) {
153
+
154
+ super.onReceivedError(
155
+
156
+ view,
157
+
158
+ request,
97
159
 
160
+ error
161
+
162
+ )
163
+
164
+ val url =
165
+
166
+ request?.url?.toString()
167
+
168
+ ?: "unknown"
169
+
170
+ val message =
171
+
172
+ error?.description
173
+
174
+ ?.toString()
175
+
176
+ ?: "unknown error"
177
+ if (AppDebugLogger.isWebViewLoggingEnabled(context)) {
178
+ AppDebugLogger.error(
179
+
180
+ context,
181
+
182
+ "WEBVIEW",
183
+
184
+ "Load error: $url - $message"
185
+
186
+ )
98
187
  }
99
188
  }
100
189
 
@@ -110,22 +199,60 @@ class WebViewController(
110
199
  }
111
200
 
112
201
  override fun shouldOverrideUrlLoading(
113
- view: WebView?,
114
- request: WebResourceRequest?
202
+ view: WebView?, request: WebResourceRequest?
115
203
  ): Boolean {
116
204
  val url = request?.url ?: return true
117
205
  return url.host != "127.0.0.1"
118
206
  }
119
207
 
120
-
121
208
  }
122
209
  webChromeClient = object : WebChromeClient() {
123
210
 
124
- override fun onPermissionRequest(request: PermissionRequest) {
211
+ override fun onPermissionRequest(
212
+
213
+ request: PermissionRequest
214
+
215
+ ) {
125
216
 
126
217
  permissionHandler.onPermissionRequest(request)
127
218
 
128
219
  }
220
+
221
+ override fun onConsoleMessage(
222
+
223
+ consoleMessage: android.webkit.ConsoleMessage
224
+
225
+ ): Boolean {
226
+
227
+ val level =
228
+
229
+ when (consoleMessage.messageLevel()) {
230
+
231
+ android.webkit.ConsoleMessage.MessageLevel.ERROR -> "ERROR"
232
+
233
+ android.webkit.ConsoleMessage.MessageLevel.WARNING -> "WARN"
234
+
235
+ android.webkit.ConsoleMessage.MessageLevel.LOG -> "LOG"
236
+
237
+ else -> "DEBUG"
238
+ }
239
+ if (AppDebugLogger.isWebViewLoggingEnabled(context)) {
240
+ AppDebugLogger.log(
241
+
242
+ context,
243
+
244
+ "WEBVIEW",
245
+
246
+ "$level: ${consoleMessage.message()} " +
247
+
248
+ "(${consoleMessage.sourceId()}:${consoleMessage.lineNumber()})"
249
+
250
+ )
251
+ }
252
+ return true
253
+
254
+ }
255
+
129
256
  }
130
257
  }
131
258
 
@@ -139,7 +266,7 @@ class WebViewController(
139
266
 
140
267
  webView = webView,
141
268
 
142
- ),
269
+ ),
143
270
 
144
271
  "AndroidBridge"
145
272
 
@@ -199,22 +326,20 @@ class WebViewController(
199
326
  private fun injectNip07(): Boolean {
200
327
 
201
328
  return try {
202
- val js =
203
- context.assets
204
- .open("nip07.js")
205
- .bufferedReader()
206
- .readText()
329
+ val js = context.assets.open("nip07.js")
330
+ .bufferedReader()
331
+ .readText()
207
332
 
208
333
  webView.evaluateJavascript(
209
- js,
210
- null
334
+ js, null
211
335
  )
212
336
  true
213
337
  } catch (e: Exception) {
214
- AppDebugLogger.log(
215
- "WEBVIEW",
216
- "Failed loading nip07.js: ${e.message}"
217
- )
338
+ if (AppDebugLogger.isWebViewLoggingEnabled(context)) {
339
+ AppDebugLogger.log(
340
+ context, "WebViewController - WEBVIEW", "Failed loading nip07.js: ${e.message}"
341
+ )
342
+ }
218
343
  false
219
344
  }
220
345
  }
@@ -146,11 +146,6 @@ object Bip340Verifier {
146
146
 
147
147
  } catch (e: Exception) {
148
148
 
149
- AppDebugLogger.log(
150
- "BIP340",
151
- "Verification failed: ${e.message}"
152
- )
153
-
154
149
  false
155
150
 
156
151
  }
@@ -1,21 +1,293 @@
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.Date
9
+ import java.util.Locale
5
10
 
6
11
  object AppDebugLogger {
7
12
 
13
+ private const val TAG = "PakstrDebug"
14
+
15
+ private const val MAX_LOGS = 500
16
+
17
+ private val logs =
18
+ mutableListOf<String>()
19
+
8
20
  fun log(
21
+ context: Context,
9
22
  tag: String,
10
23
  message: String
11
24
  ) {
12
25
 
13
- if (BuildConfig.DEBUG) {
26
+ if (!isDebugEnabled(context)) {
27
+ return
28
+ }
14
29
 
15
- Log.d(
16
- tag,
30
+ save(
31
+ context,
32
+ "DEBUG",
33
+ tag,
34
+ message
35
+ )
36
+
37
+ Log.d(
38
+ TAG,
39
+ "[$tag] $message"
40
+ )
41
+ }
42
+
43
+ fun error(
44
+ context: Context,
45
+ tag: String,
46
+ message: String,
47
+ throwable: Throwable? = null
48
+ ) {
49
+ if (!isDebugEnabled(context)) {
50
+ return
51
+ }
52
+ val fullMessage =
53
+ if (throwable != null) {
54
+ "$message\n${Log.getStackTraceString(throwable)}"
55
+ } else {
17
56
  message
57
+ }
58
+
59
+
60
+ save(
61
+ context,
62
+ "ERROR",
63
+ tag,
64
+ fullMessage
65
+ )
66
+
67
+
68
+ Log.e(
69
+ TAG,
70
+ "[$tag] $message",
71
+ throwable
72
+ )
73
+ }
74
+
75
+ private fun save(
76
+ context: Context,
77
+ level: String,
78
+ tag: String,
79
+ message: String
80
+ ) {
81
+
82
+ val sanitized =
83
+ sanitize(message)
84
+
85
+ val entry =
86
+ format(
87
+ level,
88
+ tag,
89
+ sanitized
18
90
  )
91
+
92
+
93
+ logs.add(entry)
94
+
95
+
96
+ DebugLogStorage.append(
97
+ context,
98
+ entry
99
+ )
100
+
101
+
102
+ trim()
103
+ }
104
+
105
+ fun getLogs(): List<String> {
106
+
107
+ return logs.toList()
108
+
109
+ }
110
+
111
+ fun clear() {
112
+
113
+ logs.clear()
114
+
115
+ }
116
+
117
+ private fun isDebugEnabled(
118
+
119
+ context: Context
120
+
121
+ ): Boolean {
122
+
123
+ return BuildConfig.DEBUG ||
124
+
125
+ config(context).enabled
126
+
127
+ }
128
+
129
+ private fun sanitize(
130
+ message: String
131
+ ): String {
132
+
133
+ // Debug build može vidjeti sve
134
+ if (BuildConfig.DEBUG) {
135
+ return message
19
136
  }
137
+
138
+ // Release build uvijek sanitizira
139
+ return message
140
+ .replace(
141
+ Regex(
142
+ "\"plaintext\"\\s*:\\s*\".*?\""
143
+ ),
144
+ "\"plaintext\":\"***\""
145
+ )
146
+ .replace(
147
+ Regex(
148
+ "\"ciphertext\"\\s*:\\s*\".*?\""
149
+ ),
150
+ "\"ciphertext\":\"***\""
151
+ )
152
+ .replace(
153
+ Regex(
154
+ "\"sig\"\\s*:\\s*\".*?\""
155
+ ),
156
+ "\"sig\":\"***\""
157
+ )
158
+ .replace(
159
+ Regex(
160
+ "\"event\"\\s*:\\s*\".*?\""
161
+ ),
162
+ "\"event\":\"***\""
163
+ )
164
+ .replace(
165
+ Regex(
166
+ "(?i)authorization: .*"
167
+ ),
168
+ "authorization: ***"
169
+ )
170
+ .replace(
171
+ Regex(
172
+ "(?i)bearer\\s+[A-Za-z0-9._-]+"
173
+ ),
174
+ "Bearer ***"
175
+ )
176
+ .replace(
177
+ Regex(
178
+ "(?i)token=[^\\s&]+"
179
+ ),
180
+ "token=***"
181
+ )
182
+ .replace(
183
+ Regex(
184
+ "(?i)password=[^\\s&]+"
185
+ ),
186
+ "password=***"
187
+ )
188
+ }
189
+
190
+ private fun format(
191
+ level: String,
192
+ tag: String,
193
+ message: String
194
+ ): String {
195
+
196
+ val time =
197
+ SimpleDateFormat(
198
+ "yyyy-MM-dd HH:mm:ss",
199
+ Locale.US
200
+ )
201
+ .format(Date())
202
+
203
+
204
+ return "$time [$level] $tag: $message"
205
+
206
+ }
207
+
208
+ private fun trim() {
209
+
210
+ while (logs.size > MAX_LOGS) {
211
+
212
+ logs.removeAt(0)
213
+
214
+ }
215
+
216
+ }
217
+
218
+ private fun isDevelopmentBuild(): Boolean {
219
+ return BuildConfig.DEBUG
220
+ }
221
+
222
+ private fun isProductionDebug(context: Context): Boolean {
223
+ return !BuildConfig.DEBUG &&
224
+ RuntimeConfig.debugEnabled(context)
225
+ }
226
+
227
+ fun isNetworkLoggingEnabled(
228
+
229
+ context: Context
230
+
231
+ ): Boolean {
232
+
233
+ return BuildConfig.DEBUG ||
234
+
235
+ config(context).networkLogs
236
+
237
+ }
238
+
239
+ fun isWebViewLoggingEnabled(
240
+
241
+ context: Context
242
+
243
+ ): Boolean {
244
+
245
+ return BuildConfig.DEBUG ||
246
+
247
+ config(context).webViewLogs
248
+
249
+ }
250
+
251
+ fun network(
252
+ context: Context,
253
+ message: String
254
+ ) {
255
+ if (!isNetworkLoggingEnabled(context)) {
256
+ return
257
+ }
258
+
259
+ log(
260
+ context,
261
+ "HTTP",
262
+ message
263
+ )
264
+ }
265
+
266
+
267
+ fun webView(
268
+ context: Context,
269
+ message: String
270
+ ) {
271
+ if (!isWebViewLoggingEnabled(context)) {
272
+ return
273
+ }
274
+
275
+ log(
276
+ context,
277
+ "WEBVIEW",
278
+ message
279
+ )
280
+ }
281
+
282
+ private fun config(
283
+
284
+ context: Context
285
+
286
+ ): DebugConfig {
287
+
288
+ return DebugRuntimeOverride.get()
289
+
290
+ ?: RuntimeConfig.debugConfig(context)
291
+
20
292
  }
21
293
  }
@@ -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
+ )