@appsupportkit/support-sdk 0.1.2 → 0.3.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 (224) hide show
  1. package/lib/commonjs/api.js +17 -2
  2. package/lib/commonjs/api.js.map +1 -1
  3. package/lib/commonjs/components/BottomSheet.js +67 -47
  4. package/lib/commonjs/components/BottomSheet.js.map +1 -1
  5. package/lib/commonjs/components/LauncherButton.js +177 -0
  6. package/lib/commonjs/components/LauncherButton.js.map +1 -0
  7. package/lib/commonjs/components/SupportButton.js +168 -190
  8. package/lib/commonjs/components/SupportButton.js.map +1 -1
  9. package/lib/commonjs/components/icons.js +110 -23
  10. package/lib/commonjs/components/icons.js.map +1 -1
  11. package/lib/commonjs/components/primitives.js +191 -44
  12. package/lib/commonjs/components/primitives.js.map +1 -1
  13. package/lib/commonjs/components/screens/ComposeScreen.js +108 -60
  14. package/lib/commonjs/components/screens/ComposeScreen.js.map +1 -1
  15. package/lib/commonjs/components/screens/HomeScreen.js +221 -118
  16. package/lib/commonjs/components/screens/HomeScreen.js.map +1 -1
  17. package/lib/commonjs/components/screens/LanguageScreen.js +150 -0
  18. package/lib/commonjs/components/screens/LanguageScreen.js.map +1 -0
  19. package/lib/commonjs/components/screens/ThreadScreen.js +237 -111
  20. package/lib/commonjs/components/screens/ThreadScreen.js.map +1 -1
  21. package/lib/commonjs/i18n/index.js +101 -0
  22. package/lib/commonjs/i18n/index.js.map +1 -0
  23. package/lib/commonjs/i18n/languages.js +95 -0
  24. package/lib/commonjs/i18n/languages.js.map +1 -0
  25. package/lib/commonjs/i18n/strings/de.js +72 -0
  26. package/lib/commonjs/i18n/strings/de.js.map +1 -0
  27. package/lib/commonjs/i18n/strings/en.js +88 -0
  28. package/lib/commonjs/i18n/strings/en.js.map +1 -0
  29. package/lib/commonjs/i18n/strings/es.js +72 -0
  30. package/lib/commonjs/i18n/strings/es.js.map +1 -0
  31. package/lib/commonjs/i18n/strings/fr.js +72 -0
  32. package/lib/commonjs/i18n/strings/fr.js.map +1 -0
  33. package/lib/commonjs/i18n/strings/hi.js +72 -0
  34. package/lib/commonjs/i18n/strings/hi.js.map +1 -0
  35. package/lib/commonjs/i18n/strings/it.js +72 -0
  36. package/lib/commonjs/i18n/strings/it.js.map +1 -0
  37. package/lib/commonjs/i18n/strings/ja.js +72 -0
  38. package/lib/commonjs/i18n/strings/ja.js.map +1 -0
  39. package/lib/commonjs/i18n/strings/ko.js +72 -0
  40. package/lib/commonjs/i18n/strings/ko.js.map +1 -0
  41. package/lib/commonjs/i18n/strings/nl.js +72 -0
  42. package/lib/commonjs/i18n/strings/nl.js.map +1 -0
  43. package/lib/commonjs/i18n/strings/pl.js +72 -0
  44. package/lib/commonjs/i18n/strings/pl.js.map +1 -0
  45. package/lib/commonjs/i18n/strings/pt.js +72 -0
  46. package/lib/commonjs/i18n/strings/pt.js.map +1 -0
  47. package/lib/commonjs/i18n/strings/ru.js +72 -0
  48. package/lib/commonjs/i18n/strings/ru.js.map +1 -0
  49. package/lib/commonjs/i18n/strings/tr.js +72 -0
  50. package/lib/commonjs/i18n/strings/tr.js.map +1 -0
  51. package/lib/commonjs/i18n/strings/zh.js +72 -0
  52. package/lib/commonjs/i18n/strings/zh.js.map +1 -0
  53. package/lib/commonjs/index.js +31 -0
  54. package/lib/commonjs/index.js.map +1 -1
  55. package/lib/commonjs/theme.js +136 -17
  56. package/lib/commonjs/theme.js.map +1 -1
  57. package/lib/commonjs/types.js +18 -0
  58. package/lib/commonjs/types.js.map +1 -1
  59. package/lib/commonjs/unread.js +92 -0
  60. package/lib/commonjs/unread.js.map +1 -0
  61. package/lib/commonjs/useSupportThreads.js +296 -0
  62. package/lib/commonjs/useSupportThreads.js.map +1 -0
  63. package/lib/commonjs/utils.js +58 -10
  64. package/lib/commonjs/utils.js.map +1 -1
  65. package/lib/module/api.js +16 -2
  66. package/lib/module/api.js.map +1 -1
  67. package/lib/module/components/BottomSheet.js +68 -48
  68. package/lib/module/components/BottomSheet.js.map +1 -1
  69. package/lib/module/components/LauncherButton.js +172 -0
  70. package/lib/module/components/LauncherButton.js.map +1 -0
  71. package/lib/module/components/SupportButton.js +172 -194
  72. package/lib/module/components/SupportButton.js.map +1 -1
  73. package/lib/module/components/icons.js +107 -22
  74. package/lib/module/components/icons.js.map +1 -1
  75. package/lib/module/components/primitives.js +187 -45
  76. package/lib/module/components/primitives.js.map +1 -1
  77. package/lib/module/components/screens/ComposeScreen.js +114 -64
  78. package/lib/module/components/screens/ComposeScreen.js.map +1 -1
  79. package/lib/module/components/screens/HomeScreen.js +224 -121
  80. package/lib/module/components/screens/HomeScreen.js.map +1 -1
  81. package/lib/module/components/screens/LanguageScreen.js +147 -0
  82. package/lib/module/components/screens/LanguageScreen.js.map +1 -0
  83. package/lib/module/components/screens/ThreadScreen.js +243 -115
  84. package/lib/module/components/screens/ThreadScreen.js.map +1 -1
  85. package/lib/module/i18n/index.js +56 -0
  86. package/lib/module/i18n/index.js.map +1 -0
  87. package/lib/module/i18n/languages.js +88 -0
  88. package/lib/module/i18n/languages.js.map +1 -0
  89. package/lib/module/i18n/strings/de.js +68 -0
  90. package/lib/module/i18n/strings/de.js.map +1 -0
  91. package/lib/module/i18n/strings/en.js +84 -0
  92. package/lib/module/i18n/strings/en.js.map +1 -0
  93. package/lib/module/i18n/strings/es.js +68 -0
  94. package/lib/module/i18n/strings/es.js.map +1 -0
  95. package/lib/module/i18n/strings/fr.js +68 -0
  96. package/lib/module/i18n/strings/fr.js.map +1 -0
  97. package/lib/module/i18n/strings/hi.js +68 -0
  98. package/lib/module/i18n/strings/hi.js.map +1 -0
  99. package/lib/module/i18n/strings/it.js +68 -0
  100. package/lib/module/i18n/strings/it.js.map +1 -0
  101. package/lib/module/i18n/strings/ja.js +68 -0
  102. package/lib/module/i18n/strings/ja.js.map +1 -0
  103. package/lib/module/i18n/strings/ko.js +68 -0
  104. package/lib/module/i18n/strings/ko.js.map +1 -0
  105. package/lib/module/i18n/strings/nl.js +68 -0
  106. package/lib/module/i18n/strings/nl.js.map +1 -0
  107. package/lib/module/i18n/strings/pl.js +68 -0
  108. package/lib/module/i18n/strings/pl.js.map +1 -0
  109. package/lib/module/i18n/strings/pt.js +68 -0
  110. package/lib/module/i18n/strings/pt.js.map +1 -0
  111. package/lib/module/i18n/strings/ru.js +68 -0
  112. package/lib/module/i18n/strings/ru.js.map +1 -0
  113. package/lib/module/i18n/strings/tr.js +68 -0
  114. package/lib/module/i18n/strings/tr.js.map +1 -0
  115. package/lib/module/i18n/strings/zh.js +68 -0
  116. package/lib/module/i18n/strings/zh.js.map +1 -0
  117. package/lib/module/index.js +1 -0
  118. package/lib/module/index.js.map +1 -1
  119. package/lib/module/theme.js +135 -16
  120. package/lib/module/theme.js.map +1 -1
  121. package/lib/module/types.js +18 -0
  122. package/lib/module/types.js.map +1 -1
  123. package/lib/module/unread.js +83 -0
  124. package/lib/module/unread.js.map +1 -0
  125. package/lib/module/useSupportThreads.js +291 -0
  126. package/lib/module/useSupportThreads.js.map +1 -0
  127. package/lib/module/utils.js +55 -10
  128. package/lib/module/utils.js.map +1 -1
  129. package/lib/typescript/api.d.ts +9 -0
  130. package/lib/typescript/api.d.ts.map +1 -1
  131. package/lib/typescript/components/BottomSheet.d.ts.map +1 -1
  132. package/lib/typescript/components/LauncherButton.d.ts +14 -0
  133. package/lib/typescript/components/LauncherButton.d.ts.map +1 -0
  134. package/lib/typescript/components/SupportButton.d.ts +3 -3
  135. package/lib/typescript/components/SupportButton.d.ts.map +1 -1
  136. package/lib/typescript/components/icons.d.ts +18 -2
  137. package/lib/typescript/components/icons.d.ts.map +1 -1
  138. package/lib/typescript/components/primitives.d.ts +42 -7
  139. package/lib/typescript/components/primitives.d.ts.map +1 -1
  140. package/lib/typescript/components/screens/ComposeScreen.d.ts +3 -1
  141. package/lib/typescript/components/screens/ComposeScreen.d.ts.map +1 -1
  142. package/lib/typescript/components/screens/HomeScreen.d.ts +8 -2
  143. package/lib/typescript/components/screens/HomeScreen.d.ts.map +1 -1
  144. package/lib/typescript/components/screens/LanguageScreen.d.ts +30 -0
  145. package/lib/typescript/components/screens/LanguageScreen.d.ts.map +1 -0
  146. package/lib/typescript/components/screens/ThreadScreen.d.ts +3 -1
  147. package/lib/typescript/components/screens/ThreadScreen.d.ts.map +1 -1
  148. package/lib/typescript/i18n/index.d.ts +15 -0
  149. package/lib/typescript/i18n/index.d.ts.map +1 -0
  150. package/lib/typescript/i18n/languages.d.ts +36 -0
  151. package/lib/typescript/i18n/languages.d.ts.map +1 -0
  152. package/lib/typescript/i18n/strings/de.d.ts +3 -0
  153. package/lib/typescript/i18n/strings/de.d.ts.map +1 -0
  154. package/lib/typescript/i18n/strings/en.d.ts +83 -0
  155. package/lib/typescript/i18n/strings/en.d.ts.map +1 -0
  156. package/lib/typescript/i18n/strings/es.d.ts +3 -0
  157. package/lib/typescript/i18n/strings/es.d.ts.map +1 -0
  158. package/lib/typescript/i18n/strings/fr.d.ts +3 -0
  159. package/lib/typescript/i18n/strings/fr.d.ts.map +1 -0
  160. package/lib/typescript/i18n/strings/hi.d.ts +3 -0
  161. package/lib/typescript/i18n/strings/hi.d.ts.map +1 -0
  162. package/lib/typescript/i18n/strings/it.d.ts +3 -0
  163. package/lib/typescript/i18n/strings/it.d.ts.map +1 -0
  164. package/lib/typescript/i18n/strings/ja.d.ts +3 -0
  165. package/lib/typescript/i18n/strings/ja.d.ts.map +1 -0
  166. package/lib/typescript/i18n/strings/ko.d.ts +3 -0
  167. package/lib/typescript/i18n/strings/ko.d.ts.map +1 -0
  168. package/lib/typescript/i18n/strings/nl.d.ts +3 -0
  169. package/lib/typescript/i18n/strings/nl.d.ts.map +1 -0
  170. package/lib/typescript/i18n/strings/pl.d.ts +3 -0
  171. package/lib/typescript/i18n/strings/pl.d.ts.map +1 -0
  172. package/lib/typescript/i18n/strings/pt.d.ts +3 -0
  173. package/lib/typescript/i18n/strings/pt.d.ts.map +1 -0
  174. package/lib/typescript/i18n/strings/ru.d.ts +3 -0
  175. package/lib/typescript/i18n/strings/ru.d.ts.map +1 -0
  176. package/lib/typescript/i18n/strings/tr.d.ts +3 -0
  177. package/lib/typescript/i18n/strings/tr.d.ts.map +1 -0
  178. package/lib/typescript/i18n/strings/zh.d.ts +3 -0
  179. package/lib/typescript/i18n/strings/zh.d.ts.map +1 -0
  180. package/lib/typescript/index.d.ts +2 -1
  181. package/lib/typescript/index.d.ts.map +1 -1
  182. package/lib/typescript/theme.d.ts +44 -3
  183. package/lib/typescript/theme.d.ts.map +1 -1
  184. package/lib/typescript/types.d.ts +54 -2
  185. package/lib/typescript/types.d.ts.map +1 -1
  186. package/lib/typescript/unread.d.ts +22 -0
  187. package/lib/typescript/unread.d.ts.map +1 -0
  188. package/lib/typescript/useSupportThreads.d.ts +38 -0
  189. package/lib/typescript/useSupportThreads.d.ts.map +1 -0
  190. package/lib/typescript/utils.d.ts +8 -2
  191. package/lib/typescript/utils.d.ts.map +1 -1
  192. package/package.json +3 -3
  193. package/src/api.ts +24 -1
  194. package/src/components/BottomSheet.tsx +61 -43
  195. package/src/components/LauncherButton.tsx +217 -0
  196. package/src/components/SupportButton.tsx +195 -210
  197. package/src/components/icons.tsx +113 -19
  198. package/src/components/primitives.tsx +230 -39
  199. package/src/components/screens/ComposeScreen.tsx +129 -63
  200. package/src/components/screens/HomeScreen.tsx +230 -120
  201. package/src/components/screens/LanguageScreen.tsx +172 -0
  202. package/src/components/screens/ThreadScreen.tsx +319 -122
  203. package/src/i18n/index.ts +81 -0
  204. package/src/i18n/languages.ts +106 -0
  205. package/src/i18n/strings/de.ts +78 -0
  206. package/src/i18n/strings/en.ts +94 -0
  207. package/src/i18n/strings/es.ts +77 -0
  208. package/src/i18n/strings/fr.ts +78 -0
  209. package/src/i18n/strings/hi.ts +77 -0
  210. package/src/i18n/strings/it.ts +77 -0
  211. package/src/i18n/strings/ja.ts +77 -0
  212. package/src/i18n/strings/ko.ts +76 -0
  213. package/src/i18n/strings/nl.ts +77 -0
  214. package/src/i18n/strings/pl.ts +77 -0
  215. package/src/i18n/strings/pt.ts +77 -0
  216. package/src/i18n/strings/ru.ts +77 -0
  217. package/src/i18n/strings/tr.ts +77 -0
  218. package/src/i18n/strings/zh.ts +75 -0
  219. package/src/index.tsx +9 -0
  220. package/src/theme.ts +165 -18
  221. package/src/types.ts +56 -2
  222. package/src/unread.ts +91 -0
  223. package/src/useSupportThreads.ts +392 -0
  224. package/src/utils.ts +48 -10
