adb-sqlite-viewer 1.0.5

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.
@@ -0,0 +1,821 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>ADB SQLite Query Viewer</title>
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ body {
16
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
17
+ background: #f5f6f7;
18
+ display: flex;
19
+ height: 100vh;
20
+ overflow: hidden;
21
+ }
22
+
23
+ /* Sidebar */
24
+ .sidebar {
25
+ width: 280px;
26
+ background: #2c3e50;
27
+ color: #ecf0f1;
28
+ display: flex;
29
+ flex-direction: column;
30
+ border-right: 1px solid #34495e;
31
+ }
32
+
33
+ .sidebar-header {
34
+ padding: 20px;
35
+ background: #34495e;
36
+ border-bottom: 1px solid #2c3e50;
37
+ }
38
+
39
+ .sidebar-header h1 {
40
+ font-size: 18px;
41
+ font-weight: 600;
42
+ margin-bottom: 5px;
43
+ }
44
+
45
+ .connection-status {
46
+ font-size: 12px;
47
+ padding: 5px 10px;
48
+ border-radius: 4px;
49
+ display: inline-block;
50
+ margin-top: 10px;
51
+ }
52
+
53
+ .connection-status.connected {
54
+ background: #27ae60;
55
+ color: white;
56
+ }
57
+
58
+ .connection-status.disconnected {
59
+ background: #e74c3c;
60
+ color: white;
61
+ }
62
+
63
+ .connection-status.bridge {
64
+ background: #8e44ad;
65
+ color: white;
66
+ }
67
+
68
+ /* Config Section - top panel */
69
+ .config-section {
70
+ background: #f8f9fa;
71
+ border-bottom: 2px solid #dee2e6;
72
+ }
73
+
74
+ .config-toggle {
75
+ padding: 8px 20px;
76
+ display: flex;
77
+ align-items: center;
78
+ gap: 8px;
79
+ cursor: pointer;
80
+ font-size: 13px;
81
+ font-weight: 600;
82
+ color: #495057;
83
+ background: #e9ecef;
84
+ border-bottom: 1px solid #dee2e6;
85
+ user-select: none;
86
+ transition: background 0.2s;
87
+ }
88
+
89
+ .config-toggle:hover {
90
+ background: #dee2e6;
91
+ }
92
+
93
+ .config-toggle .toggle-arrow {
94
+ font-size: 10px;
95
+ transition: transform 0.2s;
96
+ color: #6c757d;
97
+ }
98
+
99
+ .config-section.expanded .toggle-arrow {
100
+ transform: rotate(180deg);
101
+ }
102
+
103
+ .config-panel {
104
+ display: none;
105
+ padding: 12px 20px;
106
+ }
107
+
108
+ .config-section.expanded .config-panel {
109
+ display: block;
110
+ }
111
+
112
+ .config-row {
113
+ display: flex;
114
+ gap: 16px;
115
+ flex-wrap: wrap;
116
+ align-items: flex-end;
117
+ }
118
+
119
+ .config-group {
120
+ flex: 1;
121
+ min-width: 180px;
122
+ }
123
+
124
+ .config-group label {
125
+ display: block;
126
+ font-size: 11px;
127
+ font-weight: 600;
128
+ text-transform: uppercase;
129
+ letter-spacing: 0.5px;
130
+ color: #6c757d;
131
+ margin-bottom: 4px;
132
+ }
133
+
134
+ .config-group select,
135
+ .config-group input[type="text"] {
136
+ width: 100%;
137
+ padding: 6px 10px;
138
+ border: 1px solid #ced4da;
139
+ border-radius: 4px;
140
+ background: white;
141
+ color: #495057;
142
+ font-size: 12px;
143
+ appearance: auto;
144
+ }
145
+
146
+ .config-group select:focus,
147
+ .config-group input[type="text"]:focus {
148
+ outline: none;
149
+ border-color: #3498db;
150
+ box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.15);
151
+ }
152
+
153
+ .config-group .input-with-btn {
154
+ display: flex;
155
+ gap: 6px;
156
+ }
157
+
158
+ .config-group .input-with-btn input {
159
+ flex: 1;
160
+ }
161
+
162
+ .config-group .input-with-btn button {
163
+ padding: 6px 12px;
164
+ border: 1px solid #3498db;
165
+ border-radius: 4px;
166
+ background: #3498db;
167
+ color: white;
168
+ font-size: 11px;
169
+ cursor: pointer;
170
+ white-space: nowrap;
171
+ }
172
+
173
+ .config-group .input-with-btn button:hover {
174
+ background: #2980b9;
175
+ }
176
+
177
+ /* USB connect button */
178
+ .usb-connect-btn {
179
+ padding: 6px 14px;
180
+ border: 1px solid #27ae60;
181
+ border-radius: 4px;
182
+ background: #27ae60;
183
+ color: white;
184
+ font-size: 12px;
185
+ font-weight: 600;
186
+ cursor: pointer;
187
+ white-space: nowrap;
188
+ transition: background 0.2s;
189
+ }
190
+
191
+ .usb-connect-btn:hover {
192
+ background: #219a52;
193
+ }
194
+
195
+ .usb-connect-btn.disconnect {
196
+ background: #e74c3c;
197
+ border-color: #e74c3c;
198
+ }
199
+
200
+ .usb-connect-btn.disconnect:hover {
201
+ background: #c0392b;
202
+ }
203
+
204
+ .device-status {
205
+ font-size: 11px;
206
+ color: #495057;
207
+ margin-top: 4px;
208
+ }
209
+
210
+ .device-status.ok {
211
+ color: #27ae60;
212
+ }
213
+
214
+ /* Generic dropdown used by both package search and db search */
215
+ .combo-dropdown {
216
+ max-height: 220px;
217
+ overflow-y: auto;
218
+ background: white;
219
+ border: 1px solid #ced4da;
220
+ border-top: none;
221
+ border-radius: 0 0 4px 4px;
222
+ display: none;
223
+ position: absolute;
224
+ z-index: 100;
225
+ left: 0;
226
+ right: 0;
227
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
228
+ }
229
+
230
+ .combo-dropdown.visible {
231
+ display: block;
232
+ }
233
+
234
+ .combo-item {
235
+ padding: 7px 10px;
236
+ font-size: 12px;
237
+ cursor: pointer;
238
+ border-bottom: 1px solid #f0f0f0;
239
+ color: #495057;
240
+ }
241
+
242
+ .combo-item:last-child {
243
+ border-bottom: none;
244
+ }
245
+
246
+ .combo-item:hover,
247
+ .combo-item.active {
248
+ background: #3498db;
249
+ color: white;
250
+ }
251
+
252
+ .combo-item .item-sub {
253
+ font-size: 10px;
254
+ color: #6c757d;
255
+ margin-top: 2px;
256
+ }
257
+
258
+ .combo-item:hover .item-sub,
259
+ .combo-item.active .item-sub {
260
+ color: #d5e8f7;
261
+ }
262
+
263
+ .combo-empty {
264
+ padding: 10px;
265
+ font-size: 12px;
266
+ color: #999;
267
+ text-align: center;
268
+ font-style: italic;
269
+ }
270
+
271
+ .combo-wrapper {
272
+ position: relative;
273
+ }
274
+
275
+ .combo-wrapper input {
276
+ padding-right: 28px;
277
+ }
278
+
279
+ .combo-clear {
280
+ position: absolute;
281
+ right: 6px;
282
+ top: 50%;
283
+ transform: translateY(-50%);
284
+ background: none;
285
+ border: none;
286
+ color: #999;
287
+ font-size: 14px;
288
+ cursor: pointer;
289
+ padding: 0 4px;
290
+ line-height: 1;
291
+ display: none;
292
+ }
293
+
294
+ .combo-clear:hover {
295
+ color: #e74c3c;
296
+ }
297
+
298
+ .combo-wrapper.has-value .combo-clear {
299
+ display: block;
300
+ }
301
+
302
+ /* Backward compat aliases */
303
+ .search-results-dropdown {
304
+ max-height: 220px;
305
+ overflow-y: auto;
306
+ background: white;
307
+ border: 1px solid #ced4da;
308
+ border-top: none;
309
+ border-radius: 0 0 4px 4px;
310
+ display: none;
311
+ position: absolute;
312
+ z-index: 100;
313
+ left: 0;
314
+ right: 0;
315
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
316
+ }
317
+
318
+ .search-results-dropdown.visible {
319
+ display: block;
320
+ }
321
+
322
+ .search-result-item {
323
+ padding: 7px 10px;
324
+ font-size: 12px;
325
+ cursor: pointer;
326
+ border-bottom: 1px solid #f0f0f0;
327
+ color: #495057;
328
+ }
329
+
330
+ .search-result-item:hover {
331
+ background: #3498db;
332
+ color: white;
333
+ }
334
+
335
+ .search-result-item .file-name {
336
+ font-weight: 600;
337
+ }
338
+
339
+ .search-result-item .file-path {
340
+ font-size: 10px;
341
+ color: #6c757d;
342
+ margin-top: 2px;
343
+ }
344
+
345
+ .search-result-item:hover .file-path {
346
+ color: #d5e8f7;
347
+ }
348
+
349
+ .sidebar-search {
350
+ padding: 15px;
351
+ border-bottom: 1px solid #34495e;
352
+ }
353
+
354
+ .sidebar-search input {
355
+ width: 100%;
356
+ padding: 8px 12px;
357
+ border: 1px solid #34495e;
358
+ border-radius: 4px;
359
+ background: #34495e;
360
+ color: #ecf0f1;
361
+ font-size: 13px;
362
+ }
363
+
364
+ .sidebar-search input::placeholder {
365
+ color: #95a5a6;
366
+ }
367
+
368
+ .tables-list {
369
+ flex: 1;
370
+ overflow-y: auto;
371
+ padding: 10px 0;
372
+ }
373
+
374
+ .table-item {
375
+ padding: 0;
376
+ cursor: default;
377
+ transition: background 0.2s;
378
+ border-left: 3px solid transparent;
379
+ display: block;
380
+ }
381
+
382
+ .accordion-header {
383
+ padding: 10px 15px;
384
+ display: flex;
385
+ align-items: center;
386
+ cursor: pointer;
387
+ transition: background 0.2s;
388
+ }
389
+
390
+ .accordion-header:hover {
391
+ background: #34495e;
392
+ }
393
+
394
+ .accordion-header .arrow {
395
+ margin-right: 8px;
396
+ font-size: 10px;
397
+ transition: transform 0.2s;
398
+ color: #95a5a6;
399
+ }
400
+
401
+ .table-item.expanded .arrow {
402
+ transform: rotate(90deg);
403
+ }
404
+
405
+ .table-item-name {
406
+ flex: 1;
407
+ font-size: 14px;
408
+ font-weight: 500;
409
+ }
410
+
411
+ .query-btn {
412
+ padding: 2px 8px;
413
+ font-size: 11px;
414
+ background: #3498db;
415
+ border: none;
416
+ border-radius: 3px;
417
+ color: white;
418
+ cursor: pointer;
419
+ margin-left: 8px;
420
+ opacity: 0;
421
+ transition: opacity 0.2s;
422
+ }
423
+
424
+ .accordion-header:hover .query-btn {
425
+ opacity: 1;
426
+ }
427
+
428
+ .query-btn:hover {
429
+ background: #2980b9;
430
+ }
431
+
432
+ .accordion-content {
433
+ display: none;
434
+ background: #233342;
435
+ padding: 5px 15px 5px 33px;
436
+ font-size: 12px;
437
+ border-top: 1px solid #34495e;
438
+ }
439
+
440
+ .table-item.expanded .accordion-content {
441
+ display: block;
442
+ }
443
+
444
+ .column-item {
445
+ padding: 3px 0;
446
+ color: #bdc3c7;
447
+ display: flex;
448
+ justify-content: space-between;
449
+ font-family: monospace;
450
+ }
451
+
452
+ .column-type {
453
+ color: #7f8c8d;
454
+ font-size: 10px;
455
+ margin-left: 10px;
456
+ }
457
+
458
+ .pk-badge {
459
+ color: #f1c40f;
460
+ margin-right: 4px;
461
+ }
462
+
463
+ /* Main Content */
464
+ .main-content {
465
+ flex: 1;
466
+ display: flex;
467
+ flex-direction: column;
468
+ overflow: hidden;
469
+ }
470
+
471
+ .toolbar {
472
+ background: white;
473
+ border-bottom: 1px solid #ddd;
474
+ padding: 15px 20px;
475
+ display: flex;
476
+ gap: 10px;
477
+ align-items: center;
478
+ }
479
+
480
+ .toolbar button {
481
+ padding: 8px 16px;
482
+ border: 1px solid #ddd;
483
+ background: white;
484
+ border-radius: 4px;
485
+ cursor: pointer;
486
+ font-size: 13px;
487
+ transition: all 0.2s;
488
+ }
489
+
490
+ .toolbar button:hover {
491
+ background: #f8f9fa;
492
+ }
493
+
494
+ .toolbar button.primary {
495
+ background: #3498db;
496
+ color: white;
497
+ border-color: #3498db;
498
+ }
499
+
500
+ .toolbar button.primary:hover {
501
+ background: #2980b9;
502
+ }
503
+
504
+ .query-editor {
505
+ background: white;
506
+ border-bottom: 1px solid #ddd;
507
+ padding: 15px 20px;
508
+ }
509
+
510
+ .query-editor textarea {
511
+ width: 100%;
512
+ padding: 12px;
513
+ border: 1px solid #ddd;
514
+ border-radius: 4px;
515
+ font-family: 'Courier New', monospace;
516
+ font-size: 13px;
517
+ resize: vertical;
518
+ min-height: 80px;
519
+ }
520
+
521
+ .content-area {
522
+ flex: 1;
523
+ overflow: auto;
524
+ background: white;
525
+ position: relative;
526
+ }
527
+
528
+ .table-wrapper {
529
+ overflow: auto;
530
+ height: 55vh;
531
+ max-height: 100%;
532
+ max-width: 100%;
533
+ position: relative;
534
+ }
535
+
536
+ table {
537
+ width: max-content;
538
+ min-width: 100%;
539
+ border-collapse: collapse;
540
+ font-size: 13px;
541
+ }
542
+
543
+ thead {
544
+ position: sticky;
545
+ top: 0;
546
+ background: #f8f9fa;
547
+ z-index: 10;
548
+ }
549
+
550
+ th {
551
+ padding: 12px 15px;
552
+ text-align: left;
553
+ font-weight: 600;
554
+ border-bottom: 2px solid #dee2e6;
555
+ border-right: 1px solid #dee2e6;
556
+ background: #f8f9fa;
557
+ color: #495057;
558
+ }
559
+
560
+ td {
561
+ padding: 10px 15px;
562
+ border-bottom: 1px solid #dee2e6;
563
+ border-right: 1px solid #dee2e6;
564
+ white-space: nowrap;
565
+ }
566
+
567
+ tbody tr:hover {
568
+ background: #f8f9fa;
569
+ }
570
+
571
+ .status-bar {
572
+ background: #f8f9fa;
573
+ border-top: 1px solid #ddd;
574
+ padding: 8px 20px;
575
+ font-size: 12px;
576
+ color: #666;
577
+ }
578
+
579
+ .loading {
580
+ padding: 40px;
581
+ text-align: center;
582
+ color: #666;
583
+ }
584
+
585
+ .error {
586
+ padding: 20px;
587
+ background: #fee;
588
+ color: #c33;
589
+ border: 1px solid #fcc;
590
+ border-radius: 4px;
591
+ margin: 20px;
592
+ }
593
+
594
+ .info {
595
+ padding: 20px;
596
+ background: #e3f2fd;
597
+ color: #1976d2;
598
+ border: 1px solid #90caf9;
599
+ border-radius: 4px;
600
+ margin: 20px;
601
+ }
602
+
603
+ .pagination {
604
+ padding: 15px 20px;
605
+ background: white;
606
+ border-top: 1px solid #ddd;
607
+ display: flex;
608
+ justify-content: space-between;
609
+ align-items: center;
610
+ }
611
+
612
+ .pagination button {
613
+ padding: 6px 12px;
614
+ border: 1px solid #ddd;
615
+ background: white;
616
+ border-radius: 4px;
617
+ cursor: pointer;
618
+ font-size: 12px;
619
+ }
620
+
621
+ .pagination button:disabled {
622
+ opacity: 0.5;
623
+ cursor: not-allowed;
624
+ }
625
+
626
+ .pagination button:not(:disabled):hover {
627
+ background: #f8f9fa;
628
+ }
629
+
630
+ .pagination input[type="number"] {
631
+ border: 1px solid #ddd;
632
+ border-radius: 4px;
633
+ }
634
+
635
+ .pagination select {
636
+ border: 1px solid #ddd;
637
+ border-radius: 4px;
638
+ background: white;
639
+ }
640
+
641
+ .pagination label {
642
+ font-size: 12px;
643
+ color: #666;
644
+ }
645
+
646
+ /* Tabs */
647
+ .tabs {
648
+ display: flex;
649
+ gap: 5px;
650
+ padding: 0 20px;
651
+ background: white;
652
+ border-bottom: 1px solid #ddd;
653
+ }
654
+
655
+ .tab {
656
+ padding: 10px 20px;
657
+ cursor: pointer;
658
+ border-bottom: 2px solid transparent;
659
+ font-size: 13px;
660
+ color: #666;
661
+ }
662
+
663
+ .tab:hover {
664
+ background: #f8f9fa;
665
+ }
666
+
667
+ .tab.active {
668
+ color: #3498db;
669
+ border-bottom-color: #3498db;
670
+ }
671
+
672
+ .tab-content {
673
+ display: none;
674
+ }
675
+
676
+ .tab-content.active {
677
+ display: block;
678
+ }
679
+
680
+ /* Refresh button animation */
681
+ @keyframes spin {
682
+ from { transform: rotate(0deg); }
683
+ to { transform: rotate(360deg); }
684
+ }
685
+
686
+ .spinning {
687
+ animation: spin 1s linear infinite;
688
+ }
689
+ </style>
690
+ <script type="module" crossorigin src="./assets/index-COoGrD16.js"></script>
691
+ </head>
692
+
693
+ <body>
694
+ <!-- Sidebar -->
695
+ <div class="sidebar">
696
+ <div class="sidebar-header">
697
+ <h1>ADB SQLite Viewer</h1>
698
+ <div class="connection-status disconnected" id="connectionStatus">
699
+ Not connected
700
+ </div>
701
+ </div>
702
+ <div class="sidebar-search">
703
+ <input type="text" id="tableSearch" placeholder="Search tables...">
704
+ </div>
705
+ <div class="tables-list" id="tablesList">
706
+ <div class="info" style="margin: 10px; font-size: 12px;">Connect a USB device to get started.</div>
707
+ </div>
708
+ </div>
709
+
710
+ <!-- Main Content -->
711
+ <div class="main-content">
712
+ <!-- Collapsible Configuration Panel -->
713
+ <div class="config-section expanded" id="configSection">
714
+ <div class="config-toggle" id="configToggleBtn">
715
+ <span class="toggle-arrow">&#9660;</span>
716
+ <span>Device &amp; Database Configuration</span>
717
+ </div>
718
+ <div class="config-panel">
719
+ <div class="config-row">
720
+ <div class="config-group">
721
+ <label>USB Device</label>
722
+ <div style="display: flex; gap: 8px; align-items: center;">
723
+ <button class="usb-connect-btn" id="usbConnectBtn">Connect Device</button>
724
+ </div>
725
+ <div class="device-status" id="deviceStatus">No device connected</div>
726
+ </div>
727
+ <div class="config-group" style="position: relative;">
728
+ <label>Package (debuggable only)</label>
729
+ <div class="combo-wrapper" id="packageComboWrapper">
730
+ <input type="text" id="packageSearchInput"
731
+ placeholder="Connect device first..."
732
+ disabled>
733
+ <button class="combo-clear" id="packageClearBtn" title="Clear selection">&times;</button>
734
+ </div>
735
+ <div class="combo-dropdown" id="packageDropdown"></div>
736
+ </div>
737
+ <div class="config-group">
738
+ <label>Database File</label>
739
+ <select id="databaseSelect" disabled>
740
+ <option value="">Select a package first</option>
741
+ </select>
742
+ </div>
743
+ <div class="config-group" style="position: relative;">
744
+ <label>Search SQLite Files</label>
745
+ <div class="input-with-btn">
746
+ <input type="text" id="dbSearchInput" placeholder="Search for .db files...">
747
+ <button id="dbSearchBtn">Search</button>
748
+ </div>
749
+ <div class="search-results-dropdown" id="searchResultsDropdown"></div>
750
+ </div>
751
+ </div>
752
+ </div>
753
+ </div>
754
+
755
+ <div class="toolbar">
756
+ <button class="primary" id="executeBtn">Execute (F5)</button>
757
+ <button id="executeAllBtn" title="Run the entire query ignoring selection">Execute All</button>
758
+ <button id="refreshTablesBtn">Refresh Tables</button>
759
+ <button id="clearQueryBtn">Clear Query</button>
760
+ <button id="formatQueryBtn">Format</button>
761
+ </div>
762
+
763
+ <div class="tabs">
764
+ <div class="tab active" data-tab="query">Query</div>
765
+ <div class="tab" data-tab="structure">Structure</div>
766
+ </div>
767
+
768
+ <div class="query-editor">
769
+ <textarea id="queryInput" placeholder="Enter your SQL query here..."></textarea>
770
+ </div>
771
+
772
+ <div class="tab-content active" id="queryTab">
773
+ <div class="content-area">
774
+ <div class="info" id="welcomeMessage">
775
+ <strong>Welcome to ADB SQLite Query Viewer!</strong><br>
776
+ <b>ADB Bridge (recommended for RN devs):</b>
777
+ <a href="https://github.com/amitwinit/SQLite-DevTools-Mobile-ReactNative/releases/latest/download/adb-bridge.exe" style="color: #8e44ad; font-weight: 600;">Download adb-bridge.exe</a>,
778
+ run it, and this page auto-connects.<br>
779
+ <b>WebUSB:</b> Click "Connect Device" (requires <code>adb kill-server</code> first).<br>
780
+ Select a package and database, then browse tables or write SQL queries.<br>
781
+ <small>WebUSB requires Chrome or Edge. Device must have USB debugging enabled.</small>
782
+ </div>
783
+ <div class="table-wrapper" id="resultsContainer"></div>
784
+ </div>
785
+ <div class="pagination" id="pagination" style="display: none;">
786
+ <div style="display: flex; gap: 10px; align-items: center;">
787
+ <button id="firstBtn">First</button>
788
+ <button id="prevBtn">Previous</button>
789
+ <span id="pageInfo"></span>
790
+ <button id="nextBtn">Next</button>
791
+ <button id="lastBtn">Last</button>
792
+ <span style="margin-left: 20px;">|</span>
793
+ <label style="margin-left: 10px;">Go to page:</label>
794
+ <input type="number" id="gotoPageInput" min="1" style="width: 80px; padding: 4px;">
795
+ <button id="gotoPageBtn">Go</button>
796
+ <span style="margin-left: 20px;">|</span>
797
+ <label style="margin-left: 10px;">Rows per page:</label>
798
+ <select id="limitSelect" style="padding: 4px;">
799
+ <option value="50">50</option>
800
+ <option value="100" selected>100</option>
801
+ <option value="200">200</option>
802
+ <option value="500">500</option>
803
+ <option value="1000">1000</option>
804
+ <option value="all">All</option>
805
+ </select>
806
+ </div>
807
+ </div>
808
+ <div class="status-bar" id="statusBar">Ready</div>
809
+ </div>
810
+
811
+ <div class="tab-content" id="structureTab">
812
+ <div class="content-area">
813
+ <div class="info">Select a table to view its structure</div>
814
+ <div class="table-wrapper" id="structureContainer"></div>
815
+ </div>
816
+ </div>
817
+ </div>
818
+
819
+ </body>
820
+
821
+ </html>