Skip to content

Commit

Permalink
feat: Add keyword and instance filtering (#824)
Browse files Browse the repository at this point in the history
  • Loading branch information
gkasdorf authored Jul 23, 2023
1 parent 4ac8297 commit 0bcf905
Show file tree
Hide file tree
Showing 10 changed files with 504 additions and 14 deletions.
24 changes: 24 additions & 0 deletions Stack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ import { useAppSelector } from "./store";
import { truncateName } from "./src/helpers/TextHelper";
import ScreenGestureHandler from "./src/components/common/Navigation/ScreenGestureHandler";
import { ICON_MAP } from "./src/constants/IconMap";
import FiltersScreen from "./src/components/screens/Settings/Filters/FiltersScreen";
import KeywordsScreen from "./src/components/screens/Settings/Filters/KeywordsScreen";
import InstancesScreen from "./src/components/screens/Settings/Filters/InstancesScreen";

function CustomDrawerContent() {
const theme = useTheme();
Expand Down Expand Up @@ -351,6 +354,27 @@ function SettingsScreens(stack) {
freezeOnBlur: true,
}}
/>
<stack.Screen
name="Filters"
component={FiltersScreen}
options={{
title: t("Filters"),
}}
/>
<stack.Screen
name="Keywords"
component={KeywordsScreen}
options={{
tilte: t("Keywords"),
}}
/>
<stack.Screen
name="Instances"
component={InstancesScreen}
options={{
title: t("Instances"),
}}
/>
<stack.Screen
name="About"
component={AboutScreen}
Expand Down
2 changes: 2 additions & 0 deletions Start.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { ThemeOptionsArr, ThemeOptionsMap } from "./src/theme/themeOptions";
import Toast from "./src/components/common/Toast";
import { systemFontSettings } from "./src/theme/common";
import { loadFavorites } from "./src/slices/favorites/favoritesActions";
import { useFiltersStore } from "./src/stores/filters/filtersStore";

const logError = (e, info) => {
writeToLog(e.toString());
Expand Down Expand Up @@ -218,6 +219,7 @@ function Start({ onReady }: StartProps) {
dispatch(loadAccounts());
dispatch(loadFavorites());
setLoaded(true);
useFiltersStore.getState().init();
}

if (!accountsLoaded) {
Expand Down
52 changes: 52 additions & 0 deletions src/components/screens/Settings/Filters/FiltersScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from "react";
import { useTranslation } from "react-i18next";
import { ScrollView, useTheme } from "native-base";
import { StyleSheet } from "react-native";
import { TableView } from "@gkasdorf/react-native-tableview-simple";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import CSection from "../../../common/Table/CSection";
import CCell from "../../../common/Table/CCell";

interface IProps {
navigation: NativeStackNavigationProp<any>;
}

function FiltersScreen({ navigation }: IProps) {
const { t } = useTranslation();
const theme = useTheme();

return (
<ScrollView backgroundColor={theme.colors.app.bg} flex={1}>
<TableView style={styles.table}>
<CSection header={t("Haptics")}>
<CCell
cellStyle="RightDetail"
title={t("Keywords")}
backgroundColor={theme.colors.app.fg}
titleTextColor={theme.colors.app.textPrimary}
rightDetailColor={theme.colors.app.textSecondary}
accessory="DisclosureIndicator"
onPress={() => navigation.push("Keywords")}
/>
<CCell
cellStyle="RightDetail"
title={t("Instances")}
backgroundColor={theme.colors.app.fg}
titleTextColor={theme.colors.app.textPrimary}
rightDetailColor={theme.colors.app.textSecondary}
accessory="DisclosureIndicator"
onPress={() => navigation.push("Instances")}
/>
</CSection>
</TableView>
</ScrollView>
);
}

const styles = StyleSheet.create({
table: {
marginHorizontal: 15,
},
});

export default FiltersScreen;
131 changes: 131 additions & 0 deletions src/components/screens/Settings/Filters/InstancesScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import React, { useEffect, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { ScrollView, useTheme } from "native-base";
import { Alert, Button, StyleSheet } from "react-native";
import { TableView } from "@gkasdorf/react-native-tableview-simple";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import CSection from "../../../common/Table/CSection";
import CCell from "../../../common/Table/CCell";
import {
useFiltersStore,
useInstancesFilter,
} from "../../../../stores/filters/filtersStore";
import { getBaseUrl } from "../../../../helpers/LinkHelper";

interface IProps {
navigation: NativeStackNavigationProp<any>;
}

function InstanceOption({ instance }: { instance: string }) {
const filtersStore = useFiltersStore();
const theme = useTheme();
const { t } = useTranslation();

const onInstancePress = () => {
Alert.alert(
t("settings.filters.removeInstance"),
t("settings.filters.areYouSureInstance"),
[
{
text: t("Cancel"),
style: "cancel",
},
{
text: t("Remove"),
style: "destructive",
onPress: () => {
filtersStore.removeInstance(instance);
},
},
]
);
};

return (
<CCell
cellStyle="RightDetail"
title={instance}
backgroundColor={theme.colors.app.fg}
titleTextColor={theme.colors.app.textPrimary}
rightDetailColor={theme.colors.app.textSecondary}
accessory="DisclosureIndicator"
onPress={onInstancePress}
/>
);
}

function InstancesScreen({ navigation }: IProps) {
const { t } = useTranslation();
const theme = useTheme();

const filtersStore = useFiltersStore();
const instances = useInstancesFilter();

useEffect(() => {
navigation.setOptions({
// eslint-disable-next-line react/no-unstable-nested-components
headerRight: () => (
<Button
title={t("Add")}
onPress={onAddPress}
color={theme.colors.app.accent}
/>
),
});
}, []);

const onAddPress = () => {
Alert.prompt(
t("settings.filters.addInstance"),
t("settings.filters.enterAnInstance"),
[
{
text: t("Cancel"),
style: "cancel",
},
{
text: t("Save"),
style: "default",
onPress: (value?: string) => {
if (!value) return;

filtersStore.addInstance(getBaseUrl(value)).then();
},
},
]
);
};

const instanceOptions = useMemo(
() => instances.map((k) => <InstanceOption key={k} instance={k} />),
[instances]
);

return (
<ScrollView backgroundColor={theme.colors.app.bg} flex={1}>
<TableView style={styles.table}>
<CSection header={t("Instances").toUpperCase()}>
{instances.length < 1 ? (
<CCell
cellStyle="RightDetail"
title={t("settings.filters.noInstances")}
backgroundColor={theme.colors.app.fg}
titleTextColor={theme.colors.app.textPrimary}
rightDetailColor={theme.colors.app.textSecondary}
/>
) : (
instanceOptions
)}
</CSection>
</TableView>
</ScrollView>
);
}

const styles = StyleSheet.create({
table: {
marginHorizontal: 15,
},
});

export default InstancesScreen;
130 changes: 130 additions & 0 deletions src/components/screens/Settings/Filters/KeywordsScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import React, { useEffect, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { ScrollView, useTheme } from "native-base";
import { Alert, Button, StyleSheet } from "react-native";
import { TableView } from "@gkasdorf/react-native-tableview-simple";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import CSection from "../../../common/Table/CSection";
import CCell from "../../../common/Table/CCell";
import {
useFiltersStore,
useKeywordFilter,
} from "../../../../stores/filters/filtersStore";

interface IProps {
navigation: NativeStackNavigationProp<any>;
}

function KeywordOption({ keyword }: { keyword: string }) {
const filtersStore = useFiltersStore();
const theme = useTheme();
const { t } = useTranslation();

const onKeywordPress = () => {
Alert.alert(
t("settings.filters.removeKeyword"),
t("settings.filters.areYouSureKeyword"),
[
{
text: t("Cancel"),
style: "cancel",
},
{
text: t("Remove"),
style: "destructive",
onPress: () => {
filtersStore.removeKeyword(keyword);
},
},
]
);
};

return (
<CCell
cellStyle="RightDetail"
title={keyword}
backgroundColor={theme.colors.app.fg}
titleTextColor={theme.colors.app.textPrimary}
rightDetailColor={theme.colors.app.textSecondary}
accessory="DisclosureIndicator"
onPress={onKeywordPress}
/>
);
}

function KeywordsScreen({ navigation }: IProps) {
const { t } = useTranslation();
const theme = useTheme();

const filtersStore = useFiltersStore();
const keywords = useKeywordFilter();

useEffect(() => {
navigation.setOptions({
// eslint-disable-next-line react/no-unstable-nested-components
headerRight: () => (
<Button
title={t("Add")}
onPress={onAddPress}
color={theme.colors.app.accent}
/>
),
});
}, []);

const onAddPress = () => {
Alert.prompt(
t("settings.filters.addKeyword"),
t("settings.filters.enterAKeyword"),
[
{
text: t("Cancel"),
style: "cancel",
},
{
text: t("Save"),
style: "default",
onPress: (value?: string) => {
if (!value) return;

filtersStore.addKeyword(value.toLowerCase()).then();
},
},
]
);
};

const keywordOptions = useMemo(
() => keywords.map((k) => <KeywordOption key={k} keyword={k} />),
[keywords]
);

return (
<ScrollView backgroundColor={theme.colors.app.bg} flex={1}>
<TableView style={styles.table}>
<CSection header={t("Keywords").toUpperCase()}>
{keywords.length < 1 ? (
<CCell
cellStyle="RightDetail"
title={t("settings.filters.noKeywords")}
backgroundColor={theme.colors.app.fg}
titleTextColor={theme.colors.app.textPrimary}
rightDetailColor={theme.colors.app.textSecondary}
/>
) : (
keywordOptions
)}
</CSection>
</TableView>
</ScrollView>
);
}

const styles = StyleSheet.create({
table: {
marginHorizontal: 15,
},
});

export default KeywordsScreen;
15 changes: 15 additions & 0 deletions src/components/screens/Settings/SettingsIndexScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,21 @@ function SettingsIndexScreen({
titleTextColor={theme.colors.app.textPrimary}
rightDetailColor={theme.colors.app.textSecondary}
/>
<CCell
cellStyle="Basic"
title={
<SettingOptionTitle
text={t("Filters")}
icon={ICON_MAP.FILTERS}
iconBgColor="#ed5a6e"
/>
}
accessory="DisclosureIndicator"
onPress={() => navigation.push("Filters")}
backgroundColor={theme.colors.app.fg}
titleTextColor={theme.colors.app.textPrimary}
rightDetailColor={theme.colors.app.textSecondary}
/>
<CCell
cellStyle="Basic"
title={
Expand Down
1 change: 1 addition & 0 deletions src/constants/IconMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export const ICON_MAP = {
COPY: "doc.on.doc",
LINK: "link",
BLOCK_COMMUNITY: "xmark.circle",
FILTERS: "eye.slash",
};
Loading

0 comments on commit 0bcf905

Please sign in to comment.