@@ -1,18 +1,76 @@
1
- import { useState } from 'react';
2
- import { KeyboardAvoidingView, Platform, Text, TextInput, View } from 'react-native';
1
+ import { useEffect, useRef, useState } from 'react';
2
+ import {
3
+ Animated,
4
+ Easing,
5
+ KeyboardAvoidingView,
6
+ Platform,
7
+ Text,
8
+ TextInput,
9
+ View,
10
+ } from 'react-native';
11
+ import type { Translator } from '../../i18n';
3
12
  import type { SupportTheme } from '../../theme';
4
13
  import type { QueryType } from '../../types';
5
- import { QUERY_TYPE_LABEL, USER_MESSAGE_MAX, USER_MESSAGE_MIN } from '../../types';
14
+ import { USER_MESSAGE_MAX, USER_MESSAGE_MIN } from '../../types';
6
15
  import { CheckIcon, Chevron } from '../icons';
7
- import { PressableRow, PrimaryButton, textStyles } from '../primitives';
16
+ import {
17
+ IconButton,
18
+ PrimaryButton,
19
+ textStyles,
20
+ TypeGlyph,
21
+ } from '../primitives';
22
+
23
+ /** Scales in once on success — the only celebratory motion in the SDK. */
24
+ function SentMark({ theme }: { theme: SupportTheme }) {
25
+ const scale = useRef(new Animated.Value(0.6)).current;
26
+ const opacity = useRef(new Animated.Value(0)).current;
27
+
28
+ useEffect(() => {
29
+ Animated.parallel([
30
+ Animated.timing(scale, {
31
+ toValue: 1,
32
+ duration: 320,
33
+ easing: Easing.bezier(0.16, 1, 0.3, 1),
34
+ useNativeDriver: true,
35
+ }),
36
+ Animated.timing(opacity, {
37
+ toValue: 1,
38
+ duration: 200,
39
+ easing: Easing.out(Easing.cubic),
40
+ useNativeDriver: true,
41
+ }),
42
+ ]).start();
43
+ }, [scale, opacity]);
44
+
45
+ return (
46
+ <Animated.View
47
+ style={{
48
+ width: 56,
49
+ height: 56,
50
+ borderRadius: 28,
51
+ backgroundColor: theme.colors.statusResolvedBg,
52
+ borderWidth: 1,
53
+ borderColor: theme.colors.statusResolved,
54
+ alignItems: 'center',
55
+ justifyContent: 'center',
56
+ opacity,
57
+ transform: [{ scale }],
58
+ }}
59
+ >
60
+ <CheckIcon color={theme.colors.statusResolved} size={20} />
61
+ </Animated.View>
62
+ );
63
+ }
8
64
 
