Skip to content

Commit 7a0058a

Browse files
committed
sharing: Enable users to delete attachments before sending.
1 parent 4e946fe commit 7a0058a

File tree

2 files changed

+89
-31
lines changed

2 files changed

+89
-31
lines changed

src/sharing/ShareToPm.js

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,21 @@ import { View, ImageBackground, ScrollView, Modal, FlatList, Text } from 'react-
44
import type { RouteProp } from '../react-navigation';
55
import type { SharingNavigationProp } from './SharingScreen';
66
import * as NavigationService from '../nav/NavigationService';
7-
import type { Dispatch, Auth, GetText, SharedData, UserId } from '../types';
7+
import type { Dispatch, Auth, GetText, SharedData, UserId, Content } from '../types';
88
import { BRAND_COLOR, createStyleSheet } from '../styles';
99
import { TranslationContext } from '../boot/TranslationProvider';
1010
import { connect } from '../react-redux';
11-
import { ZulipButton, Input, Label } from '../common';
11+
import { ZulipButton, Input, Label, ComponentWithOverlay } from '../common';
1212
import UserItem from '../users/UserItem';
1313
import { getAuth } from '../selectors';
1414
import { navigateBack, replaceWithChat } from '../nav/navActions';
1515
import ChooseRecipientsScreen from './ChooseRecipientsScreen';
1616
import { handleSend } from './send';
1717
import { pmNarrowFromRecipients } from '../utils/narrow';
18+
import { showToast } from '../utils/info';
1819
import { pmKeyRecipientsFromIds } from '../utils/recipient';
1920
import { getOwnUserId } from '../users/userSelectors';
20-
import { IconAttachment } from '../common/Icons';
21+
import { IconAttachment, IconCancel } from '../common/Icons';
2122

