Skip to content

Commit 4cd5091

Browse files
committed
changes
1 parent 205ad0a commit 4cd5091

4 files changed

Lines changed: 337 additions & 54 deletions

File tree

js/locale/en.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,12 @@
9494
"no_hot_topics": "No hot topics found for this site.",
9595
"discover_communities": "Communities",
9696
"discover_pick_tag": "What are you interested in?",
97+
"discover_pick_tag_description": "See what people have been discussing in Discourse communities recently and join the ones that most match your interests.",
9798
"discover_explore_more": "Explore another topic",
98-
"discover_communities_section": "COMMUNITIES",
99-
"discover_topics_section": "TOPICS",
99+
"discover_communities_section": "%{tag} Communities",
100+
"discover_topics_section": "Recent Discussions in %{tag}",
100101
"discover_see_all_communities": "See all communities",
102+
"discover_community_directory": "Community Directory",
101103
"remove_from_home_screen": "Remove",
102104
"preview": "Preview",
103105
"community_recent_topics": "Hot Topics",

js/screens/DiscoverScreen.js

Lines changed: 189 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
} from 'react-native';
2020

2121
import DiscoverComponents from './DiscoverScreenComponents';
22+
import { PRIMARY_TAGS } from './DiscoverScreenComponents/TagSplash';
2223
import { ThemeContext } from '../ThemeContext';
2324
import Site from '../site';
2425
import i18n from 'i18n-js';
@@ -114,6 +115,11 @@ class DiscoverScreen extends React.Component {
114115
hotTopicsPage: 1,
115116
hotTopicsHasMore: false,
116117

118+
// All communities
119+
communitiesFilter: null, // null = all, 'recent' = order by latest, otherwise a tag
120+
allCommunities: [],
121+
allCommunitiesLoading: false,
122+
117123
// Community detail
118124
activeCommunity: null,
119125
communityTopics: [],
@@ -233,7 +239,11 @@ class DiscoverScreen extends React.Component {
233239
this.setState({
234240
view: VIEWS.ALL_COMMUNITIES,
235241
previousView: VIEWS.SPLASH,
242+
communitiesFilter: tag,
243+
allCommunities: [],
244+
allCommunitiesLoading: true,
236245
});
246+
this._fetchAllCommunities(tag);
237247
}
238248
})
239249
.catch(e => {
@@ -534,10 +544,89 @@ class DiscoverScreen extends React.Component {
534544
}
535545

536546
_goToAllCommunities() {
547+
const filter = this.state.activeTag;
548+
if (this.state.tagCommunitiesLoading) {
549+
this.setState({
550+
view: VIEWS.ALL_COMMUNITIES,
551+
previousView: VIEWS.TAG_DETAIL,
552+
communitiesFilter: filter,
553+
allCommunities: [],
554+
allCommunitiesLoading: true,
555+
});
556+
this._fetchAllCommunities(filter);
557+
} else {
558+
this.setState({
559+
view: VIEWS.ALL_COMMUNITIES,
560+
previousView: VIEWS.TAG_DETAIL,
561+
communitiesFilter: filter,
562+
allCommunities: this.state.tagCommunities,
563+
allCommunitiesLoading: false,
564+
});
565+
}
566+
}
567+
568+
_goToAllCommunitiesFromSplash(filter = null) {
537569
this.setState({
538570
view: VIEWS.ALL_COMMUNITIES,
539-
previousView: VIEWS.TAG_DETAIL,
571+
previousView: VIEWS.SPLASH,
572+
communitiesFilter: filter,
573+
allCommunities: [],
574+
allCommunitiesLoading: true,
575+
});
576+
this._fetchAllCommunities(filter);
577+
}
578+
579+
_selectFromTagDetail(key) {
580+
if (key === null) {
581+
this._goToAllCommunitiesFromSplash(null);
582+
} else if (key === 'recent') {
583+
this._goToAllCommunitiesFromSplash('recent');
584+
} else if (key !== this.state.activeTag) {
585+
this.onSelectTag(key);
586+
}
587+
}
588+
589+
_selectCommunitiesFilter(filter) {
590+
if (filter === this.state.communitiesFilter) {
591+
return;
592+
}
593+
this.setState({
594+
communitiesFilter: filter,
595+
allCommunities: [],
596+
allCommunitiesLoading: true,
540597
});
598+
this._fetchAllCommunities(filter);
599+
}
600+
601+
_fetchAllCommunities(filter) {
602+
let searchString;
603+
if (filter === 'recent') {
604+
searchString = '#discover order:latest_topic';
605+
} else if (filter) {
606+
searchString = `#discover #${filter} order:featured`;
607+
} else {
608+
searchString = '#discover order:featured';
609+
}
610+
const url = `${this.baseUrl}${encodeURIComponent(searchString)}&page=1`;
611+
612+
fetch(url)
613+
.then(res => res.json())
614+
.then(json => {
615+
if (filter !== this.state.communitiesFilter) {
616+
return; // stale response
617+
}
618+
this.setState({
619+
allCommunities: json.topics || [],
620+
allCommunitiesLoading: false,
621+
});
622+
})
623+
.catch(e => {
624+
console.log(e);
625+
if (filter !== this.state.communitiesFilter) {
626+
return;
627+
}
628+
this.setState({ allCommunitiesLoading: false });
629+
});
541630
}
542631

543632
// ── Render ──
@@ -582,6 +671,8 @@ class DiscoverScreen extends React.Component {
582671
tags={this.state.splashTags}
583672
loading={this.state.splashTagsLoading}
584673
onSelectTag={tag => this.onSelectTag(tag)}
674+
onSelectRecent={() => this._goToAllCommunitiesFromSplash('recent')}
675+
onSeeAllCommunities={() => this._goToAllCommunitiesFromSplash()}
585676
/>
586677
</View>
587678
);
@@ -664,12 +755,12 @@ class DiscoverScreen extends React.Component {
664755

665756
_renderTagDetailView(tabBarHeight) {
666757
const theme = this.context;
667-
const tagLabel = this._formatTagLabel(this.state.activeTag);
758+
const activeTagLabel = this.state.activeTag;
668759

669760
const headerComponent = (
670761
<View>
671762
<Text style={[styles.sectionLabel, { color: theme.graySubtitle }]}>
672-
{i18n.t('discover_communities_section')}
763+
{i18n.t('discover_communities_section', { tag: activeTagLabel })}
673764
</Text>
674765
<DiscoverComponents.CommunityCarousel
675766
communities={this.state.tagCommunities}
@@ -691,17 +782,17 @@ class DiscoverScreen extends React.Component {
691782
</Text>
692783
</TouchableHighlight>
693784
<Text style={[styles.sectionLabel, { color: theme.graySubtitle }]}>
694-
{i18n.t('discover_topics_section')}
785+
{i18n.t('discover_topics_section', { tag: activeTagLabel })}
695786
</Text>
696787
</View>
697788
);
698789

699790
return (
700791
<View style={styles.container}>
701-
<DiscoverComponents.TagDetailHeader
702-
title={tagLabel}
703-
onBack={() => this._navigateBack()}
704-
/>
792+
{this._renderSearchBox()}
793+
{this._renderCommunitiesTagBar(this.state.activeTag, key =>
794+
this._selectFromTagDetail(key),
795+
)}
705796
<DiscoverComponents.DiscoverTopicList
706797
topics={this.state.hotTopics}
707798
loading={this.state.hotTopicsLoading}
@@ -723,26 +814,24 @@ class DiscoverScreen extends React.Component {
723814

724815
_renderAllCommunitiesView(tabBarHeight) {
725816
const theme = this.context;
726-
const tagLabel = this._formatTagLabel(this.state.activeTag);
727-
const title = `${tagLabel} ${i18n.t('discover_communities')}`;
728817

729-
const emptyComponent = this.state.tagCommunitiesLoading ? (
818+
const emptyComponent = this.state.allCommunitiesLoading ? (
730819
<View style={styles.emptyResult}>
731820
<ActivityIndicator size="large" color={theme.grayUI} />
732821
</View>
733822
) : null;
734823

735824
return (
736825
<View style={styles.container}>
737-
<DiscoverComponents.TagDetailHeader
738-
title={title}
739-
onBack={() => this._navigateBack()}
740-
/>
826+
{this._renderSearchBox()}
827+
{this._renderCommunitiesTagBar(this.state.communitiesFilter, key =>
828+
this._selectCommunitiesFilter(key),
829+
)}
741830
<FlatList
742831
keyExtractor={item => String(item.id || item.featured_link)}
743832
ListEmptyComponent={emptyComponent}
744833
contentContainerStyle={{ paddingBottom: tabBarHeight }}
745-
data={this.state.tagCommunities}
834+
data={this.state.allCommunities}
746835
renderItem={({ item }) => this._renderSiteItem({ item })}
747836
extraData={this.state.selectionCount}
748837
keyboardDismissMode="on-drag"
@@ -751,6 +840,68 @@ class DiscoverScreen extends React.Component {
751840
);
752841
}
753842

843+
_renderCommunitiesTagBar(activeKey, onSelect) {
844+
const theme = this.context;
845+
846+
const primaryTagSet = new Set(PRIMARY_TAGS.map(t => t.tag));
847+
const secondaryTags = (this.state.splashTags || [])
848+
.filter(tag => !primaryTagSet.has(tag))
849+
.sort((a, b) => a.localeCompare(b));
850+
851+
const entries = [
852+
{ key: null, label: i18n.t('discover_all') },
853+
...PRIMARY_TAGS.map(({ tag, label }) => ({
854+
key: tag,
855+
label: label,
856+
})),
857+
{ key: 'recent', label: i18n.t('discover_recent') },
858+
...secondaryTags.map(tag => ({
859+
key: tag,
860+
label: tag,
861+
})),
862+
];
863+
864+
return (
865+
<ScrollView
866+
horizontal={true}
867+
showsHorizontalScrollIndicator={false}
868+
style={styles.tagBar}
869+
contentContainerStyle={styles.tagBarContent}
870+
keyboardShouldPersistTaps="handled"
871+
>
872+
{entries.map(entry => {
873+
const isSelected = entry.key === activeKey;
874+
return (
875+
<TouchableHighlight
876+
key={entry.key === null ? '__all__' : entry.key}
877+
accessibilityRole="button"
878+
accessibilityLabel={entry.label}
879+
style={{
880+
...styles.tagBarItem,
881+
borderColor: theme.grayUILight,
882+
backgroundColor: isSelected
883+
? theme.grayBackground
884+
: theme.background,
885+
}}
886+
underlayColor={theme.grayBackground}
887+
onPress={() => onSelect(entry.key)}
888+
>
889+
<Text
890+
style={{
891+
...styles.tagBarItemText,
892+
color: theme.tagButtonTextColor,
893+
fontSize: this.state.largerUI ? 15 : 13,
894+
}}
895+
>
896+
{entry.label}
897+
</Text>
898+
</TouchableHighlight>
899+
);
900+
})}
901+
</ScrollView>
902+
);
903+
}
904+
754905
_renderCommunityDetailView(tabBarHeight) {
755906
const community = this.state.activeCommunity;
756907
if (!community) {
@@ -772,6 +923,7 @@ class DiscoverScreen extends React.Component {
772923

773924
return (
774925
<View style={styles.container}>
926+
{this._renderSearchBox()}
775927
<DiscoverComponents.TagDetailHeader
776928
title={community.title}
777929
onBack={() => this._navigateBack()}
@@ -832,16 +984,6 @@ class DiscoverScreen extends React.Component {
832984
);
833985
}
834986

835-
_formatTagLabel(tag) {
836-
if (!tag) {
837-
return '';
838-
}
839-
return tag
840-
.split('-')
841-
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
842-
.join(' ');
843-
}
844-
845987
// ── Pagination ──
846988

847989
_fetchNextSearchPage() {
@@ -899,6 +1041,27 @@ const styles = StyleSheet.create({
8991041
paddingHorizontal: 16,
9001042
paddingTop: 16,
9011043
paddingBottom: 4,
1044+
textTransform: 'uppercase',
1045+
},
1046+
tagBar: {
1047+
flexGrow: 0,
1048+
flexShrink: 0,
1049+
paddingVertical: 8,
1050+
paddingHorizontal: 8,
1051+
},
1052+
tagBarContent: {
1053+
alignItems: 'center',
1054+
paddingRight: 16,
1055+
},
1056+
tagBarItem: {
1057+
paddingVertical: 8,
1058+
paddingHorizontal: 12,
1059+
borderRadius: 16,
1060+
borderWidth: StyleSheet.hairlineWidth,
1061+
marginHorizontal: 4,
1062+
},
1063+
tagBarItemText: {
1064+
fontWeight: '500',
9021065
},
9031066
seeAllButton: {
9041067
marginHorizontal: 16,

js/screens/DiscoverScreenComponents/TagDetailHeader.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const TagDetailHeader = props => {
2626
accessibilityLabel="Back"
2727
>
2828
<FontAwesome5
29-
name={'arrow-left'}
29+
name={'angle-left'}
3030
size={18}
3131
color={theme.grayTitle}
3232
iconStyle="solid"

0 commit comments

Comments
 (0)