9
65
  export function ComposeScreen({
10
66
  theme,
67
+ strings,
11
68
  type,
12
69
  onBack,
13
70
  onSubmit,
14
71
  }: {
15
72
  theme: SupportTheme;
73
+ strings: Translator;
16
74
  type: QueryType;
17
75
  onBack: () => void;
18
76
  /** Resolves null on success, or a user-facing error message. */
@@ -27,6 +85,7 @@ export function ComposeScreen({
27
85
  const valid =
28
86
  trimmed.length >= USER_MESSAGE_MIN && trimmed.length <= USER_MESSAGE_MAX;
29
87
  const overLimit = message.length > USER_MESSAGE_MAX;
88
+ const tooShort = trimmed.length > 0 && trimmed.length < USER_MESSAGE_MIN;
30
89
 
31
90
  async function handleSubmit() {
32
91
  if (!valid || submitting) return;
@@ -40,26 +99,27 @@ export function ComposeScreen({
40
99
 
41
100
  if (sent) {
42
101
  return (
43
- <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', gap: 12, padding: 24 }}>
44
- <View
45
- style={{
46
- width: 40,
47
- height: 40,
48
- borderRadius: 20,
49
- borderWidth: 1,
50
- borderColor: theme.colors.statusResolved,
51
- alignItems: 'center',
52
- justifyContent: 'center',
53
- }}
54
- >
55
- <CheckIcon color={theme.colors.statusResolved} size={14} />
56
- </View>
57
- <Text style={textStyles.body(theme)}>Sent</Text>
102
+ <View
103
+ style={{
104
+ flex: 1,
105
+ alignItems: 'center',
106
+ justifyContent: 'center',
107
+ gap: 14,
108
+ paddingHorizontal: 32,
109
+ paddingBottom: 40,
110
+ }}
111
+ >
112
+ <SentMark theme={theme} />
113
+ <Text style={textStyles.title(theme)}>{strings.t('compose.sent')}</Text>
58
114
  <Text style={[textStyles.secondary(theme), { textAlign: 'center' }]}>
59
- We&apos;ll reply here. You&apos;ll see the thread under Open.
115
+ {strings.t('compose.sentHint')}
60
116
  </Text>
61
- <View style={{ marginTop: 8 }}>
62
- <PrimaryButton label="Done" onPress={onBack} theme={theme} />
117
+ <View style={{ marginTop: 6 }}>
118
+ <PrimaryButton
119
+ label={strings.t('compose.done')}
120
+ onPress={onBack}
121
+ theme={theme}
122
+ />
63
123
  </View>
64
124
  </View>
65
125
  );
@@ -70,25 +130,31 @@ export function ComposeScreen({
70
130
  style={{ flex: 1 }}
71
131
  behavior={Platform.OS === 'ios' ? 'padding' : undefined}
72
132
  >
73
- {/* Header: back + read-only chosen type */}
133
+ {/* Header: back + the chosen type */}
74
134
  <View
75
135
  style={{
76
136
  flexDirection: 'row',
77
137
  alignItems: 'center',
78
- gap: 8,
138
+ gap: 10,
79
139
  paddingHorizontal: 12,
80
- paddingBottom: 12,
140
+ paddingBottom: 14,
81
141
  }}
82
142
  >
83
- <PressableRow
143
+ <IconButton
84
144
  onPress={onBack}
85
145
  theme={theme}
86
- accessibilityLabel="Back"
87
- style={{ padding: 6, borderRadius: theme.radii.control }}
146
+ accessibilityLabel={strings.t('compose.back')}
147
+ size={32}
88
148
  >
89
149
  <Chevron color={theme.colors.textSecondary} direction="left" size={12} />
90
- </PressableRow>
91
- <Text style={textStyles.title(theme)}>{QUERY_TYPE_LABEL[type]}</Text>
150
+ </IconButton>
151
+ <TypeGlyph type={type} theme={theme} size={32} />
152
+ <View style={{ flex: 1, gap: 1 }}>
153
+ <Text style={textStyles.heading(theme)}>
154
+ {strings.t(`type.${type}`)}
155
+ </Text>
156
+ <Text style={textStyles.meta(theme)}>{strings.t(`sub.${type}`)}</Text>
157
+ </View>
92
158
  </View>
93
159
 
94
160
  <View style={{ flex: 1, paddingHorizontal: 16 }}>
@@ -100,62 +166,62 @@ export function ComposeScreen({
100
166
  }}
101
167
  multiline
102
168
  autoFocus
103
- placeholder={
104
- type === 'bug_report'
105
- ? 'What happened, and what did you expect?'
106
- : type === 'feature_request'
107
- ? 'What would you like to see?'
108
- : 'What should we know?'
109
- }
169
+ editable={!submitting}
170
+ placeholder={strings.t(`prompt.${type}`)}
110
171
  placeholderTextColor={theme.colors.textTertiary}
111
172
  style={{
112
- minHeight: 120,
113
- maxHeight: 220,
173
+ minHeight: 140,
174
+ maxHeight: 240,
114
175
  borderWidth: 1,
115
176
  borderColor: theme.colors.border,
116
- borderRadius: theme.radii.control,
177
+ borderRadius: theme.radii.card,
117
178
  backgroundColor: theme.colors.surface,
118
179
  color: theme.colors.textPrimary,
119
- fontSize: 14,
120
- lineHeight: 20,
121
- padding: 12,
180
+ fontSize: 15,
181
+ lineHeight: 21,
182
+ padding: 14,
122
183
  textAlignVertical: 'top',
123
184
  }}
124
185
  />
186
+
125
187
  <View
126
188
  style={{
127
189
  flexDirection: 'row',
128
190
  alignItems: 'center',
129
- marginTop: 8,
130
- gap: 12,
191
+ gap: 10,
192
+ paddingTop: 10,
193
+ paddingHorizontal: 2,
194
+ minHeight: 20,
131
195
  }}
132
196
  >
197
+ {failedMessage !== null ? (
198
+ <Text style={{ fontSize: 12, color: theme.colors.statusDanger }}>
199
+ {failedMessage}
200
+ </Text>
201
+ ) : tooShort ? (
202
+ <Text style={textStyles.meta(theme)}>
203
+ {strings.t('compose.minChars', { count: USER_MESSAGE_MIN })}
204
+ </Text>
205
+ ) : null}
133
206
  <Text
134
207
  style={[
135
208
  textStyles.meta(theme),
209
+ { marginLeft: 'auto' },
136
210
  overLimit && { color: theme.colors.statusDanger },
137
211
  ]}
138
212
  >
139
213
  {message.length}/{USER_MESSAGE_MAX}
140
214
  </Text>
141
- {trimmed.length > 0 && trimmed.length < USER_MESSAGE_MIN && (
142
- <Text style={textStyles.meta(theme)}>
143
- At least {USER_MESSAGE_MIN} characters
144
- </Text>
145
- )}
146
- {failedMessage !== null && (
147
- <Text style={{ fontSize: 11, color: theme.colors.statusDanger }}>
148
- {failedMessage}
149
- </Text>
150
- )}
151
- <View style={{ marginLeft: 'auto' }}>
152
- <PrimaryButton
153
- label={submitting ? 'Sending…' : 'Send'}
154
- onPress={handleSubmit}
155
- disabled={!valid || submitting}
156
- theme={theme}
157
- />
158
- </View>
215
+ </View>
216
+
217
+ <View style={{ paddingTop: 12 }}>
218
+ <PrimaryButton
219
+ label={strings.t(submitting ? 'compose.sending' : 'compose.send')}
220
+ onPress={handleSubmit}
221
+ disabled={!valid || submitting}
222
+ theme={theme}
223
+ fullWidth
224
+ />
159
225
  </View>
160
226
  </View>
161
227
  </KeyboardAvoidingView>