2223
const styles = createStyleSheet({
2324
wrapper: {
@@ -80,6 +81,7 @@ type State = $ReadOnly<{|
8081
message: string,
8182
choosingRecipients: boolean,
8283
sending: boolean,
84+
content: Array<Content>,
8385
|}>;
8486

8587
class ShareToPm extends React.Component<Props, State> {
@@ -93,6 +95,7 @@ class ShareToPm extends React.Component<Props, State> {
9395
message: sharedData.isText ? sharedData.sharedText : '',
9496
choosingRecipients: false,
9597
sending: false,
98+
content: sharedData.isText ? [] : sharedData.content,
9699
};
97100
})();
98101

@@ -114,6 +117,11 @@ class ShareToPm extends React.Component<Props, State> {
114117
const { auth } = this.props;
115118
const { sharedData } = this.props.route.params;
116119
const { selectedRecipients, message } = this.state;
120+
121+
if (!sharedData.isText) {
122+
sharedData.content = this.state.content;
123+
}
124+
117125
const data = { selectedRecipients, message, sharedData, type: 'pm' };
118126

119127
this.setSending();
@@ -152,6 +160,16 @@ class ShareToPm extends React.Component<Props, State> {
152160
return selectedRecipients.length > 0;
153161
};
154162

163+
deleteItem = toDelete => {
164+
const content = [...this.state.content];
165+
const filteredItems = content.filter(item => item.url !== toDelete.url);
166+
this.setState({ content: filteredItems });
167+
if (filteredItems.length === 0) {
168+
showToast('Cancelled Share');
169+
this.finishShare();
170+
}
171+
};
172+
155173
renderUsersPreview = () => {
156174
const { selectedRecipients } = this.state;
157175

@@ -165,17 +183,25 @@ class ShareToPm extends React.Component<Props, State> {
165183
return preview;
166184
};
167185

168-
renderItem = ({ item, index, separators }) =>
169-
item.type.startsWith('image') ? (
170-
<ImageBackground source={{ uri: item.url }} style={styles.imagePreview}>
171-
<Text style={styles.previewText}>{item.fileName}</Text>
172-
</ImageBackground>
173-
) : (
174-
<View style={styles.imagePreview}>
175-
<IconAttachment size={200} color={BRAND_COLOR} />
176-
<Text style={styles.previewText}>{item.fileName}</Text>
177-
</View>
178-
);
186+
renderItem = ({ item, index, separators }) => (
187+
<ComponentWithOverlay
188+
overlaySize={20}
189+
overlayColor="white"
190+
overlayPosition="bottom-right"
191+
overlay={<IconCancel color="gray" size={20} onPress={() => this.deleteItem(item)} />}
192+
>
193+
{item.type.startsWith('image') ? (
194+
<ImageBackground source={{ uri: item.url }} style={styles.imagePreview}>
195+
<Text style={styles.previewText}>{item.fileName}</Text>
196+
</ImageBackground>
197+
) : (
198+
<View style={styles.imagePreview}>
199+
<IconAttachment size={200} color={BRAND_COLOR} />
200+
<Text style={styles.previewText}>{item.fileName}</Text>
201+
</View>
202+
)}
203+
</ComponentWithOverlay>
204+
);
179205

180206
render() {
181207
const { message, choosingRecipients, sending } = this.state;
@@ -198,7 +224,7 @@ class ShareToPm extends React.Component<Props, State> {
198224
<></>
199225
) : (
200226
<FlatList
201-
data={sharedData.content}
227+
data={this.state.content}
202228
renderItem={this.renderItem}
203229
keyExtractor={i => i.url}
204230
horizontal

src/sharing/ShareToStream.js

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,22 @@ import { View, ImageBackground, ScrollView, FlatList, Text } from 'react-native'
44
import type { SharingNavigationProp } from './SharingScreen';
55
import type { RouteProp } from '../react-navigation';
66
import * as NavigationService from '../nav/NavigationService';
7-
import type { Dispatch, Subscription, Auth, GetText, SharedData } from '../types';
7+
import type { Dispatch, Subscription, Auth, GetText, SharedData, Content } from '../types';
88
import { BRAND_COLOR, createStyleSheet } from '../styles';
99
import { TranslationContext } from '../boot/TranslationProvider';
1010
import { connect } from '../react-redux';
11-
import { ZulipButton, Input } from '../common';
11+
import { ZulipButton, Input, ComponentWithOverlay } from '../common';
1212
import { getSubscriptionsById } from '../subscriptions/subscriptionSelectors';
1313
import StreamAutocomplete from '../autocomplete/StreamAutocomplete';
1414
import TopicAutocomplete from '../autocomplete/TopicAutocomplete';
1515
import AnimatedScaleComponent from '../animation/AnimatedScaleComponent';
1616
import { streamNarrow } from '../utils/narrow';
17+
import { showToast } from '../utils/info';
1718
import { getAuth } from '../selectors';
1819
import { navigateBack, replaceWithChat } from '../nav/navActions';
1920
import { fetchTopicsForStream } from '../topics/topicActions';
2021
import { handleSend } from './send';
21-
import { IconAttachment } from '../common/Icons';
22+
import { IconAttachment, IconCancel } from '../common/Icons';
2223

2324
const styles = createStyleSheet({
2425
wrapper: {
@@ -50,12 +51,19 @@ const styles = createStyleSheet({
5051
left: 0,
5152
right: 0,
5253
},
54+
cross: {
55+
backgroundColor: '#000000a0',
56+
position: 'absolute',
57+
right: 0,
58+
top: 0,
59+
height: 20,
60+
width: 20,
61+
},
5362
});
5463

5564
type Props = $ReadOnly<{|
5665
navigation: SharingNavigationProp<'share-to-stream'>,
5766
route: RouteProp<'share-to-stream', {| sharedData: SharedData |}>,
58-
5967
dispatch: Dispatch,
6068
subscriptions: Map<number, Subscription>,
6169
auth: Auth,
@@ -68,6 +76,7 @@ type State = $ReadOnly<{|
6876
isStreamFocused: boolean,
6977
isTopicFocused: boolean,
7078
sending: boolean,
79+
content: Array<Content>,
7180
|}>;
7281

7382
class ShareToStream extends React.Component<Props, State> {
@@ -81,6 +90,7 @@ class ShareToStream extends React.Component<Props, State> {
8190
isStreamFocused: false,
8291
isTopicFocused: false,
8392
sending: false,
93+
content: this.props.route.params.sharedData.content || [],
8494
};
8595

8696
setSending = () => {
@@ -136,6 +146,10 @@ class ShareToStream extends React.Component<Props, State> {
136146
const { sharedData } = this.props.route.params;
137147
const data = { stream, topic, message, sharedData, type: 'stream' };
138148

149+
if (!sharedData.isText) {
150+
sharedData.content = this.state.content;
151+
}
152+
139153
this.setSending();
140154
try {
141155
await handleSend(data, auth, _);
@@ -166,17 +180,35 @@ class ShareToStream extends React.Component<Props, State> {
166180
return stream !== '' && topic !== '' && message !== '';
167181
};
168182

169-
renderItem = ({ item, index, separators }) =>
170-
item.type.startsWith('image') ? (
171-
<ImageBackground source={{ uri: item.url }} style={styles.imagePreview}>
172-
<Text style={styles.previewText}>{item.fileName}</Text>
173-
</ImageBackground>
174-
) : (
175-
<View style={styles.imagePreview}>
176-
<IconAttachment size={200} color={BRAND_COLOR} />
177-
<Text style={styles.previewText}>{item.fileName}</Text>
178-
</View>
179-
);
183+
deleteItem = toDelete => {
184+
const content = [...this.state.content];
185+
const filteredItems = content.filter(item => item.url !== toDelete.url);
186+
this.setState({ content: filteredItems });
187+
if (filteredItems.length === 0) {
188+
showToast('Cancelled Share');
189+
this.finishShare();
190+
}
191+
};
192+
193+
renderItem = ({ item, index, separators }) => (
194+
<ComponentWithOverlay
195+
overlaySize={20}
196+
overlayColor="white"
197+
overlayPosition="bottom-right"
198+
overlay={<IconCancel color="gray" size={20} onPress={() => this.deleteItem(item)} />}
199+
>
200+
{item.type.startsWith('image') ? (
201+
<ImageBackground source={{ uri: item.url }} style={styles.imagePreview}>
202+
<Text style={styles.previewText}>{item.fileName}</Text>
203+
</ImageBackground>
204+
) : (
205+
<View style={styles.imagePreview}>
206+
<IconAttachment size={200} color={BRAND_COLOR} />
207+
<Text style={styles.previewText}>{item.fileName}</Text>
208+
</View>
209+
)}
210+
</ComponentWithOverlay>
211+
);
180212

181213
render() {
182214
const { sharedData } = this.props.route.params;
@@ -191,7 +223,7 @@ class ShareToStream extends React.Component<Props, State> {
191223
<></>
192224
) : (
193225
<FlatList
194-
data={sharedData.content}
226+
data={this.state.content}
195227
renderItem={this.renderItem}
196228
keyExtractor={i => i.url}
197229
horizontal

0 commit comments

Comments
 (0)