mirror of
https://github.com/mattermost/mattermost-mobile.git
synced 2026-11-06 10:50:13 +00:00
* Expo-Router partial migration * Full migration to ExpoRouter * i18n * add tests * Merge branch 'main' into expo-router * align package-lock.json * i18n * feedback review * feedback review * android 16kb patch * Refactored emoji picker keyboard using a state machine * set android launch_screen in drawables instead of layout * no conditional hooks * remove duplicate call in test * address feedback * fix tests and address more feedback * small corrections * small corrections * small corrections * fix draft test * fix draft test 2 * remove navigateToScreen in draff test * fix nit in draft test * remove doc file * Feedback review * fix snapshots * improve test coverage * fix i18n * Upgrade t o RN 0.83, other dependencies and new architecture (#9737) * library hardware-keyboard android new arch support fix * library rnshare android new arch support fix * library rnutils android new arch support fix * library secure-pdf-viewer add new arch support * Enable new arch on iOS and Android * update emm and network client with new-arch * update intune to use new-arch * performance improvements * fix tests * fixes post input on new-arch * fix android emoji picker * remove doc * run tests in parallel * upgrade to React Native 0.83.9, Expo 55, React 19, and New Architecture Bumps core dependencies to their latest versions: - React Native 0.77.3 → 0.83.9 (New Architecture enabled) - React 18.3.1 → 19.2.5 - Expo SDK 52 → 55 - TypeScript 5.8.3 → 6.0.3 - Node.js 22.16.0 → 24.15.0 - react-native-reanimated 3.17.3 → 4.3.0 - Various other dependency upgrades Migrates iOS AppDelegate from Objective-C to Swift, updates Android build tooling and Gradle wrapper, refreshes all patches and font assets, and adapts app code, tests, and CI workflows throughout for API changes introduced by these upgrades. * remove unecessary dismissKeyboard in notifications * feedback review * update intune to use new-arch * update @mattermost deps * missing i18n string * additional fixes * update fastlane
265 lines
8.2 KiB
TypeScript
265 lines
8.2 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import React, {useMemo} from 'react';
|
|
import {Pressable, Text, View} from 'react-native';
|
|
|
|
import Tag from '@components/tag';
|
|
import {useTheme} from '@context/theme';
|
|
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
|
import {typography} from '@utils/typography';
|
|
|
|
import CompassIcon, {type CompassIconName} from '../compass_icon';
|
|
import Markdown from '../markdown';
|
|
|
|
import SectionNoticeButton from './section_notice_button';
|
|
|
|
import type {SectionNoticeButtonProps} from './types';
|
|
import type {AvailableScreens} from '@typings/screens/navigation';
|
|
|
|
type Props = {
|
|
title: string;
|
|
text?: string;
|
|
primaryButton?: SectionNoticeButtonProps;
|
|
secondaryButton?: SectionNoticeButtonProps;
|
|
linkButton?: SectionNoticeButtonProps;
|
|
type?: 'info' | 'success' | 'danger' | 'welcome' | 'warning' | 'hint';
|
|
isDismissable?: boolean;
|
|
onDismissClick?: () => void;
|
|
location: AvailableScreens;
|
|
tags?: string[];
|
|
testID?: string;
|
|
squareCorners?: boolean;
|
|
}
|
|
|
|
const iconByType: Record<string, CompassIconName | undefined> = {
|
|
info: 'information-outline',
|
|
hint: 'lightbulb-outline',
|
|
success: 'check',
|
|
danger: 'alert-outline',
|
|
warning: 'alert-outline',
|
|
welcome: undefined,
|
|
};
|
|
|
|
const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
|
|
return {
|
|
container: {
|
|
borderWidth: 1,
|
|
borderStyle: 'solid',
|
|
},
|
|
roundCorners: {
|
|
borderRadius: 4,
|
|
},
|
|
content: {
|
|
flexDirection: 'row',
|
|
alignItems: 'flex-start',
|
|
padding: 16,
|
|
gap: 12,
|
|
},
|
|
body: {
|
|
flexDirection: 'column',
|
|
gap: 8,
|
|
flex: 1,
|
|
},
|
|
actions: {
|
|
marginTop: 8,
|
|
gap: 8,
|
|
},
|
|
title: {
|
|
margin: 0,
|
|
color: theme.centerChannelColor,
|
|
...typography('Body', 100, 'SemiBold'),
|
|
},
|
|
welcomeTitle: {
|
|
margin: 0,
|
|
color: theme.centerChannelColor,
|
|
...typography('Heading', 400, 'SemiBold'),
|
|
},
|
|
baseText: {
|
|
color: theme.centerChannelColor,
|
|
...typography('Body', 100, 'Regular'),
|
|
},
|
|
infoText: {
|
|
color: theme.centerChannelColor,
|
|
},
|
|
infoIcon: {
|
|
color: theme.sidebarTextActiveBorder,
|
|
},
|
|
infoContainer: {
|
|
borderColor: changeOpacity(theme.sidebarTextActiveBorder, 0.16),
|
|
backgroundColor: changeOpacity(theme.sidebarTextActiveBorder, 0.08),
|
|
},
|
|
successText: {
|
|
color: theme.centerChannelColor,
|
|
},
|
|
successIcon: {
|
|
color: theme.onlineIndicator,
|
|
},
|
|
successContainer: {
|
|
borderColor: changeOpacity(theme.onlineIndicator, 0.16),
|
|
backgroundColor: changeOpacity(theme.onlineIndicator, 0.08),
|
|
},
|
|
dangerText: {
|
|
color: theme.dndIndicator,
|
|
},
|
|
dangerIcon: {
|
|
color: theme.errorTextColor,
|
|
},
|
|
dangerContainer: {
|
|
borderColor: changeOpacity(theme.dndIndicator, 0.16),
|
|
backgroundColor: changeOpacity(theme.dndIndicator, 0.08),
|
|
},
|
|
warningText: {
|
|
color: theme.awayIndicator,
|
|
},
|
|
warningIcon: {
|
|
color: theme.sidebarTextActiveBorder,
|
|
},
|
|
warningContainer: {
|
|
borderColor: changeOpacity(theme.awayIndicator, 0.16),
|
|
backgroundColor: changeOpacity(theme.awayIndicator, 0.08),
|
|
},
|
|
welcomeText: {
|
|
color: theme.centerChannelColor,
|
|
},
|
|
welcomeIcon: {
|
|
color: theme.centerChannelColor,
|
|
},
|
|
welcomeContainer: {
|
|
borderColor: changeOpacity(theme.centerChannelColor, 0.08),
|
|
backgroundColor: changeOpacity(theme.centerChannelColor, 0.04),
|
|
},
|
|
hintText: {
|
|
color: theme.centerChannelColor,
|
|
},
|
|
hintIcon: {
|
|
color: theme.sidebarTextActiveBorder,
|
|
},
|
|
hintContainer: {
|
|
borderColor: changeOpacity(theme.sidebarTextActiveBorder, 0.16),
|
|
backgroundColor: changeOpacity(theme.sidebarTextActiveBorder, 0.08),
|
|
},
|
|
dismissIcon: {
|
|
position: 'absolute',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
right: 10,
|
|
top: 10,
|
|
width: 32,
|
|
height: 32,
|
|
},
|
|
tagsContainer: {
|
|
flexDirection: 'row',
|
|
flexWrap: 'wrap',
|
|
gap: 4,
|
|
},
|
|
|
|
};
|
|
});
|
|
|
|
const SectionNotice = ({
|
|
title,
|
|
isDismissable,
|
|
linkButton,
|
|
onDismissClick,
|
|
primaryButton,
|
|
secondaryButton,
|
|
text,
|
|
type = 'info',
|
|
location,
|
|
tags,
|
|
squareCorners,
|
|
testID,
|
|
}: Props) => {
|
|
const theme = useTheme();
|
|
const styles = getStyleFromTheme(theme);
|
|
|
|
const icon = iconByType[type];
|
|
const showDismiss = Boolean(isDismissable && onDismissClick);
|
|
const hasButtons = primaryButton || secondaryButton || linkButton;
|
|
const showTags = tags && tags.length > 0;
|
|
|
|
const combinedContainerStyle = useMemo(() => [
|
|
styles.container,
|
|
styles[`${type}Container`],
|
|
!squareCorners && styles.roundCorners,
|
|
], [styles, type, squareCorners]);
|
|
const iconStyle = useMemo(() => styles[`${type}Icon`], [styles, type]);
|
|
return (
|
|
<View
|
|
style={combinedContainerStyle}
|
|
testID={testID || 'sectionNoticeContainer'}
|
|
>
|
|
<View style={styles.content}>
|
|
{icon && (
|
|
<CompassIcon
|
|
name={icon}
|
|
style={iconStyle}
|
|
size={20}
|
|
testID='sectionNoticeHeaderIcon'
|
|
/>
|
|
)}
|
|
<View style={styles.body}>
|
|
<Text style={styles.title}>{title}</Text>
|
|
{text && (
|
|
<Markdown
|
|
theme={theme}
|
|
location={location}
|
|
baseTextStyle={styles.baseText}
|
|
value={text}
|
|
/>
|
|
)}
|
|
{showTags && (
|
|
<View style={styles.tagsContainer}>
|
|
{tags.map((tag) => (
|
|
<Tag
|
|
key={tag}
|
|
testID={`tag.${tag}`}
|
|
message={tag}
|
|
/>
|
|
))}
|
|
</View>
|
|
)}
|
|
{hasButtons && (
|
|
<View style={styles.actions}>
|
|
{primaryButton && (
|
|
<SectionNoticeButton
|
|
button={primaryButton}
|
|
emphasis='primary'
|
|
/>
|
|
)}
|
|
{secondaryButton && (
|
|
<SectionNoticeButton
|
|
button={secondaryButton}
|
|
emphasis='tertiary'
|
|
/>
|
|
)}
|
|
{linkButton && (
|
|
<SectionNoticeButton
|
|
button={linkButton}
|
|
emphasis='link'
|
|
/>
|
|
)}
|
|
</View>
|
|
)}
|
|
</View>
|
|
</View>
|
|
{showDismiss && (
|
|
<Pressable
|
|
style={styles.dismissIcon}
|
|
role={'button'}
|
|
onPress={onDismissClick}
|
|
testID={'sectionNoticeDismissButton'}
|
|
>
|
|
<CompassIcon
|
|
name={'close'}
|
|
size={18}
|
|
/>
|
|
</Pressable>
|
|
)}
|
|
</View>
|
|
);
|
|
};
|
|
|
|
export default SectionNotice;
|