react-native-debug-toolkit 0.2.2 → 0.3.1
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.
- package/index.js +8 -0
- package/lib/features/ConsoleLogFeature.js +1 -1
- package/lib/features/NavigationLogFeature.js +47 -0
- package/lib/features/NetworkFeature.js +1 -1
- package/lib/features/ZustandLogFeature.js +46 -0
- package/lib/hooks/useNavigationLogger.js +92 -0
- package/lib/index.js +16 -2
- package/lib/navigation/NavigationLogger.js +1 -0
- package/lib/utils/DebugConst.js +37 -5
- package/lib/utils/StorageUtils.js +80 -0
- package/lib/views/FloatPanelView.js +127 -10
- package/lib/views/NavigationLogDetails.js +294 -0
- package/lib/views/SubViewNavigationLogs.js +199 -0
- package/lib/views/SubViewZustandLogs.js +279 -0
- package/lib/views/ZustandLogDetails.js +355 -0
- package/package.json +2 -2
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { View, Text, StyleSheet, Clipboard } from 'react-native'
|
|
3
|
+
import { ScrollView, Pressable } from 'react-native'
|
|
4
|
+
import JSONTree from 'react-native-json-tree'
|
|
5
|
+
import { getNavigationActionColor } from '../utils/DebugConst'
|
|
6
|
+
|
|
7
|
+
// Re-using the theme from ConsoleLogDetails for consistency
|
|
8
|
+
const theme = {
|
|
9
|
+
scheme: 'monokai',
|
|
10
|
+
author: 'wimer hazenberg (http://www.monokai.nl)',
|
|
11
|
+
base00: '#272822',
|
|
12
|
+
base01: '#383830',
|
|
13
|
+
base02: '#49483e',
|
|
14
|
+
base03: '#75715e',
|
|
15
|
+
base04: '#a59f85',
|
|
16
|
+
base05: '#f8f8f2',
|
|
17
|
+
base06: '#f5f4f1',
|
|
18
|
+
base07: '#f9f8f5',
|
|
19
|
+
base08: '#f92672',
|
|
20
|
+
base09: '#fd971f',
|
|
21
|
+
base0A: '#f4bf75',
|
|
22
|
+
base0B: '#a6e22e',
|
|
23
|
+
base0C: '#a1efe4',
|
|
24
|
+
base0D: '#66d9ef',
|
|
25
|
+
base0E: '#ae81ff',
|
|
26
|
+
base0F: '#cc6633'
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const CopyButton = ({ text, style }) => {
|
|
30
|
+
const [copied, setCopied] = React.useState(false)
|
|
31
|
+
|
|
32
|
+
const handleCopy = async () => {
|
|
33
|
+
await Clipboard.setString(text)
|
|
34
|
+
setCopied(true)
|
|
35
|
+
setTimeout(() => setCopied(false), 2000)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<Pressable style={[styles.copyButton, style]} onPress={handleCopy}>
|
|
40
|
+
<Text style={styles.copyButtonText}>{copied ? 'Copied!' : 'Copy'}</Text>
|
|
41
|
+
</Pressable>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const CollapsibleSection = ({ title, children, initiallyExpanded = false }) => {
|
|
46
|
+
const [expanded, setExpanded] = React.useState(initiallyExpanded)
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<View style={styles.collapsibleSection}>
|
|
50
|
+
<Pressable
|
|
51
|
+
style={styles.sectionHeader}
|
|
52
|
+
onPress={() => setExpanded(!expanded)}>
|
|
53
|
+
<Text style={styles.sectionTitle}>{title}</Text>
|
|
54
|
+
<Text style={styles.expandIcon}>{expanded ? '▼' : '▶'}</Text>
|
|
55
|
+
</Pressable>
|
|
56
|
+
{expanded && children}
|
|
57
|
+
</View>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Basic JSONValue renderer
|
|
62
|
+
const JSONValue = ({ value }) => {
|
|
63
|
+
if (value === null) {
|
|
64
|
+
return <Text style={styles.jsonNull}>null</Text>
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (value === undefined) {
|
|
68
|
+
return <Text style={styles.jsonNull}>undefined</Text>
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (typeof value === 'boolean') {
|
|
72
|
+
return <Text style={styles.jsonBoolean}>{value.toString()}</Text>
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (typeof value === 'number') {
|
|
76
|
+
return <Text style={styles.jsonNumber}>{value}</Text>
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (typeof value === 'string') {
|
|
80
|
+
return (
|
|
81
|
+
<Text style={styles.jsonString} selectable={true}>
|
|
82
|
+
"{value}"
|
|
83
|
+
</Text>
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (typeof value === 'object') {
|
|
88
|
+
return (
|
|
89
|
+
<JSONTree
|
|
90
|
+
data={value}
|
|
91
|
+
theme={theme}
|
|
92
|
+
invertTheme={true}
|
|
93
|
+
hideRoot={true}
|
|
94
|
+
shouldExpandNode={(keyPath, nodeData, currentLevel) => currentLevel < 1}
|
|
95
|
+
/>
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return <Text style={styles.jsonOther}>{String(value)}</Text>
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const NavigationLogDetails = ({ log }) => {
|
|
103
|
+
if (!log) {
|
|
104
|
+
return (
|
|
105
|
+
<View style={styles.errorContainer}>
|
|
106
|
+
<Text style={styles.errorText}>Navigation log data is missing</Text>
|
|
107
|
+
</View>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const { action, from, to, timestamp, startTime, duration } = log
|
|
112
|
+
const actionColor = getNavigationActionColor(action)
|
|
113
|
+
|
|
114
|
+
// Format the log data for text display and copying
|
|
115
|
+
const formatLogForCopy = () => {
|
|
116
|
+
try {
|
|
117
|
+
return `Navigation: ${action}
|
|
118
|
+
From: ${JSON.stringify(from, null, 2)}
|
|
119
|
+
To: ${JSON.stringify(to, null, 2)}
|
|
120
|
+
Time: ${timestamp ? new Date(timestamp).toLocaleString() : 'Unknown'}
|
|
121
|
+
Duration: ${duration || 'N/A'} ms`;
|
|
122
|
+
} catch (e) {
|
|
123
|
+
return 'Failed to format navigation log';
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<ScrollView
|
|
129
|
+
style={styles.container}
|
|
130
|
+
contentContainerStyle={styles.contentContainer}
|
|
131
|
+
showsVerticalScrollIndicator={true}
|
|
132
|
+
scrollEventThrottle={16}
|
|
133
|
+
keyboardShouldPersistTaps='handled'>
|
|
134
|
+
|
|
135
|
+
<View style={styles.header}>
|
|
136
|
+
<View style={styles.headerInfo}>
|
|
137
|
+
<Text style={[styles.actionIndicator, { color: actionColor }]}>
|
|
138
|
+
{action?.toUpperCase() || 'UNKNOWN'}
|
|
139
|
+
</Text>
|
|
140
|
+
<Text style={styles.timestamp}>
|
|
141
|
+
{timestamp
|
|
142
|
+
? new Date(timestamp).toLocaleString()
|
|
143
|
+
: 'Unknown time'}
|
|
144
|
+
</Text>
|
|
145
|
+
{duration && (
|
|
146
|
+
<Text style={styles.duration}>
|
|
147
|
+
{`${duration} ms`}
|
|
148
|
+
</Text>
|
|
149
|
+
)}
|
|
150
|
+
</View>
|
|
151
|
+
<CopyButton text={formatLogForCopy()} />
|
|
152
|
+
</View>
|
|
153
|
+
|
|
154
|
+
<CollapsibleSection title='From Route' initiallyExpanded={true}>
|
|
155
|
+
<View style={styles.dataContentWrapper}>
|
|
156
|
+
<View style={styles.dataContent}>
|
|
157
|
+
<JSONValue value={from} />
|
|
158
|
+
</View>
|
|
159
|
+
</View>
|
|
160
|
+
</CollapsibleSection>
|
|
161
|
+
|
|
162
|
+
<CollapsibleSection title='To Route' initiallyExpanded={true}>
|
|
163
|
+
<View style={styles.dataContentWrapper}>
|
|
164
|
+
<View style={styles.dataContent}>
|
|
165
|
+
<JSONValue value={to} />
|
|
166
|
+
</View>
|
|
167
|
+
</View>
|
|
168
|
+
</CollapsibleSection>
|
|
169
|
+
|
|
170
|
+
</ScrollView>
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Styles adapted from ConsoleLogDetails
|
|
175
|
+
const styles = StyleSheet.create({
|
|
176
|
+
container: {
|
|
177
|
+
flex: 1,
|
|
178
|
+
backgroundColor: '#fff',
|
|
179
|
+
},
|
|
180
|
+
contentContainer: {
|
|
181
|
+
paddingBottom: 20,
|
|
182
|
+
},
|
|
183
|
+
header: {
|
|
184
|
+
flexDirection: 'row',
|
|
185
|
+
padding: 15,
|
|
186
|
+
borderBottomWidth: 1,
|
|
187
|
+
borderBottomColor: '#eee',
|
|
188
|
+
alignItems: 'center',
|
|
189
|
+
justifyContent: 'space-between',
|
|
190
|
+
},
|
|
191
|
+
headerInfo: {
|
|
192
|
+
flexShrink: 1,
|
|
193
|
+
marginRight: 10,
|
|
194
|
+
},
|
|
195
|
+
actionIndicator: {
|
|
196
|
+
fontSize: 14,
|
|
197
|
+
fontWeight: 'bold',
|
|
198
|
+
marginBottom: 4,
|
|
199
|
+
},
|
|
200
|
+
timestamp: {
|
|
201
|
+
fontSize: 13,
|
|
202
|
+
color: '#666',
|
|
203
|
+
marginBottom: 2,
|
|
204
|
+
},
|
|
205
|
+
duration: {
|
|
206
|
+
fontSize: 12,
|
|
207
|
+
color: '#888',
|
|
208
|
+
},
|
|
209
|
+
collapsibleSection: {
|
|
210
|
+
marginBottom: 1,
|
|
211
|
+
backgroundColor: '#fff',
|
|
212
|
+
},
|
|
213
|
+
sectionHeader: {
|
|
214
|
+
flexDirection: 'row',
|
|
215
|
+
justifyContent: 'space-between',
|
|
216
|
+
alignItems: 'center',
|
|
217
|
+
padding: 15,
|
|
218
|
+
backgroundColor: '#f5f5f5',
|
|
219
|
+
},
|
|
220
|
+
sectionTitle: {
|
|
221
|
+
fontSize: 15,
|
|
222
|
+
fontWeight: 'bold',
|
|
223
|
+
color: '#333',
|
|
224
|
+
},
|
|
225
|
+
expandIcon: {
|
|
226
|
+
fontSize: 14,
|
|
227
|
+
color: '#666',
|
|
228
|
+
},
|
|
229
|
+
content: {
|
|
230
|
+
padding: 15,
|
|
231
|
+
},
|
|
232
|
+
dataContentWrapper: {
|
|
233
|
+
flex: 1,
|
|
234
|
+
padding: 10,
|
|
235
|
+
},
|
|
236
|
+
dataContent: {
|
|
237
|
+
backgroundColor: '#f8f9fa',
|
|
238
|
+
padding: 10,
|
|
239
|
+
borderRadius: 4,
|
|
240
|
+
borderWidth: 1,
|
|
241
|
+
borderColor: '#e9ecef',
|
|
242
|
+
},
|
|
243
|
+
errorContainer: {
|
|
244
|
+
flex: 1,
|
|
245
|
+
justifyContent: 'center',
|
|
246
|
+
alignItems: 'center',
|
|
247
|
+
padding: 20,
|
|
248
|
+
},
|
|
249
|
+
errorText: {
|
|
250
|
+
color: '#ff4444',
|
|
251
|
+
fontSize: 16,
|
|
252
|
+
},
|
|
253
|
+
copyButton: {
|
|
254
|
+
backgroundColor: '#e9ecef',
|
|
255
|
+
paddingHorizontal: 10,
|
|
256
|
+
paddingVertical: 5,
|
|
257
|
+
borderRadius: 4,
|
|
258
|
+
flexShrink: 0,
|
|
259
|
+
},
|
|
260
|
+
copyButtonText: {
|
|
261
|
+
fontSize: 12,
|
|
262
|
+
color: '#666',
|
|
263
|
+
},
|
|
264
|
+
// JSON Value Styles (reused from ConsoleLogDetails)
|
|
265
|
+
jsonString: {
|
|
266
|
+
color: '#CB772F',
|
|
267
|
+
fontFamily: 'monospace',
|
|
268
|
+
fontSize: 13,
|
|
269
|
+
},
|
|
270
|
+
jsonNumber: {
|
|
271
|
+
color: '#AE81FF',
|
|
272
|
+
fontFamily: 'monospace',
|
|
273
|
+
fontSize: 13,
|
|
274
|
+
},
|
|
275
|
+
jsonBoolean: {
|
|
276
|
+
color: '#66D9EF',
|
|
277
|
+
fontWeight: 'bold',
|
|
278
|
+
fontFamily: 'monospace',
|
|
279
|
+
fontSize: 13,
|
|
280
|
+
},
|
|
281
|
+
jsonNull: {
|
|
282
|
+
color: '#F92672',
|
|
283
|
+
fontStyle: 'italic',
|
|
284
|
+
fontFamily: 'monospace',
|
|
285
|
+
fontSize: 13,
|
|
286
|
+
},
|
|
287
|
+
jsonOther: {
|
|
288
|
+
color: '#75715e',
|
|
289
|
+
fontFamily: 'monospace',
|
|
290
|
+
fontSize: 13,
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
export default NavigationLogDetails
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import React, { useState, useMemo } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
Text,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
FlatList,
|
|
7
|
+
TouchableOpacity,
|
|
8
|
+
} from 'react-native'
|
|
9
|
+
import NavigationLogDetails from './NavigationLogDetails'
|
|
10
|
+
import { getNavigationActionColor } from '../utils/DebugConst'
|
|
11
|
+
|
|
12
|
+
const SubViewNavigationLogs = ({ logs = [] }) => {
|
|
13
|
+
const [selectedLog, setSelectedLog] = useState(null)
|
|
14
|
+
|
|
15
|
+
// Memoize the sorted logs
|
|
16
|
+
const sortedLogs = useMemo(() => {
|
|
17
|
+
// Create a stable copy before sorting if FlatList relies on reference equality
|
|
18
|
+
return [...logs].sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0));
|
|
19
|
+
}, [logs]);
|
|
20
|
+
|
|
21
|
+
// Helper to format navigation data for preview
|
|
22
|
+
const formatNavigationPreview = (action, from, to) => {
|
|
23
|
+
const fromName = from?.name || 'Unknown';
|
|
24
|
+
const toName = to?.name || 'Unknown';
|
|
25
|
+
|
|
26
|
+
let preview = `${action || 'Navigate'}: ${fromName} → ${toName}`;
|
|
27
|
+
|
|
28
|
+
// Add params summary if available
|
|
29
|
+
if (to?.params) {
|
|
30
|
+
try {
|
|
31
|
+
const paramsStr = JSON.stringify(to.params);
|
|
32
|
+
const shortParams = paramsStr.length > 30 ? paramsStr.substring(0, 27) + '...' : paramsStr;
|
|
33
|
+
preview += ` ${shortParams}`;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
preview += ' [with params]';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return preview;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const renderLogItem = ({ item }) => {
|
|
43
|
+
const action = item.action || 'navigate';
|
|
44
|
+
const actionColor = getNavigationActionColor(action);
|
|
45
|
+
const previewText = formatNavigationPreview(action, item.from, item.to);
|
|
46
|
+
const timestamp = item.timestamp
|
|
47
|
+
? new Date(item.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false })
|
|
48
|
+
: '';
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<TouchableOpacity
|
|
52
|
+
style={styles.logItem}
|
|
53
|
+
onPress={() => setSelectedLog(item)}>
|
|
54
|
+
<View style={styles.logItemContainer}>
|
|
55
|
+
<View
|
|
56
|
+
style={[styles.actionIndicator, { backgroundColor: actionColor }]}
|
|
57
|
+
/>
|
|
58
|
+
|
|
59
|
+
<View style={styles.logContent}>
|
|
60
|
+
<View style={styles.logHeader}>
|
|
61
|
+
<Text style={[styles.actionText, { color: actionColor }]}>
|
|
62
|
+
{action.toUpperCase()}
|
|
63
|
+
</Text>
|
|
64
|
+
<Text style={styles.time}>{timestamp}</Text>
|
|
65
|
+
</View>
|
|
66
|
+
|
|
67
|
+
<Text style={styles.logMessage} numberOfLines={2}>
|
|
68
|
+
{previewText}
|
|
69
|
+
</Text>
|
|
70
|
+
|
|
71
|
+
{item.duration && (
|
|
72
|
+
<Text style={styles.duration}>{`${item.duration} ms`}</Text>
|
|
73
|
+
)}
|
|
74
|
+
</View>
|
|
75
|
+
</View>
|
|
76
|
+
</TouchableOpacity>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// If a log is selected, show the details view
|
|
81
|
+
if (selectedLog) {
|
|
82
|
+
return (
|
|
83
|
+
<View style={styles.container}>
|
|
84
|
+
<View style={styles.detailsHeader}>
|
|
85
|
+
<TouchableOpacity
|
|
86
|
+
style={styles.backButton}
|
|
87
|
+
onPress={() => setSelectedLog(null)}>
|
|
88
|
+
<Text style={styles.backButtonText}>← Back</Text>
|
|
89
|
+
</TouchableOpacity>
|
|
90
|
+
<Text style={styles.headerTitle}>Navigation Details</Text>
|
|
91
|
+
</View>
|
|
92
|
+
<NavigationLogDetails log={selectedLog} />
|
|
93
|
+
</View>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Otherwise show the list view
|
|
98
|
+
return (
|
|
99
|
+
<View style={styles.container}>
|
|
100
|
+
{sortedLogs.length === 0 ? (
|
|
101
|
+
<Text style={styles.emptyText}>No navigation events logged yet</Text>
|
|
102
|
+
) : (
|
|
103
|
+
<FlatList
|
|
104
|
+
data={sortedLogs}
|
|
105
|
+
renderItem={renderLogItem}
|
|
106
|
+
keyExtractor={(item, index) => `${item.timestamp}-${index}`}
|
|
107
|
+
style={styles.list}
|
|
108
|
+
/>
|
|
109
|
+
)}
|
|
110
|
+
</View>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Adapted styles from SubViewConsoleLogs
|
|
115
|
+
const styles = StyleSheet.create({
|
|
116
|
+
container: {
|
|
117
|
+
flex: 1,
|
|
118
|
+
backgroundColor: '#fff',
|
|
119
|
+
},
|
|
120
|
+
list: {
|
|
121
|
+
flex: 1,
|
|
122
|
+
},
|
|
123
|
+
emptyText: {
|
|
124
|
+
textAlign: 'center',
|
|
125
|
+
color: '#999',
|
|
126
|
+
marginTop: 20,
|
|
127
|
+
},
|
|
128
|
+
logItem: {
|
|
129
|
+
borderBottomWidth: 1,
|
|
130
|
+
borderBottomColor: '#eee',
|
|
131
|
+
},
|
|
132
|
+
logItemContainer: {
|
|
133
|
+
flexDirection: 'row',
|
|
134
|
+
paddingVertical: 10,
|
|
135
|
+
paddingHorizontal: 12,
|
|
136
|
+
},
|
|
137
|
+
actionIndicator: {
|
|
138
|
+
width: 4,
|
|
139
|
+
borderRadius: 2,
|
|
140
|
+
marginRight: 10,
|
|
141
|
+
},
|
|
142
|
+
logContent: {
|
|
143
|
+
flex: 1,
|
|
144
|
+
},
|
|
145
|
+
logHeader: {
|
|
146
|
+
flexDirection: 'row',
|
|
147
|
+
justifyContent: 'space-between',
|
|
148
|
+
alignItems: 'center',
|
|
149
|
+
marginBottom: 5,
|
|
150
|
+
},
|
|
151
|
+
actionText: {
|
|
152
|
+
fontSize: 13,
|
|
153
|
+
fontWeight: 'bold',
|
|
154
|
+
},
|
|
155
|
+
time: {
|
|
156
|
+
fontSize: 12,
|
|
157
|
+
color: '#888',
|
|
158
|
+
},
|
|
159
|
+
logMessage: {
|
|
160
|
+
fontSize: 14,
|
|
161
|
+
color: '#333',
|
|
162
|
+
lineHeight: 18,
|
|
163
|
+
fontFamily: 'monospace',
|
|
164
|
+
},
|
|
165
|
+
duration: {
|
|
166
|
+
fontSize: 12,
|
|
167
|
+
color: '#888',
|
|
168
|
+
marginTop: 4,
|
|
169
|
+
},
|
|
170
|
+
// Details Header Styles
|
|
171
|
+
detailsHeader: {
|
|
172
|
+
flexDirection: 'row',
|
|
173
|
+
alignItems: 'center',
|
|
174
|
+
paddingVertical: 10,
|
|
175
|
+
paddingHorizontal: 15,
|
|
176
|
+
borderBottomWidth: 1,
|
|
177
|
+
borderBottomColor: '#eee',
|
|
178
|
+
backgroundColor: '#f8f9fa',
|
|
179
|
+
},
|
|
180
|
+
backButton: {
|
|
181
|
+
paddingHorizontal: 10,
|
|
182
|
+
paddingVertical: 5,
|
|
183
|
+
borderRadius: 4,
|
|
184
|
+
backgroundColor: '#eee',
|
|
185
|
+
marginRight: 15,
|
|
186
|
+
},
|
|
187
|
+
backButtonText: {
|
|
188
|
+
color: '#333',
|
|
189
|
+
fontWeight: '500',
|
|
190
|
+
fontSize: 14,
|
|
191
|
+
},
|
|
192
|
+
headerTitle: {
|
|
193
|
+
fontSize: 16,
|
|
194
|
+
fontWeight: 'bold',
|
|
195
|
+
color: '#333',
|
|
196
|
+
},
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
export default SubViewNavigationLogs
|