mattermost-mobile/app/utils/theme/index.ts
Avinash Lingaloo e8ce78f39d
MM-36721 - [GEKIDOU] Porting Markdown components (#5586)
* Started with Channel Post List

* Added markdown hashtag

* Added TouchableWithFeedback component

* Added utils/bottom_sheet

* Removed BottomSheet in favor of future SlideUpPanel

* Added markdown_block_quote

* Added markdown_list_item

* Added markdown_list

* Added MarkDownTableCell component

* Markdown_table - in progress - need to verify TS

* Added markdown_table

* Update Podfile.lock

* Added deep_linking constant

* Added utils/draft

* Update config to include ExperimentalNormalizeMarkdownLinks

* Added markdown_link

* Added markdown_table_row

* Added ProgressiveImage and RetriableImage components and images utils

* Converted Retriable component to functional component

* Added type definition for commonmark

* Continuing with markdown TS

* Markdown - Typing props [ in progress ]

* Fix boolean flag with mardown block quote

* Adding observable config to markdown_link

* TS Fixes [ in progress ]

* TS fixes

* TS fixes - TextStyles

* Update markdown.tsx

* TS fixes on markdown

* TS Fixes - AtMention component

* AtMention [ IN PROGRESS ]

* Add markdown support

* Fix emoji and jumboEmoji on iOS

* Fix handleMyTeam operator

* Fix navigation style based on theme

* Fix iOS MattermostManaged deleteDatabse return error type

* wrap setNavigationStackStyles under a requestAnimationFrame

* Add preventDoubleTap to channel mention

* Increase double tap to 750ms

* Fix handleReceivedPostsInChannel chunk query

* Set initial navigation theme

* Swizzle FastImage on iOS

* fix preventDoubleTap test

Co-authored-by: Avinash Lingaloo <>
Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
2021-08-02 20:30:17 +04:00

190 lines
5 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {StyleSheet} from 'react-native';
import tinyColor from 'tinycolor2';
import {mergeNavigationOptions} from '@screens/navigation';
import EphemeralStore from '@store/ephemeral_store';
import type {Options} from 'react-native-navigation';
const MODAL_SCREENS_WITHOUT_BACK = [
'AddReaction',
'ChannelInfo',
'ClientUpgrade',
'CreateChannel',
'EditPost',
'ErrorTeamsList',
'MoreChannels',
'MoreDirectMessages',
'Permalink',
'SelectTeam',
'Settings',
'TermsOfService',
'UserProfile',
];
const rgbPattern = /^rgba?\((\d+),(\d+),(\d+)(?:,([\d.]+))?\)$/;
export function getComponents(inColor: string): {red: number; green: number; blue: number; alpha: number} {
let color = inColor;
// RGB color
const match = rgbPattern.exec(color);
if (match) {
return {
red: parseInt(match[1], 10),
green: parseInt(match[2], 10),
blue: parseInt(match[3], 10),
alpha: match[4] ? parseFloat(match[4]) : 1,
};
}
// Hex color
if (color[0] === '#') {
color = color.slice(1);
}
if (color.length === 3) {
const tempColor = color;
color = '';
color += tempColor[0] + tempColor[0];
color += tempColor[1] + tempColor[1];
color += tempColor[2] + tempColor[2];
}
return {
red: parseInt(color.substring(0, 2), 16),
green: parseInt(color.substring(2, 4), 16),
blue: parseInt(color.substring(4, 6), 16),
alpha: 1,
};
}
export function makeStyleSheetFromTheme(getStyleFromTheme: (a: any) => any): (a: any) => any {
let lastTheme: any;
let style: any;
return (theme: any) => {
if (!style || theme !== lastTheme) {
style = StyleSheet.create(getStyleFromTheme(theme));
lastTheme = theme;
}
return style;
};
}
export function changeOpacity(oldColor: string, opacity: number): string {
const {
red,
green,
blue,
alpha,
} = getComponents(oldColor);
return `rgba(${red},${green},${blue},${alpha * opacity})`;
}
export function concatStyles<T>(...styles: T[]) {
return ([] as T[]).concat(...styles);
}
export function setNavigatorStyles(componentId: string, theme: Theme) {
const options: Options = {
topBar: {
title: {
color: theme.sidebarHeaderTextColor,
},
background: {
color: theme.sidebarHeaderBg,
},
leftButtonColor: theme.sidebarHeaderTextColor,
rightButtonColor: theme.sidebarHeaderTextColor,
},
layout: {
componentBackgroundColor: theme.centerChannelBg,
},
};
if (!MODAL_SCREENS_WITHOUT_BACK.includes(componentId) && options.topBar) {
options.topBar.backButton = {
color: theme.sidebarHeaderTextColor,
};
}
mergeNavigationOptions(componentId, options);
}
export function setNavigationStackStyles(theme: Theme) {
EphemeralStore.allNavigationComponentIds.forEach((componentId) => {
setNavigatorStyles(componentId, theme);
});
}
export function getKeyboardAppearanceFromTheme(theme: Theme) {
return tinyColor(theme.centerChannelBg).isLight() ? 'light' : 'dark';
}
export function hexToHue(hexColor: string) {
let {red, green, blue} = getComponents(hexColor);
red /= 255;
green /= 255;
blue /= 255;
const channelMax = Math.max(red, green, blue);
const channelMin = Math.min(red, green, blue);
const delta = channelMax - channelMin;
let hue = 0;
if (delta === 0) {
hue = 0;
} else if (channelMax === red) {
hue = ((green - blue) / delta) % 6;
} else if (channelMax === green) {
hue = ((blue - red) / delta) + 2;
} else {
hue = ((red - green) / delta) + 4;
}
hue = Math.round(hue * 60);
if (hue < 0) {
hue += 360;
}
return hue;
}
function blendComponent(background: number, foreground: number, opacity: number): number {
return ((1 - opacity) * background) + (opacity * foreground);
}
export function blendColors(background: string, foreground: string, opacity: number): string {
const backgroundComponents = getComponents(background);
const foregroundComponents = getComponents(foreground);
const red = Math.floor(blendComponent(
backgroundComponents.red,
foregroundComponents.red,
opacity,
));
const green = Math.floor(blendComponent(
backgroundComponents.green,
foregroundComponents.green,
opacity,
));
const blue = Math.floor(blendComponent(
backgroundComponents.blue,
foregroundComponents.blue,
opacity,
));
const alpha = blendComponent(
backgroundComponents.alpha,
foregroundComponents.alpha,
opacity,
);
return `rgba(${red},${green},${blue},${alpha})`;
}