Add tags and mute words (#2968)
* Add bare minimum hashtags support (#2804) * Add bare minimum hashtags support As atproto/api already parses hashtags, this is as simple as hooking it up like link segments. This is "bare minimum" because: - Opening hashtag "#foo" is actually just a search for "foo" right now to work around #2491. - There is no integration in the composer. This hasn't stopped people from using hashtags already, and can be added later. - This change itself only had to hook things up - thank you for having already put the hashtag parsing in place. * Remove workaround for hash search not working now that it's fixed * Add RichTextTag and TagMenu * Sketch * Remove hackfix * Some cleanup * Sketch web * Mobile design * Mobile handling of tags search * Web only * Fix navigation woes * Use new callback * Hook it up * Integrate muted tags * Fix dropdown styles * Type error * Use close callback * Fix styles * Cleanup, install latest sdk * Quick muted words screen * Targets * Dir structure * Icons, list view * Move to dialog * Add removal confirmation * Swap copy * Improve checkboxees * Update matching, add tests * Moderate embeds * Create global dialogs concept again to prevent flashing * Add access from moderation screen * Highlight tags on native * Add web highlighting * Add close to web modal * Adjust close color * Rename toggles and adjust logic * Icon update * Load states * Improve regex * Improve regex * Improve regex * Revert link test * Hyphenated words * Improve matching * Enhance * Some tweaks * Muted words modal changes * Handle invalid handles, handle long tags * Remove main regex * Better test * Space/punct check drop to includes * Lowercase post text before comparison * Add better real world test case --------- Co-authored-by: Kisaragi Hiu <mail@kisaragi-hiu.com>
This commit is contained in:
parent
c8582924e2
commit
58aaad704a
49 changed files with 1983 additions and 39 deletions
|
@ -31,6 +31,7 @@ import {
|
|||
useProfileUpdateMutation,
|
||||
} from '#/state/queries/profile'
|
||||
import {ScrollView} from '../com/util/Views'
|
||||
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
|
||||
|
||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Moderation'>
|
||||
export function ModerationScreen({}: Props) {
|
||||
|
@ -40,6 +41,7 @@ export function ModerationScreen({}: Props) {
|
|||
const {screen, track} = useAnalytics()
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
const {openModal} = useModalControls()
|
||||
const {mutedWordsDialogControl} = useGlobalDialogsControlContext()
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
|
@ -69,8 +71,8 @@ export function ModerationScreen({}: Props) {
|
|||
style={[styles.linkCard, pal.view]}
|
||||
onPress={onPressContentFiltering}
|
||||
accessibilityRole="tab"
|
||||
accessibilityHint="Content filtering"
|
||||
accessibilityLabel="">
|
||||
accessibilityHint=""
|
||||
accessibilityLabel={_(msg`Open content filtering settings`)}>
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<FontAwesomeIcon
|
||||
icon="eye"
|
||||
|
@ -81,6 +83,23 @@ export function ModerationScreen({}: Props) {
|
|||
<Trans>Content filtering</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
testID="mutedWordsBtn"
|
||||
style={[styles.linkCard, pal.view]}
|
||||
onPress={() => mutedWordsDialogControl.open()}
|
||||
accessibilityRole="tab"
|
||||
accessibilityHint=""
|
||||
accessibilityLabel={_(msg`Open muted words settings`)}>
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<FontAwesomeIcon
|
||||
icon="filter"
|
||||
style={pal.text as FontAwesomeIconStyle}
|
||||
/>
|
||||
</View>
|
||||
<Text type="lg" style={pal.text}>
|
||||
<Trans>Muted words & tags</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<Link
|
||||
testID="moderationlistsBtn"
|
||||
style={[styles.linkCard, pal.view]}
|
||||
|
|
|
@ -16,7 +16,7 @@ import {
|
|||
FontAwesomeIcon,
|
||||
FontAwesomeIconStyle,
|
||||
} from '@fortawesome/react-native-fontawesome'
|
||||
import {useFocusEffect} from '@react-navigation/native'
|
||||
import {useFocusEffect, useNavigation} from '@react-navigation/native'
|
||||
|
||||
import {logger} from '#/logger'
|
||||
import {
|
||||
|
@ -53,6 +53,7 @@ import {listenSoftReset} from '#/state/events'
|
|||
import {s} from '#/lib/styles'
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
import {augmentSearchQuery} from '#/lib/strings/helpers'
|
||||
import {NavigationProp} from '#/lib/routes/types'
|
||||
|
||||
function Loader() {
|
||||
const pal = usePalette('default')
|
||||
|
@ -448,6 +449,7 @@ export function SearchScreenInner({
|
|||
export function SearchScreen(
|
||||
props: NativeStackScreenProps<SearchTabNavigatorParams, 'Search'>,
|
||||
) {
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const theme = useTheme()
|
||||
const textInput = React.useRef<TextInput>(null)
|
||||
const {_} = useLingui()
|
||||
|
@ -472,6 +474,27 @@ export function SearchScreen(
|
|||
React.useState(false)
|
||||
const [searchHistory, setSearchHistory] = React.useState<string[]>([])
|
||||
|
||||
/**
|
||||
* The Search screen's `q` param
|
||||
*/
|
||||
const queryParam = props.route?.params?.q
|
||||
|
||||
/**
|
||||
* If `true`, this means we received new instructions from the router. This
|
||||
* is handled in a effect, and used to update the value of `query` locally
|
||||
* within this screen.
|
||||
*/
|
||||
const routeParamsMismatch = queryParam && queryParam !== query
|
||||
|
||||
React.useEffect(() => {
|
||||
if (queryParam && routeParamsMismatch) {
|
||||
// reset immediately and let local state take over
|
||||
navigation.setParams({q: ''})
|
||||
// update query for next search
|
||||
setQuery(queryParam)
|
||||
}
|
||||
}, [queryParam, routeParamsMismatch, navigation])
|
||||
|
||||
React.useEffect(() => {
|
||||
const loadSearchHistory = async () => {
|
||||
try {
|
||||
|
@ -774,6 +797,8 @@ export function SearchScreen(
|
|||
)}
|
||||
</View>
|
||||
</CenteredView>
|
||||
) : routeParamsMismatch ? (
|
||||
<ActivityIndicator />
|
||||
) : (
|
||||
<SearchScreenInner query={query} />
|
||||
)}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue