@webority/mobile-support 0.0.12 → 0.1.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.
- package/lib/commonjs/SupportProvider.js +1 -335
- package/lib/commonjs/client.js +1 -164
- package/lib/commonjs/clipboard.js +1 -10
- package/lib/commonjs/components/Attachments.js +1 -246
- package/lib/commonjs/components/NewSupportTicket.js +1 -210
- package/lib/commonjs/components/PhotoTray.js +1 -141
- package/lib/commonjs/components/SupportContact.js +1 -134
- package/lib/commonjs/components/SupportTicketDetail.js +1 -348
- package/lib/commonjs/components/SupportTicketList.js +1 -279
- package/lib/commonjs/device.js +1 -29
- package/lib/commonjs/files.js +1 -37
- package/lib/commonjs/format.js +1 -29
- package/lib/commonjs/index.js +1 -97
- package/lib/commonjs/photos.js +1 -67
- package/lib/commonjs/report/ReportIssueButton.js +1 -57
- package/lib/commonjs/report/captureAndReport.js +1 -34
- package/lib/commonjs/report/index.js +1 -20
- package/lib/commonjs/share/index.js +1 -44
- package/lib/commonjs/types.js +1 -2
- package/lib/commonjs/validation.js +1 -45
- package/lib/module/SupportProvider.js +1 -323
- package/lib/module/client.js +1 -156
- package/lib/module/clipboard.js +1 -5
- package/lib/module/components/Attachments.js +1 -240
- package/lib/module/components/NewSupportTicket.js +1 -205
- package/lib/module/components/PhotoTray.js +1 -136
- package/lib/module/components/SupportContact.js +1 -129
- package/lib/module/components/SupportTicketDetail.js +1 -343
- package/lib/module/components/SupportTicketList.js +1 -273
- package/lib/module/device.js +1 -24
- package/lib/module/files.js +1 -31
- package/lib/module/format.js +1 -23
- package/lib/module/index.js +1 -10
- package/lib/module/photos.js +1 -61
- package/lib/module/report/ReportIssueButton.js +1 -52
- package/lib/module/report/captureAndReport.js +1 -29
- package/lib/module/report/index.js +1 -12
- package/lib/module/share/index.js +1 -37
- package/lib/module/types.js +0 -2
- package/lib/module/validation.js +1 -38
- package/lib/typescript/commonjs/SupportProvider.d.ts +4 -0
- package/lib/typescript/commonjs/client.d.ts +0 -1
- package/lib/typescript/commonjs/format.d.ts +6 -4
- package/lib/typescript/module/SupportProvider.d.ts +4 -0
- package/lib/typescript/module/client.d.ts +0 -1
- package/lib/typescript/module/format.d.ts +6 -4
- package/package.json +8 -6
|
@@ -1,279 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.statusFilterOptions = exports.SupportTicketList = exports.STATUS_TONES = void 0;
|
|
7
|
-
var _mobileUi = require("@webority/mobile-ui");
|
|
8
|
-
var _react = require("react");
|
|
9
|
-
var _reactNative = require("react-native");
|
|
10
|
-
var _format = require("../format.js");
|
|
11
|
-
var _SupportProvider = require("../SupportProvider.js");
|
|
12
|
-
var _jsxRuntime = require("react/jsx-runtime");
|
|
13
|
-
const STATUS_TONES = exports.STATUS_TONES = {
|
|
14
|
-
Open: 'warning',
|
|
15
|
-
InProgress: 'info',
|
|
16
|
-
Resolved: 'success',
|
|
17
|
-
Closed: 'neutral'
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
// The counts endpoint carries numbers only, so the chip wording lives here. It
|
|
21
|
-
// matches the server's own labels (Webority.Support SupportDisplay).
|
|
22
|
-
const STATUS_FILTERS = [{
|
|
23
|
-
value: 'Open',
|
|
24
|
-
label: 'Open',
|
|
25
|
-
count: 'open'
|
|
26
|
-
}, {
|
|
27
|
-
value: 'InProgress',
|
|
28
|
-
label: 'In progress',
|
|
29
|
-
count: 'inProgress'
|
|
30
|
-
}, {
|
|
31
|
-
value: 'Resolved',
|
|
32
|
-
label: 'Resolved',
|
|
33
|
-
count: 'resolved'
|
|
34
|
-
}, {
|
|
35
|
-
value: 'Closed',
|
|
36
|
-
label: 'Closed',
|
|
37
|
-
count: 'closed'
|
|
38
|
-
}];
|
|
39
|
-
const ALL = 'all';
|
|
40
|
-
/**
|
|
41
|
-
* All, then each status that has tickets. The selected status stays even at
|
|
42
|
-
* zero, so the chip the person is on never vanishes under them.
|
|
43
|
-
*/
|
|
44
|
-
const statusFilterOptions = (counts, selected) => [{
|
|
45
|
-
value: ALL,
|
|
46
|
-
label: 'All',
|
|
47
|
-
count: counts.total
|
|
48
|
-
}, ...STATUS_FILTERS.filter(s => counts[s.count] > 0 || s.value === selected).map(s => ({
|
|
49
|
-
value: s.value,
|
|
50
|
-
label: s.label,
|
|
51
|
-
count: counts[s.count]
|
|
52
|
-
}))];
|
|
53
|
-
exports.statusFilterOptions = statusFilterOptions;
|
|
54
|
-
const SEARCH_DEBOUNCE_MS = 400;
|
|
55
|
-
const SupportTicketList = ({
|
|
56
|
-
onOpenTicket,
|
|
57
|
-
onNewTicket,
|
|
58
|
-
header,
|
|
59
|
-
pageSize,
|
|
60
|
-
testID = 'support-ticket-list'
|
|
61
|
-
}) => {
|
|
62
|
-
const theme = (0, _mobileUi.useTheme)();
|
|
63
|
-
const styles = (0, _react.useMemo)(() => buildStyles(theme), [theme]);
|
|
64
|
-
const {
|
|
65
|
-
tickets,
|
|
66
|
-
counts,
|
|
67
|
-
status,
|
|
68
|
-
search,
|
|
69
|
-
setStatus,
|
|
70
|
-
setSearch,
|
|
71
|
-
loading,
|
|
72
|
-
refreshing,
|
|
73
|
-
loadingMore,
|
|
74
|
-
error,
|
|
75
|
-
loadMoreError,
|
|
76
|
-
refresh,
|
|
77
|
-
loadMore
|
|
78
|
-
} = (0, _SupportProvider.useSupportTickets)({
|
|
79
|
-
pageSize
|
|
80
|
-
});
|
|
81
|
-
const hasAnyTicket = (counts?.total ?? 0) > 0;
|
|
82
|
-
const filtered = status !== null || search.trim() !== '';
|
|
83
|
-
const listHeader = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
84
|
-
style: styles.header,
|
|
85
|
-
children: [header, onNewTicket && /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Button, {
|
|
86
|
-
title: "New ticket",
|
|
87
|
-
leftIcon: "add",
|
|
88
|
-
onPress: onNewTicket,
|
|
89
|
-
fullWidth: true
|
|
90
|
-
}), error && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
91
|
-
style: styles.error,
|
|
92
|
-
accessibilityLiveRegion: "polite",
|
|
93
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Text, {
|
|
94
|
-
variant: "bodySmall",
|
|
95
|
-
color: "error",
|
|
96
|
-
children: error.message
|
|
97
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Button, {
|
|
98
|
-
title: "Try again",
|
|
99
|
-
size: "sm",
|
|
100
|
-
variant: "ghost",
|
|
101
|
-
onPress: () => void refresh()
|
|
102
|
-
})]
|
|
103
|
-
}), counts && hasAnyTicket && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
104
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.SearchBar, {
|
|
105
|
-
value: search,
|
|
106
|
-
onChangeText: setSearch,
|
|
107
|
-
debounceMs: SEARCH_DEBOUNCE_MS,
|
|
108
|
-
placeholder: "Search by subject or ticket number",
|
|
109
|
-
accessibilityLabel: "Search tickets",
|
|
110
|
-
testID: "support-ticket-search"
|
|
111
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
|
|
112
|
-
horizontal: true,
|
|
113
|
-
showsHorizontalScrollIndicator: false,
|
|
114
|
-
contentContainerStyle: styles.filters,
|
|
115
|
-
accessibilityRole: "tablist",
|
|
116
|
-
accessibilityLabel: "Filter by status",
|
|
117
|
-
children: statusFilterOptions(counts, status).map(o => /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Chip, {
|
|
118
|
-
label: `${o.label} (${o.count})`,
|
|
119
|
-
selected: (status ?? ALL) === o.value,
|
|
120
|
-
onPress: () => setStatus(o.value === ALL ? null : o.value),
|
|
121
|
-
accessibilityLabel: `${o.label}, ${o.count} tickets`,
|
|
122
|
-
testID: `support-filter-${o.value}`
|
|
123
|
-
}, o.value))
|
|
124
|
-
})]
|
|
125
|
-
})]
|
|
126
|
-
});
|
|
127
|
-
if (loading && counts === null && !error) {
|
|
128
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
129
|
-
style: styles.center,
|
|
130
|
-
testID: testID,
|
|
131
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Spinner, {
|
|
132
|
-
accessibilityLabel: "Loading your tickets"
|
|
133
|
-
})
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
const empty = () => {
|
|
137
|
-
if (loading) {
|
|
138
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
139
|
-
style: styles.footer,
|
|
140
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Spinner, {
|
|
141
|
-
accessibilityLabel: "Loading your tickets"
|
|
142
|
-
})
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
if (error) {
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
if (!hasAnyTicket) {
|
|
149
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.EmptyState, {
|
|
150
|
-
title: "No tickets yet",
|
|
151
|
-
description: "Raise a ticket and it will show here with its status.",
|
|
152
|
-
action: onNewTicket ? {
|
|
153
|
-
label: 'New ticket',
|
|
154
|
-
onPress: onNewTicket
|
|
155
|
-
} : undefined
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.EmptyState, {
|
|
159
|
-
title: "No tickets match",
|
|
160
|
-
description: filtered ? 'Try another status or search.' : undefined
|
|
161
|
-
});
|
|
162
|
-
};
|
|
163
|
-
const footer = loadingMore ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
164
|
-
style: styles.footer,
|
|
165
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Spinner, {
|
|
166
|
-
size: "sm",
|
|
167
|
-
accessibilityLabel: "Loading more tickets"
|
|
168
|
-
})
|
|
169
|
-
}) : loadMoreError ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
170
|
-
style: [styles.footer, styles.error],
|
|
171
|
-
accessibilityLiveRegion: "polite",
|
|
172
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Text, {
|
|
173
|
-
variant: "bodySmall",
|
|
174
|
-
color: "error",
|
|
175
|
-
children: loadMoreError.message
|
|
176
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Button, {
|
|
177
|
-
title: "Load more",
|
|
178
|
-
size: "sm",
|
|
179
|
-
variant: "ghost",
|
|
180
|
-
onPress: () => void loadMore()
|
|
181
|
-
})]
|
|
182
|
-
}) : null;
|
|
183
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
|
|
184
|
-
testID: testID,
|
|
185
|
-
data: tickets,
|
|
186
|
-
keyExtractor: t => t.id,
|
|
187
|
-
contentContainerStyle: styles.content,
|
|
188
|
-
ListHeaderComponent: listHeader,
|
|
189
|
-
ListFooterComponent: footer,
|
|
190
|
-
onEndReached: () => void loadMore(),
|
|
191
|
-
onEndReachedThreshold: 0.5,
|
|
192
|
-
refreshControl: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.RefreshControl, {
|
|
193
|
-
refreshing: refreshing,
|
|
194
|
-
onRefresh: () => void refresh()
|
|
195
|
-
}),
|
|
196
|
-
ListEmptyComponent: empty(),
|
|
197
|
-
renderItem: ({
|
|
198
|
-
item
|
|
199
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_mobileUi.Card, {
|
|
200
|
-
onPress: () => onOpenTicket(item),
|
|
201
|
-
accessibilityLabel: `${item.subject}, ${item.statusLabel}, ticket ${item.number}`,
|
|
202
|
-
bodyStyle: styles.card,
|
|
203
|
-
testID: `support-ticket-${item.id}`,
|
|
204
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
205
|
-
style: styles.cardTop,
|
|
206
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Text, {
|
|
207
|
-
variant: "caption",
|
|
208
|
-
color: "tertiary",
|
|
209
|
-
children: item.number
|
|
210
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.StatusBadge, {
|
|
211
|
-
label: item.statusLabel,
|
|
212
|
-
tone: STATUS_TONES[item.status] ?? 'neutral',
|
|
213
|
-
size: "sm"
|
|
214
|
-
})]
|
|
215
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Text, {
|
|
216
|
-
variant: "title",
|
|
217
|
-
numberOfLines: 2,
|
|
218
|
-
children: item.subject
|
|
219
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Text, {
|
|
220
|
-
variant: "bodySmall",
|
|
221
|
-
color: "secondary",
|
|
222
|
-
children: item.category
|
|
223
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
224
|
-
style: styles.cardBottom,
|
|
225
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Text, {
|
|
226
|
-
variant: "caption",
|
|
227
|
-
color: "tertiary",
|
|
228
|
-
children: `Updated ${(0, _format.formatWhen)(item.updatedDateTimeUtc)}`
|
|
229
|
-
}), item.awaitingCustomer && /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Text, {
|
|
230
|
-
variant: "caption",
|
|
231
|
-
color: "warning",
|
|
232
|
-
children: "Waiting for your reply"
|
|
233
|
-
})]
|
|
234
|
-
})]
|
|
235
|
-
})
|
|
236
|
-
});
|
|
237
|
-
};
|
|
238
|
-
exports.SupportTicketList = SupportTicketList;
|
|
239
|
-
const buildStyles = theme => _reactNative.StyleSheet.create({
|
|
240
|
-
content: {
|
|
241
|
-
padding: theme.spacing.md,
|
|
242
|
-
gap: theme.spacing.sm
|
|
243
|
-
},
|
|
244
|
-
header: {
|
|
245
|
-
gap: theme.spacing.sm,
|
|
246
|
-
marginBottom: theme.spacing.xs
|
|
247
|
-
},
|
|
248
|
-
filters: {
|
|
249
|
-
gap: theme.spacing.xs
|
|
250
|
-
},
|
|
251
|
-
error: {
|
|
252
|
-
gap: theme.spacing.xs,
|
|
253
|
-
alignItems: 'flex-start'
|
|
254
|
-
},
|
|
255
|
-
center: {
|
|
256
|
-
flex: 1,
|
|
257
|
-
alignItems: 'center',
|
|
258
|
-
justifyContent: 'center',
|
|
259
|
-
padding: theme.spacing.xl
|
|
260
|
-
},
|
|
261
|
-
footer: {
|
|
262
|
-
paddingVertical: theme.spacing.md,
|
|
263
|
-
alignItems: 'center'
|
|
264
|
-
},
|
|
265
|
-
card: {
|
|
266
|
-
gap: theme.spacing.xxs
|
|
267
|
-
},
|
|
268
|
-
cardTop: {
|
|
269
|
-
flexDirection: 'row',
|
|
270
|
-
justifyContent: 'space-between',
|
|
271
|
-
alignItems: 'center'
|
|
272
|
-
},
|
|
273
|
-
cardBottom: {
|
|
274
|
-
flexDirection: 'row',
|
|
275
|
-
justifyContent: 'space-between',
|
|
276
|
-
marginTop: theme.spacing.xxs
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
//# sourceMappingURL=SupportTicketList.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.statusFilterOptions=exports.SupportTicketList=exports.STATUS_TONES=void 0;var _mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_format=require("../format.js"),_SupportProvider=require("../SupportProvider.js"),_jsxRuntime=require("react/jsx-runtime");const STATUS_TONES=exports.STATUS_TONES={Open:"warning",InProgress:"info",Resolved:"success",Closed:"neutral"},STATUS_FILTERS=[{value:"Open",label:"Open",count:"open"},{value:"InProgress",label:"In progress",count:"inProgress"},{value:"Resolved",label:"Resolved",count:"resolved"},{value:"Closed",label:"Closed",count:"closed"}],ALL="all",statusFilterOptions=(e,t)=>[{value:ALL,label:"All",count:e.total},...STATUS_FILTERS.filter(i=>e[i.count]>0||i.value===t).map(t=>({value:t.value,label:t.label,count:e[t.count]}))];exports.statusFilterOptions=statusFilterOptions;const SEARCH_DEBOUNCE_MS=400,SupportTicketList=({onOpenTicket:e,onNewTicket:t,header:i,pageSize:s,testID:r="support-ticket-list"})=>{const o=(0,_mobileUi.useTheme)(),a=(0,_react.useMemo)(()=>buildStyles(o),[o]),{tickets:n,counts:l,status:c,search:u,setStatus:m,setSearch:p,loading:d,refreshing:x,loadingMore:_,error:b,loadMoreError:j,refresh:S,loadMore:h}=(0,_SupportProvider.useSupportTickets)({pageSize:s}),g=(0,_SupportProvider.useSupportTimeZone)(),v=(l?.total??0)>0,y=null!==c||""!==u.trim(),R=(0,_jsxRuntime.jsxs)(_reactNative.View,{style:a.header,children:[i,t&&(0,_jsxRuntime.jsx)(_mobileUi.Button,{title:"New ticket",leftIcon:"add",onPress:t,fullWidth:!0}),b&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:a.error,accessibilityLiveRegion:"polite",children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"error",children:b.message}),(0,_jsxRuntime.jsx)(_mobileUi.Button,{title:"Try again",size:"sm",variant:"ghost",onPress:()=>{S()}})]}),l&&v&&(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_mobileUi.SearchBar,{value:u,onChangeText:p,debounceMs:400,placeholder:"Search by subject or ticket number",accessibilityLabel:"Search tickets",testID:"support-ticket-search"}),(0,_jsxRuntime.jsx)(_reactNative.ScrollView,{horizontal:!0,showsHorizontalScrollIndicator:!1,contentContainerStyle:a.filters,accessibilityRole:"tablist",accessibilityLabel:"Filter by status",children:statusFilterOptions(l,c).map(e=>(0,_jsxRuntime.jsx)(_mobileUi.Chip,{label:`${e.label} (${e.count})`,selected:(c??ALL)===e.value,onPress:()=>m(e.value===ALL?null:e.value),accessibilityLabel:`${e.label}, ${e.count} tickets`,testID:`support-filter-${e.value}`},e.value))})]})]});if(d&&null===l&&!b)return(0,_jsxRuntime.jsx)(_reactNative.View,{style:a.center,testID:r,children:(0,_jsxRuntime.jsx)(_mobileUi.Spinner,{accessibilityLabel:"Loading your tickets"})});const T=_?(0,_jsxRuntime.jsx)(_reactNative.View,{style:a.footer,children:(0,_jsxRuntime.jsx)(_mobileUi.Spinner,{size:"sm",accessibilityLabel:"Loading more tickets"})}):j?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:[a.footer,a.error],accessibilityLiveRegion:"polite",children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"error",children:j.message}),(0,_jsxRuntime.jsx)(_mobileUi.Button,{title:"Load more",size:"sm",variant:"ghost",onPress:()=>{h()}})]}):null;return(0,_jsxRuntime.jsx)(_reactNative.FlatList,{testID:r,data:n,keyExtractor:e=>e.id,contentContainerStyle:a.content,ListHeaderComponent:R,ListFooterComponent:T,onEndReached:()=>{h()},onEndReachedThreshold:.5,refreshControl:(0,_jsxRuntime.jsx)(_reactNative.RefreshControl,{refreshing:x,onRefresh:()=>{S()}}),ListEmptyComponent:d?(0,_jsxRuntime.jsx)(_reactNative.View,{style:a.footer,children:(0,_jsxRuntime.jsx)(_mobileUi.Spinner,{accessibilityLabel:"Loading your tickets"})}):b?null:v?(0,_jsxRuntime.jsx)(_mobileUi.EmptyState,{title:"No tickets match",description:y?"Try another status or search.":void 0}):(0,_jsxRuntime.jsx)(_mobileUi.EmptyState,{title:"No tickets yet",description:"Raise a ticket and it will show here with its status.",action:t?{label:"New ticket",onPress:t}:void 0}),renderItem:({item:t})=>(0,_jsxRuntime.jsxs)(_mobileUi.Card,{onPress:()=>e(t),accessibilityLabel:`${t.subject}, ${t.statusLabel}, ticket ${t.number}`,bodyStyle:a.card,testID:`support-ticket-${t.id}`,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:a.cardTop,children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"tertiary",children:t.number}),(0,_jsxRuntime.jsx)(_mobileUi.StatusBadge,{label:t.statusLabel,tone:STATUS_TONES[t.status]??"neutral",size:"sm"})]}),(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"title",numberOfLines:2,children:t.subject}),(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"secondary",children:t.category}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:a.cardBottom,children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"tertiary",children:`Updated ${(0,_format.formatWhen)(t.updatedDateTimeUtc,g)}`}),t.awaitingCustomer&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"warning",children:"Waiting for your reply"})]})]})})};exports.SupportTicketList=SupportTicketList;const buildStyles=e=>_reactNative.StyleSheet.create({content:{padding:e.spacing.md,gap:e.spacing.sm},header:{gap:e.spacing.sm,marginBottom:e.spacing.xs},filters:{gap:e.spacing.xs},error:{gap:e.spacing.xs,alignItems:"flex-start"},center:{flex:1,alignItems:"center",justifyContent:"center",padding:e.spacing.xl},footer:{paddingVertical:e.spacing.md,alignItems:"center"},card:{gap:e.spacing.xxs},cardTop:{flexDirection:"row",justifyContent:"space-between",alignItems:"center"},cardBottom:{flexDirection:"row",justifyContent:"space-between",marginTop:e.spacing.xxs}});
|
package/lib/commonjs/device.js
CHANGED
|
@@ -1,29 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.describeDevice = void 0;
|
|
7
|
-
var _mobileCore = require("@webority/mobile-core");
|
|
8
|
-
var _reactNative = require("react-native");
|
|
9
|
-
const PLATFORM_NAMES = {
|
|
10
|
-
ios: 'iOS',
|
|
11
|
-
android: 'Android'
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* The device line a ticket carries as its user agent: platform, OS version and,
|
|
16
|
-
* when the app registered one with mobile-core's `setDeviceContext`, the model.
|
|
17
|
-
*/
|
|
18
|
-
const describeDevice = () => {
|
|
19
|
-
const context = (0, _mobileCore.getDeviceContext)();
|
|
20
|
-
const platform = PLATFORM_NAMES[_reactNative.Platform.OS] ?? _reactNative.Platform.OS;
|
|
21
|
-
const osVersion = context?.osVersion ?? String(_reactNative.Platform.Version ?? '');
|
|
22
|
-
const parts = [`${platform} ${osVersion}`.trim()];
|
|
23
|
-
if (context?.deviceModel) {
|
|
24
|
-
parts.push(context.deviceModel);
|
|
25
|
-
}
|
|
26
|
-
return parts.join('; ');
|
|
27
|
-
};
|
|
28
|
-
exports.describeDevice = describeDevice;
|
|
29
|
-
//# sourceMappingURL=device.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.describeDevice=void 0;var _mobileCore=require("@webority/mobile-core"),_reactNative=require("react-native");const PLATFORM_NAMES={ios:"iOS",android:"Android"},describeDevice=()=>{const e=(0,_mobileCore.getDeviceContext)(),r=[`${PLATFORM_NAMES[_reactNative.Platform.OS]??_reactNative.Platform.OS} ${e?.osVersion??String(_reactNative.Platform.Version??"")}`.trim()];return e?.deviceModel&&r.push(e.deviceModel),r.join("; ")};exports.describeDevice=describeDevice;
|
package/lib/commonjs/files.js
CHANGED
|
@@ -1,37 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.saveAttachmentToCache = exports.safeFileName = void 0;
|
|
7
|
-
var _expoFileSystem = require("expo-file-system");
|
|
8
|
-
const FOLDER = 'support-attachments';
|
|
9
|
-
|
|
10
|
-
/** A server-supplied name reduced to one path segment, so it cannot leave the cache folder. */
|
|
11
|
-
const safeFileName = name => {
|
|
12
|
-
const last = name.split(/[/\\]/).pop() ?? '';
|
|
13
|
-
const cleaned = Array.from(last).filter(char => (char.codePointAt(0) ?? 0) > 0x1f).join('').trim();
|
|
14
|
-
return cleaned === '' || cleaned === '.' || cleaned === '..' ? 'attachment' : cleaned;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Writes an attachment to the app's cache and returns its `file://` URI. The id
|
|
19
|
-
* prefix keeps two tickets' `report.pdf` apart. Attachments never change once
|
|
20
|
-
* stored, so a file already on disk is reused rather than fetched again.
|
|
21
|
-
*/
|
|
22
|
-
exports.safeFileName = safeFileName;
|
|
23
|
-
const saveAttachmentToCache = async (attachment, loadBytes) => {
|
|
24
|
-
const file = new _expoFileSystem.File(_expoFileSystem.Paths.cache, FOLDER, `${attachment.id}-${safeFileName(attachment.fileName)}`);
|
|
25
|
-
if (file.exists && file.size > 0) {
|
|
26
|
-
return file.uri;
|
|
27
|
-
}
|
|
28
|
-
const bytes = await loadBytes();
|
|
29
|
-
file.create({
|
|
30
|
-
intermediates: true,
|
|
31
|
-
overwrite: true
|
|
32
|
-
});
|
|
33
|
-
file.write(new Uint8Array(bytes));
|
|
34
|
-
return file.uri;
|
|
35
|
-
};
|
|
36
|
-
exports.saveAttachmentToCache = saveAttachmentToCache;
|
|
37
|
-
//# sourceMappingURL=files.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.saveAttachmentToCache=exports.safeFileName=void 0;var _expoFileSystem=require("expo-file-system");const FOLDER="support-attachments",safeFileName=e=>{const t=e.split(/[/\\]/).pop()??"",a=Array.from(t).filter(e=>(e.codePointAt(0)??0)>31).join("").trim();return""===a||"."===a||".."===a?"attachment":a};exports.safeFileName=safeFileName;const saveAttachmentToCache=async(e,t)=>{const a=new _expoFileSystem.File(_expoFileSystem.Paths.cache,FOLDER,`${e.id}-${safeFileName(e.fileName)}`);if(a.exists&&a.size>0)return a.uri;const s=await t();return a.create({intermediates:!0,overwrite:!0}),a.write(new Uint8Array(s)),a.uri};exports.saveAttachmentToCache=saveAttachmentToCache;
|
package/lib/commonjs/format.js
CHANGED
|
@@ -1,29 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.isImage = exports.formatWhen = exports.formatBytes = void 0;
|
|
7
|
-
var _mobileCore = require("@webority/mobile-core");
|
|
8
|
-
/**
|
|
9
|
-
* A timestamp in the device's own time zone. The backend sends UTC; mobile-core's
|
|
10
|
-
* formatter goes through Intl without pinning a zone, so the reader sees their
|
|
11
|
-
* own clock.
|
|
12
|
-
*/
|
|
13
|
-
const formatWhen = utc => utc ? (0, _mobileCore.formatDateTime)(utc) || '-' : '-';
|
|
14
|
-
|
|
15
|
-
/** A byte count as a person reads it. */
|
|
16
|
-
exports.formatWhen = formatWhen;
|
|
17
|
-
const formatBytes = bytes => {
|
|
18
|
-
if (bytes >= 1024 * 1024) {
|
|
19
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
20
|
-
}
|
|
21
|
-
if (bytes >= 1024) {
|
|
22
|
-
return `${Math.round(bytes / 1024)} KB`;
|
|
23
|
-
}
|
|
24
|
-
return `${bytes} bytes`;
|
|
25
|
-
};
|
|
26
|
-
exports.formatBytes = formatBytes;
|
|
27
|
-
const isImage = contentType => contentType.startsWith('image/');
|
|
28
|
-
exports.isImage = isImage;
|
|
29
|
-
//# sourceMappingURL=format.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.isImage=exports.formatWhen=exports.formatBytes=exports.DEFAULT_TIME_ZONE=void 0;const DEFAULT_TIME_ZONE=exports.DEFAULT_TIME_ZONE="Asia/Kolkata",formatWhen=(t,e=DEFAULT_TIME_ZONE)=>{if(!t)return"-";const o=new Date(t);if(Number.isNaN(o.getTime()))return"-";const r={};for(const t of new Intl.DateTimeFormat("en-US",{timeZone:e,day:"2-digit",month:"short",year:"numeric",hour:"numeric",minute:"2-digit",hour12:!0}).formatToParts(o))r[t.type]=t.value;return`${r.day}-${r.month}-${r.year}, ${r.hour}:${r.minute} ${(r.dayPeriod??"").toUpperCase()}`};exports.formatWhen=formatWhen;const formatBytes=t=>t>=1048576?`${(t/1048576).toFixed(1)} MB`:t>=1024?`${Math.round(t/1024)} KB`:`${t} bytes`;exports.formatBytes=formatBytes;const isImage=t=>t.startsWith("image/");exports.isImage=isImage;
|
package/lib/commonjs/index.js
CHANGED
|
@@ -1,97 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
Object.defineProperty(exports, "NewSupportTicket", {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: function () {
|
|
9
|
-
return _NewSupportTicket.NewSupportTicket;
|
|
10
|
-
}
|
|
11
|
-
});
|
|
12
|
-
Object.defineProperty(exports, "SupportApiError", {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: function () {
|
|
15
|
-
return _client.SupportApiError;
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
Object.defineProperty(exports, "SupportContact", {
|
|
19
|
-
enumerable: true,
|
|
20
|
-
get: function () {
|
|
21
|
-
return _SupportContact.SupportContact;
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
Object.defineProperty(exports, "SupportProvider", {
|
|
25
|
-
enumerable: true,
|
|
26
|
-
get: function () {
|
|
27
|
-
return _SupportProvider.SupportProvider;
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
Object.defineProperty(exports, "SupportTicketDetail", {
|
|
31
|
-
enumerable: true,
|
|
32
|
-
get: function () {
|
|
33
|
-
return _SupportTicketDetail.SupportTicketDetail;
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
Object.defineProperty(exports, "SupportTicketList", {
|
|
37
|
-
enumerable: true,
|
|
38
|
-
get: function () {
|
|
39
|
-
return _SupportTicketList.SupportTicketList;
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
Object.defineProperty(exports, "createSupportClient", {
|
|
43
|
-
enumerable: true,
|
|
44
|
-
get: function () {
|
|
45
|
-
return _client.createSupportClient;
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
Object.defineProperty(exports, "describeDevice", {
|
|
49
|
-
enumerable: true,
|
|
50
|
-
get: function () {
|
|
51
|
-
return _device.describeDevice;
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
Object.defineProperty(exports, "toSupportApiError", {
|
|
55
|
-
enumerable: true,
|
|
56
|
-
get: function () {
|
|
57
|
-
return _client.toSupportApiError;
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
Object.defineProperty(exports, "useCreateSupportTicket", {
|
|
61
|
-
enumerable: true,
|
|
62
|
-
get: function () {
|
|
63
|
-
return _SupportProvider.useCreateSupportTicket;
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
Object.defineProperty(exports, "useSupportClient", {
|
|
67
|
-
enumerable: true,
|
|
68
|
-
get: function () {
|
|
69
|
-
return _SupportProvider.useSupportClient;
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
Object.defineProperty(exports, "useSupportConfig", {
|
|
73
|
-
enumerable: true,
|
|
74
|
-
get: function () {
|
|
75
|
-
return _SupportProvider.useSupportConfig;
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
Object.defineProperty(exports, "useSupportTicket", {
|
|
79
|
-
enumerable: true,
|
|
80
|
-
get: function () {
|
|
81
|
-
return _SupportProvider.useSupportTicket;
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
Object.defineProperty(exports, "useSupportTickets", {
|
|
85
|
-
enumerable: true,
|
|
86
|
-
get: function () {
|
|
87
|
-
return _SupportProvider.useSupportTickets;
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
var _client = require("./client.js");
|
|
91
|
-
var _NewSupportTicket = require("./components/NewSupportTicket.js");
|
|
92
|
-
var _SupportContact = require("./components/SupportContact.js");
|
|
93
|
-
var _SupportTicketDetail = require("./components/SupportTicketDetail.js");
|
|
94
|
-
var _SupportTicketList = require("./components/SupportTicketList.js");
|
|
95
|
-
var _device = require("./device.js");
|
|
96
|
-
var _SupportProvider = require("./SupportProvider.js");
|
|
97
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"NewSupportTicket",{enumerable:!0,get:function(){return _NewSupportTicket.NewSupportTicket}}),Object.defineProperty(exports,"SupportApiError",{enumerable:!0,get:function(){return _client.SupportApiError}}),Object.defineProperty(exports,"SupportContact",{enumerable:!0,get:function(){return _SupportContact.SupportContact}}),Object.defineProperty(exports,"SupportProvider",{enumerable:!0,get:function(){return _SupportProvider.SupportProvider}}),Object.defineProperty(exports,"SupportTicketDetail",{enumerable:!0,get:function(){return _SupportTicketDetail.SupportTicketDetail}}),Object.defineProperty(exports,"SupportTicketList",{enumerable:!0,get:function(){return _SupportTicketList.SupportTicketList}}),Object.defineProperty(exports,"createSupportClient",{enumerable:!0,get:function(){return _client.createSupportClient}}),Object.defineProperty(exports,"describeDevice",{enumerable:!0,get:function(){return _device.describeDevice}}),Object.defineProperty(exports,"toSupportApiError",{enumerable:!0,get:function(){return _client.toSupportApiError}}),Object.defineProperty(exports,"useCreateSupportTicket",{enumerable:!0,get:function(){return _SupportProvider.useCreateSupportTicket}}),Object.defineProperty(exports,"useSupportClient",{enumerable:!0,get:function(){return _SupportProvider.useSupportClient}}),Object.defineProperty(exports,"useSupportConfig",{enumerable:!0,get:function(){return _SupportProvider.useSupportConfig}}),Object.defineProperty(exports,"useSupportTicket",{enumerable:!0,get:function(){return _SupportProvider.useSupportTicket}}),Object.defineProperty(exports,"useSupportTickets",{enumerable:!0,get:function(){return _SupportProvider.useSupportTickets}});var _client=require("./client.js"),_NewSupportTicket=require("./components/NewSupportTicket.js"),_SupportContact=require("./components/SupportContact.js"),_SupportTicketDetail=require("./components/SupportTicketDetail.js"),_SupportTicketList=require("./components/SupportTicketList.js"),_device=require("./device.js"),_SupportProvider=require("./SupportProvider.js");
|
package/lib/commonjs/photos.js
CHANGED
|
@@ -1,67 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.pickPhotos = exports.PhotoPermissionError = void 0;
|
|
7
|
-
var _compressor = require("@webority/mobile-core/compressor");
|
|
8
|
-
/** The one place `expo-image-picker` is named. */
|
|
9
|
-
const picker = () => require('expo-image-picker');
|
|
10
|
-
class PhotoPermissionError extends Error {
|
|
11
|
-
constructor(source) {
|
|
12
|
-
super(source === 'camera' ? 'Allow camera access in Settings to take a photo.' : 'Allow photo access in Settings to attach a photo.');
|
|
13
|
-
this.name = 'PhotoPermissionError';
|
|
14
|
-
this.source = source;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// The fleet capture pass: quality 0.8, no editing, then bound to 1920 px.
|
|
19
|
-
exports.PhotoPermissionError = PhotoPermissionError;
|
|
20
|
-
const CAPTURE_OPTIONS = {
|
|
21
|
-
mediaTypes: ['images'],
|
|
22
|
-
quality: 0.8,
|
|
23
|
-
allowsEditing: false
|
|
24
|
-
};
|
|
25
|
-
const MAX_SIDE = 1920;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Lets the person pick or take photos and returns them ready to upload,
|
|
29
|
-
* compressed to fit the product's per-file limit. An empty list means they
|
|
30
|
-
* cancelled.
|
|
31
|
-
*/
|
|
32
|
-
const pickPhotos = async (source, options) => {
|
|
33
|
-
if (options.maxCount <= 0) {
|
|
34
|
-
return [];
|
|
35
|
-
}
|
|
36
|
-
const m = picker();
|
|
37
|
-
const permission = source === 'camera' ? await m.requestCameraPermissionsAsync() : await m.requestMediaLibraryPermissionsAsync();
|
|
38
|
-
if (!permission.granted) {
|
|
39
|
-
throw new PhotoPermissionError(source);
|
|
40
|
-
}
|
|
41
|
-
const result = source === 'camera' ? await m.launchCameraAsync(CAPTURE_OPTIONS) : await m.launchImageLibraryAsync({
|
|
42
|
-
...CAPTURE_OPTIONS,
|
|
43
|
-
allowsMultipleSelection: options.maxCount > 1,
|
|
44
|
-
selectionLimit: options.maxCount
|
|
45
|
-
});
|
|
46
|
-
if (result.canceled || !result.assets) {
|
|
47
|
-
return [];
|
|
48
|
-
}
|
|
49
|
-
const parts = [];
|
|
50
|
-
for (const asset of result.assets.slice(0, options.maxCount)) {
|
|
51
|
-
const compressed = await (0, _compressor.compressImage)(asset.uri, {
|
|
52
|
-
maxSize: MAX_SIDE,
|
|
53
|
-
maxBytes: options.maxBytes,
|
|
54
|
-
fileSize: asset.fileSize ?? undefined,
|
|
55
|
-
name: asset.fileName ?? `photo-${Date.now()}-${parts.length + 1}`
|
|
56
|
-
});
|
|
57
|
-
parts.push({
|
|
58
|
-
uri: compressed.part.uri,
|
|
59
|
-
name: compressed.part.name,
|
|
60
|
-
type: compressed.part.type,
|
|
61
|
-
size: compressed.size ?? undefined
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
return parts;
|
|
65
|
-
};
|
|
66
|
-
exports.pickPhotos = pickPhotos;
|
|
67
|
-
//# sourceMappingURL=photos.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.pickPhotos=exports.PhotoPermissionError=void 0;var _compressor=require("@webority/mobile-core/compressor");const picker=()=>require("expo-image-picker");class PhotoPermissionError extends Error{constructor(e){super("camera"===e?"Allow camera access in Settings to take a photo.":"Allow photo access in Settings to attach a photo."),this.name="PhotoPermissionError",this.source=e}}exports.PhotoPermissionError=PhotoPermissionError;const CAPTURE_OPTIONS={mediaTypes:["images"],quality:.8,allowsEditing:!1},MAX_SIDE=1920,pickPhotos=async(e,o)=>{if(o.maxCount<=0)return[];const r=picker();if(!("camera"===e?await r.requestCameraPermissionsAsync():await r.requestMediaLibraryPermissionsAsync()).granted)throw new PhotoPermissionError(e);const s="camera"===e?await r.launchCameraAsync(CAPTURE_OPTIONS):await r.launchImageLibraryAsync({...CAPTURE_OPTIONS,allowsMultipleSelection:o.maxCount>1,selectionLimit:o.maxCount});if(s.canceled||!s.assets)return[];const t=[];for(const e of s.assets.slice(0,o.maxCount)){const r=await(0,_compressor.compressImage)(e.uri,{maxSize:1920,maxBytes:o.maxBytes,fileSize:e.fileSize??void 0,name:e.fileName??`photo-${Date.now()}-${t.length+1}`});t.push({uri:r.part.uri,name:r.part.name,type:r.part.type,size:r.size??void 0})}return t};exports.pickPhotos=pickPhotos;
|
|
@@ -1,57 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.ReportIssueButton = void 0;
|
|
7
|
-
var _mobileUi = require("@webority/mobile-ui");
|
|
8
|
-
var _react = require("react");
|
|
9
|
-
var _captureAndReport = require("./captureAndReport.js");
|
|
10
|
-
var _jsxRuntime = require("react/jsx-runtime");
|
|
11
|
-
/** A button that screenshots the current screen and hands a prefilled ticket draft to the app. */
|
|
12
|
-
const ReportIssueButton = ({
|
|
13
|
-
onReport,
|
|
14
|
-
onCaptureError,
|
|
15
|
-
screenName,
|
|
16
|
-
appVersion,
|
|
17
|
-
category,
|
|
18
|
-
subject,
|
|
19
|
-
title = 'Report an issue',
|
|
20
|
-
accessibilityLabel = 'Report an issue with this screen',
|
|
21
|
-
testID = 'support-report-issue',
|
|
22
|
-
...buttonProps
|
|
23
|
-
}) => {
|
|
24
|
-
const [capturing, setCapturing] = (0, _react.useState)(false);
|
|
25
|
-
const press = async () => {
|
|
26
|
-
setCapturing(true);
|
|
27
|
-
try {
|
|
28
|
-
onReport(await (0, _captureAndReport.captureAndReport)({
|
|
29
|
-
screenName,
|
|
30
|
-
appVersion,
|
|
31
|
-
category,
|
|
32
|
-
subject
|
|
33
|
-
}));
|
|
34
|
-
} catch (error) {
|
|
35
|
-
onCaptureError?.(error);
|
|
36
|
-
onReport({
|
|
37
|
-
category,
|
|
38
|
-
subject,
|
|
39
|
-
pageUrl: screenName,
|
|
40
|
-
appVersion
|
|
41
|
-
});
|
|
42
|
-
} finally {
|
|
43
|
-
setCapturing(false);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_mobileUi.Button, {
|
|
47
|
-
leftIcon: "message-question",
|
|
48
|
-
...buttonProps,
|
|
49
|
-
title: title,
|
|
50
|
-
accessibilityLabel: accessibilityLabel,
|
|
51
|
-
testID: testID,
|
|
52
|
-
loading: capturing,
|
|
53
|
-
onPress: () => void press()
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
exports.ReportIssueButton = ReportIssueButton;
|
|
57
|
-
//# sourceMappingURL=ReportIssueButton.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ReportIssueButton=void 0;var _mobileUi=require("@webority/mobile-ui"),_react=require("react"),_captureAndReport=require("./captureAndReport.js"),_jsxRuntime=require("react/jsx-runtime");const ReportIssueButton=({onReport:e,onCaptureError:t,screenName:r,appVersion:s,category:o,subject:i,title:u="Report an issue",accessibilityLabel:a="Report an issue with this screen",testID:n="support-report-issue",...p})=>{const[c,l]=(0,_react.useState)(!1);return(0,_jsxRuntime.jsx)(_mobileUi.Button,{leftIcon:"message-question",...p,title:u,accessibilityLabel:a,testID:n,loading:c,onPress:()=>{(async()=>{l(!0);try{e(await(0,_captureAndReport.captureAndReport)({screenName:r,appVersion:s,category:o,subject:i}))}catch(u){t?.(u),e({category:o,subject:i,pageUrl:r,appVersion:s})}finally{l(!1)}})()}})};exports.ReportIssueButton=ReportIssueButton;
|
|
@@ -1,34 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.captureAndReport = void 0;
|
|
7
|
-
var _device = require("../device.js");
|
|
8
|
-
/** The one place `react-native-view-shot` is named, and only this subpath reaches it. */
|
|
9
|
-
const viewShot = () => require('react-native-view-shot');
|
|
10
|
-
/**
|
|
11
|
-
* Captures what is on screen right now and returns a draft for NewSupportTicket
|
|
12
|
-
* with the image under `screenshots`, plus the page, device and app version.
|
|
13
|
-
*/
|
|
14
|
-
const captureAndReport = async options => {
|
|
15
|
-
const uri = await viewShot().captureScreen({
|
|
16
|
-
format: 'jpg',
|
|
17
|
-
quality: 0.8,
|
|
18
|
-
result: 'tmpfile'
|
|
19
|
-
});
|
|
20
|
-
return {
|
|
21
|
-
category: options.category,
|
|
22
|
-
subject: options.subject,
|
|
23
|
-
pageUrl: options.screenName,
|
|
24
|
-
userAgent: (0, _device.describeDevice)(),
|
|
25
|
-
appVersion: options.appVersion,
|
|
26
|
-
screenshots: [{
|
|
27
|
-
uri,
|
|
28
|
-
name: `screenshot-${Date.now()}.jpg`,
|
|
29
|
-
type: 'image/jpeg'
|
|
30
|
-
}]
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
exports.captureAndReport = captureAndReport;
|
|
34
|
-
//# sourceMappingURL=captureAndReport.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.captureAndReport=void 0;var _device=require("../device.js");const viewShot=()=>require("react-native-view-shot"),captureAndReport=async e=>{const t=await viewShot().captureScreen({format:"jpg",quality:.8,result:"tmpfile"});return{category:e.category,subject:e.subject,pageUrl:e.screenName,userAgent:(0,_device.describeDevice)(),appVersion:e.appVersion,screenshots:[{uri:t,name:`screenshot-${Date.now()}.jpg`,type:"image/jpeg"}]}};exports.captureAndReport=captureAndReport;
|