Skip to content

Commit

Permalink
#290 Alphabetized Subscription Headers (#716)
Browse files Browse the repository at this point in the history
Co-authored-by: Gavin Kasdorf <127079571+gkasdorf@users.noreply.github.com>
  • Loading branch information
joshua-davis-rose and gkasdorf authored Jul 17, 2023
1 parent 75df6ce commit 0753f55
Showing 1 changed file with 68 additions and 10 deletions.
78 changes: 68 additions & 10 deletions src/components/screens/Traverse/TraverseScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useMemo, useState } from "react";
import { StyleSheet, View } from "react-native";
import { ScrollView, Text, useTheme } from "native-base";
import { CommunityView } from "lemmy-js-client";
import { useTranslation } from "react-i18next";
Expand All @@ -13,6 +14,12 @@ import { selectCurrentAccount } from "../../../slices/accounts/accountsSlice";
import { useAppSelector } from "../../../../store";
import { getCommunityFullName } from "../../../helpers/LemmyHelpers";

// Used to create an alpha-indexed list of subscriptions
interface IndexedTraverseItem {
index?: string; // if this is an alpha-index, what's the index?
subscription?: CommunityView; // if not, what's the subscription?
}

function TraverseScreen() {
const { t } = useTranslation();
const theme = useTheme();
Expand All @@ -25,6 +32,30 @@ function TraverseScreen() {
useAppSelector(selectFavorites).favorites[
`${currentAccount.username}@${currentAccount.instance}`
];
const hasFavorites = favorites && Object.keys(favorites).length > 0;

// If there are favorites then indexing should start at 3, otherwise 2
const startingIndex = hasFavorites ? 3 : 2;
// If there are favorites then we'll add it as a numeric index
const headerNumericIndexes: number[] = [];
let lastIndexAlpha: string;
const indexedTraverseItems: IndexedTraverseItem[] =
traverse.subscriptions.reduce((accumulator, subscription) => {
const { name } = subscription.community;
// get the first letter of the name
const firstLetter = name.at(0).toLocaleUpperCase();
if (lastIndexAlpha !== firstLetter) {
// track the current alpha index
lastIndexAlpha = firstLetter;
// add the new alpha-index
accumulator.push({ index: firstLetter });
// keep track of the numeric index for the ScrollView sticky headers
headerNumericIndexes.push(accumulator.length - 1 + startingIndex);
}
// add the subscription
accumulator.push({ subscription });
return accumulator;
}, []);

const header = useMemo(
() => <SearchBar query={term} setQuery={setTerm} autoFocus={false} />,
Expand All @@ -36,13 +67,27 @@ function TraverseScreen() {
return favorites ? communityFullName in favorites : false;
};

const item = (community: CommunityView) => {
if (term && !community.community.name.includes(term)) return null;
const item = (traverseItem: IndexedTraverseItem) => {
const { index, subscription } = traverseItem;
if (index)
return (
<View backgroundColor={theme.colors.app.bg}>
<Text
style={styles.alphaIndexHeaderText}
fontSize="xl"
fontWeight="semibold"
key={traverseItem.index}
>
{traverseItem.index}
</Text>
</View>
);
if (term && !subscription?.community.name.includes(term)) return null;
return (
<TraverseItem
community={community}
isFavorite={favorites ? isFavorite(community) : false}
key={community.community.id}
community={subscription}
isFavorite={favorites ? isFavorite(subscription) : false}
key={subscription?.community.id}
/>
);
};
Expand All @@ -62,17 +107,21 @@ function TraverseScreen() {
/>
}
keyboardShouldPersistTaps="handled"
stickyHeaderIndices={headerNumericIndexes}
>
{/* Index 0 */}
{header}

{favorites && Object.keys(favorites).length > 0 && (
<>
{hasFavorites && (
/* Index 1 */
<View flex={1}>
<Text textAlign="center">{t("Favorites")}</Text>
{traverse.subscriptions
.filter((c) => isFavorite(c))
.map((c) => item(c))}
</>
.map((c) => item({ subscription: c }))}
</View>
)}
{/* Index 1 OR 2 */}
<Text textAlign="center">{t("Subscriptions")}</Text>
{traverse.subscriptions.length === 0 ? (
<Text
Expand All @@ -84,10 +133,19 @@ function TraverseScreen() {
{t("traverse.noSubscriptions")}
</Text>
) : (
traverse.subscriptions.map((c) => item(c))
/* Index 2+ OR 3+ if there are favorites */
indexedTraverseItems.map((c) => item(c))
)}
</ScrollView>
);
}

const styles = StyleSheet.create({
alphaIndexHeaderText: {
paddingBottom: 10,
paddingTop: 10,
paddingStart: 18,
},
});

export default TraverseScreen;

0 comments on commit 0753f55

Please sign in to comment.