@@ -21,6 +21,7 @@ import pako from 'pako';
21
21
import { MatrixClientPeg } from '../MatrixClientPeg' ;
22
22
import PlatformPeg from '../PlatformPeg' ;
23
23
import { _t } from '../languageHandler' ;
24
+ import Tar from "tar-js" ;
24
25
25
26
import * as rageshake from './rageshake' ;
26
27
@@ -33,26 +34,7 @@ if (!TextEncoder) {
33
34
TextEncoder = TextEncodingUtf8 . TextEncoder ;
34
35
}
35
36
36
- /**
37
- * Send a bug report.
38
- *
39
- * @param {string } bugReportEndpoint HTTP url to send the report to
40
- *
41
- * @param {object } opts optional dictionary of options
42
- *
43
- * @param {string } opts.userText Any additional user input.
44
- *
45
- * @param {boolean } opts.sendLogs True to send logs
46
- *
47
- * @param {function(string) } opts.progressCallback Callback to call with progress updates
48
- *
49
- * @return {Promise } Resolved when the bug report is sent.
50
- */
51
- export default async function sendBugReport ( bugReportEndpoint , opts ) {
52
- if ( ! bugReportEndpoint ) {
53
- throw new Error ( "No bug report endpoint has been set." ) ;
54
- }
55
-
37
+ async function collectBugReport ( opts ) {
56
38
opts = opts || { } ;
57
39
const progressCallback = opts . progressCallback || ( ( ) => { } ) ;
58
40
@@ -106,10 +88,96 @@ export default async function sendBugReport(bugReportEndpoint, opts) {
106
88
}
107
89
}
108
90
91
+ return body ;
92
+ }
93
+
94
+ /**
95
+ * Send a bug report.
96
+ *
97
+ * @param {string } bugReportEndpoint HTTP url to send the report to
98
+ *
99
+ * @param {object } opts optional dictionary of options
100
+ *
101
+ * @param {string } opts.userText Any additional user input.
102
+ *
103
+ * @param {boolean } opts.sendLogs True to send logs
104
+ *
105
+ * @param {function(string) } opts.progressCallback Callback to call with progress updates
106
+ *
107
+ * @return {Promise } Resolved when the bug report is sent.
108
+ */
109
+ export default async function sendBugReport ( bugReportEndpoint , opts ) {
110
+ if ( ! bugReportEndpoint ) {
111
+ throw new Error ( "No bug report endpoint has been set." ) ;
112
+ }
113
+
114
+ opts = opts || { } ;
115
+ const progressCallback = opts . progressCallback || ( ( ) => { } ) ;
116
+ const body = await collectBugReport ( opts ) ;
117
+
109
118
progressCallback ( _t ( "Uploading report" ) ) ;
110
119
await _submitReport ( bugReportEndpoint , body , progressCallback ) ;
111
120
}
112
121
122
+ /**
123
+ * Downloads the files from a bug report. This is the same as sendBugReport,
124
+ * but instead causes the browser to download the files locally.
125
+ *
126
+ * @param {object } opts optional dictionary of options
127
+ *
128
+ * @param {string } opts.userText Any additional user input.
129
+ *
130
+ * @param {boolean } opts.sendLogs True to send logs
131
+ *
132
+ * @param {function(string) } opts.progressCallback Callback to call with progress updates
133
+ *
134
+ * @return {Promise } Resolved when the bug report is downloaded (or started).
135
+ */
136
+ export async function downloadBugReport ( opts ) {
137
+ opts = opts || { } ;
138
+ const progressCallback = opts . progressCallback || ( ( ) => { } ) ;
139
+ const body = await collectBugReport ( opts ) ;
140
+
141
+ progressCallback ( _t ( "Downloading report" ) ) ;
142
+ let metadata = "" ;
143
+ const tape = new Tar ( ) ;
144
+ let i = 0 ;
145
+ for ( const e of body . entries ( ) ) {
146
+ if ( e [ 0 ] === 'compressed-log' ) {
147
+ await new Promise ( ( resolve => {
148
+ const reader = new FileReader ( ) ;
149
+ reader . addEventListener ( 'loadend' , ev => {
150
+ tape . append ( `log-${ i ++ } .log` , pako . ungzip ( ev . target . result ) ) ;
151
+ resolve ( ) ;
152
+ } ) ;
153
+ reader . readAsArrayBuffer ( e [ 1 ] ) ;
154
+ } ) )
155
+ } else {
156
+ metadata += `${ e [ 0 ] } = ${ e [ 1 ] } \n` ;
157
+ }
158
+ }
159
+ tape . append ( 'issue.txt' , metadata ) ;
160
+
161
+ // We have to create a new anchor to download if we want a filename. Otherwise we could
162
+ // just use window.open.
163
+ const dl = document . createElement ( 'a' ) ;
164
+ dl . href = `data:application/octet-stream;base64,${ btoa ( uint8ToString ( tape . out ) ) } ` ;
165
+ dl . download = 'rageshake.tar' ;
166
+ document . body . appendChild ( dl ) ;
167
+ dl . click ( ) ;
168
+ document . body . removeChild ( dl ) ;
169
+ }
170
+
171
+ // Source: https://github.com/beatgammit/tar-js/blob/master/examples/main.js
172
+ function uint8ToString ( buf ) {
173
+ let i , length , out = '' ;
174
+ for ( i = 0 , length = buf . length ; i < length ; i += 1 ) {
175
+ out += String . fromCharCode ( buf [ i ] ) ;
176
+ }
177
+
178
+ return out ;
179
+ }
180
+
113
181
function _submitReport ( endpoint , body , progressCallback ) {
114
182
return new Promise ( ( resolve , reject ) => {
115
183
const req = new XMLHttpRequest ( ) ;
0 commit comments