Skip to content

Commit

Permalink
[Chore] Review theme colors (#131)
Browse files Browse the repository at this point in the history
* chore: add inverseSecondary to theme color

* chore: replace empty message text with pocketpal's icon

* chore: add divider component

* feat: group models by ready to use and available to download (when ungrouped by model type)

* feat: add description to Available to download group in models screen

* chore: update TextInput to support error messages

* feat: add completion settings validation

* chore: refactor completion settings

* chore: remove n_probs from the ui

* chore: update completion settings desc

* fix: increase temp max value

* chore: add inverseTextSecondary to the theme

* chore: update background and surface for the dark mode
  • Loading branch information
a-ghorbani authored Dec 10, 2024
1 parent a45fcb7 commit 416e1c5
Show file tree
Hide file tree
Showing 57 changed files with 2,343 additions and 1,137 deletions.
9 changes: 9 additions & 0 deletions __mocks__/stores/modelStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ class MockModelStore {
checkSpaceAndDownload: jest.Mock;
getDownloadProgress: jest.Mock;
manualReleaseContext: jest.Mock;
addHFModel: jest.Mock;
downloadHFModel: jest.Mock;
cancelDownload: jest.Mock;

constructor() {
makeAutoObservable(this, {
Expand All @@ -42,6 +45,9 @@ class MockModelStore {
checkSpaceAndDownload: false,
getDownloadProgress: false,
manualReleaseContext: false,
addHFModel: false,
downloadHFModel: false,
cancelDownload: false,
lastUsedModel: computed,
activeModel: computed,
isDownloading: computed,
Expand All @@ -57,6 +63,9 @@ class MockModelStore {
this.checkSpaceAndDownload = jest.fn();
this.getDownloadProgress = jest.fn();
this.manualReleaseContext = jest.fn();
this.addHFModel = jest.fn();
this.downloadHFModel = jest.fn();
this.cancelDownload = jest.fn();
}

setActiveModel = (modelId: string) => {
Expand Down
11 changes: 10 additions & 1 deletion __mocks__/stores/uiStore.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
export class UIStore {
static readonly GROUP_KEYS = {
READY_TO_USE: 'ready_to_use',
AVAILABLE_TO_DOWNLOAD: 'available_to_download',
} as const;
}

export const mockUiStore = {
colorScheme: 'light',
autoNavigatetoChat: false,
pageStates: {
modelsScreen: {
filters: [],
expandedGroups: {},
expandedGroups: {
[UIStore.GROUP_KEYS.READY_TO_USE]: true,
},
},
},
setValue: jest.fn(),
Expand Down
4 changes: 2 additions & 2 deletions jest/fixtures/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ export const mockHFModel2: HuggingFaceModel = {
};

export const hfModel1 = createModel({
id: 'hf-model-1',
id: mockHFModel1.id + '/' + mockHFModel1.siblings[0].rfilename,
name: 'hf-model-name-1',
author: 'owner',
type: 'GGUF',
Expand All @@ -228,7 +228,7 @@ export const hfModel1 = createModel({
});

export const hfModel2 = createModel({
id: 'hf-model-2',
id: mockHFModel2.id + '/' + mockHFModel2.siblings[0].rfilename,
name: 'hf-model-name-2',
author: 'owner',
type: 'GGUF',
Expand Down
16 changes: 10 additions & 6 deletions jest/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,16 @@ jest.mock('react-native-safe-area-context', () => {
};
});

jest.mock('../src/store', () => ({
modelStore: mockModelStore,
uiStore: mockUiStore,
chatSessionStore: mockChatSessionStore,
hfStore: mockHFStore,
}));
jest.mock('../src/store', () => {
const {UIStore} = require('../__mocks__/stores/uiStore');
return {
modelStore: mockModelStore,
UIStore,
uiStore: mockUiStore,
chatSessionStore: mockChatSessionStore,
hfStore: mockHFStore,
};
});

jest.mock('../src/hooks/useTheme', () => {
const {themeFixtures} = require('./fixtures/theme');
Expand Down
Binary file added src/assets/pocketpal-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/pocketpal-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/pocketpal.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
93 changes: 51 additions & 42 deletions src/components/AppleStyleSwipeableRow/AppleStyleSwipeableRow.tsx
Original file line number Diff line number Diff line change
@@ -1,80 +1,89 @@
import {Animated, Text, View} from 'react-native';
import React, {Component, PropsWithChildren} from 'react';
import React, {useRef} from 'react';
import {Animated, View} from 'react-native';

import {Text} from 'react-native-paper';
import {RectButton, Swipeable} from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';

import {styles} from './styles';
import {useTheme} from '../../hooks';

import {createStyles, SWIPE_WIDTH} from './styles';

interface AppleStyleSwipeableRowProps {
onDelete: () => void;
onSwipeableOpen?: (direction: string) => void;
onSwipeableClose?: (direction: string) => void;
children: React.ReactNode;
}

export class AppleStyleSwipeableRow extends Component<
PropsWithChildren<AppleStyleSwipeableRowProps>
> {
private renderLeftAction = (
export const AppleStyleSwipeableRow: React.FC<AppleStyleSwipeableRowProps> = ({
onDelete,
onSwipeableOpen,
onSwipeableClose,
children,
}) => {
const theme = useTheme();
const styles = createStyles(theme);
const swipeableRow = useRef<Swipeable>(null);

const close = () => {
swipeableRow.current?.close();
};

const renderLeftAction = (
text: string,
color: string,
x: number,
progress: Animated.AnimatedInterpolation<number>,
) => {
const trans = progress.interpolate({
inputRange: [0, 1],
outputRange: [-x, 0], // Start offscreen and move into view
outputRange: [-x, 0],
});

const pressHandler = () => {
this.close();
this.props.onDelete();
close();
onDelete();
};

return (
<Animated.View
style={[
styles.leftActionContainer,
{transform: [{translateX: trans}]},
{
transform: [{translateX: trans}],
backgroundColor: color,
},
]}>
<RectButton
style={[styles.leftAction, {backgroundColor: color}]}
onPress={pressHandler}>
<Text style={styles.actionText}>{text}</Text>
<RectButton style={styles.leftAction} onPress={pressHandler}>
<Icon name="trash-can-outline" size={22} color="white" />
<Text variant="bodySmall" style={styles.actionText}>
{text}
</Text>
</RectButton>
</Animated.View>
);
};

private renderLeftActions = (
const renderLeftActions = (
progress: Animated.AnimatedInterpolation<number>,
_dragAnimatedValue: Animated.AnimatedInterpolation<number>,
) => (
<View style={styles.leftActionsContainer}>
{this.renderLeftAction('Delete', '#dd2c00', 192, progress)}
{renderLeftAction('Delete', theme.colors.error, SWIPE_WIDTH, progress)}
</View>
);

private swipeableRow?: Swipeable;

private updateRef = (ref: Swipeable) => {
this.swipeableRow = ref;
};
private close = () => {
this.swipeableRow?.close();
};

render() {
const {children} = this.props;
return (
<Swipeable
ref={this.updateRef}
friction={2}
enableTrackpadTwoFingerGesture
leftThreshold={30} // Right swipe threshold
renderLeftActions={this.renderLeftActions} // Swipe right to reveal left actions
onSwipeableOpen={this.props.onSwipeableOpen}
onSwipeableClose={this.props.onSwipeableClose}>
{children}
</Swipeable>
);
}
}
return (
<Swipeable
ref={swipeableRow}
friction={2}
enableTrackpadTwoFingerGesture
leftThreshold={30}
renderLeftActions={renderLeftActions}
onSwipeableOpen={onSwipeableOpen}
onSwipeableClose={onSwipeableClose}>
{children}
</Swipeable>
);
};
62 changes: 41 additions & 21 deletions src/components/AppleStyleSwipeableRow/styles.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
import {I18nManager, StyleSheet} from 'react-native';
import {StyleSheet, Dimensions} from 'react-native';
import {Theme} from '../../utils/types';

export const styles = StyleSheet.create({
leftActionsContainer: {
width: 192,
flexDirection: I18nManager.isRTL ? 'row-reverse' : 'row',
},
leftActionContainer: {
flex: 1,
},
actionText: {
color: 'white',
fontSize: 16,
backgroundColor: 'transparent',
padding: 10,
},
leftAction: {
alignItems: 'center',
flex: 1,
justifyContent: 'center',
},
});
export const SWIPE_WIDTH = Dimensions.get('window').width * 0.3; // 30% of screen width

export const createStyles = (theme: Theme) =>
StyleSheet.create({
leftActionContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
borderTopRightRadius: 24,
borderBottomRightRadius: 24,
shadowColor: theme.colors.shadow,
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.25,
shadowRadius: 1.84,
elevation: 5,
marginVertical: 4,
marginRight: 4,
},
leftAction: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
width: SWIPE_WIDTH,
padding: 16,
},
actionText: {
color: theme.colors.onPrimary,
marginTop: 4,
textTransform: 'uppercase',
letterSpacing: 0.5,
},
leftActionsContainer: {
width: SWIPE_WIDTH,
flexDirection: 'row',
},
});
4 changes: 2 additions & 2 deletions src/components/Bubble/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ export const styles = ({
},
dateHeader: {
//textAlign: 'right',
color: theme.colors.outline,
color: theme.colors.textSecondary,
fontSize: 10,
},
iconContainer: {
marginRight: 5,
color: theme.colors.outline,
color: theme.colors.textSecondary,
fontSize: 16,
},
});
Expand Down
2 changes: 1 addition & 1 deletion src/components/ChatInput/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export const ChatInput = observer(
ref={inputRef}
multiline
placeholder={l10n.inputPlaceholder}
placeholderTextColor={theme.colors.outline}
placeholderTextColor={theme.colors.inverseTextSecondary}
underlineColorAndroid="transparent"
{...textInputProps}
style={[styles.input, textInputProps?.style]}
Expand Down
22 changes: 3 additions & 19 deletions src/components/ChatView/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@ import {
LayoutAnimation,
StatusBar,
StatusBarProps,
Text,
View,
} from 'react-native';

import dayjs from 'dayjs';
import {observer} from 'mobx-react';
import calendar from 'dayjs/plugin/calendar';
import {oneOf} from '@flyerhq/react-native-link-preview';
import {useSafeAreaInsets} from 'react-native-safe-area-context';

import {useComponentSize} from '../KeyboardAccessoryView/hooks';
Expand Down Expand Up @@ -46,6 +44,7 @@ import {
ChatInputTopLevelProps,
Menu,
LoadingBubble,
PocketPalIconAnimation,
} from '..';

// Untestable
Expand Down Expand Up @@ -136,7 +135,6 @@ export const ChatView = observer(
customDateHeaderText,
dateFormat,
disableImageGallery,
emptyState,
enableAnimation,
flatListProps,
inputProps,
Expand Down Expand Up @@ -519,22 +517,8 @@ export const ChatView = observer(
);

const renderListEmptyComponent = React.useCallback(
() => (
<View style={styles.emptyComponentContainer}>
{oneOf(
emptyState,
<Text style={styles.emptyComponentTitle}>
{l10nValue.emptyChatPlaceholder}
</Text>,
)()}
</View>
),
[
styles.emptyComponentContainer,
styles.emptyComponentTitle,
emptyState,
l10nValue,
],
() => <PocketPalIconAnimation testID="empty-state-component" />,
[],
);

const renderListFooterComponent = React.useCallback(
Expand Down
4 changes: 2 additions & 2 deletions src/components/ChatView/__tests__/ChatView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ describe('chat', () => {
const messages = [];
const onSendPress = jest.fn();
const onMessagePress = jest.fn();
const {getByText} = render(
const {getByTestId} = render(
<ChatView
messages={messages}
onMessagePress={onMessagePress}
Expand All @@ -174,7 +174,7 @@ describe('chat', () => {
/>,
);

const placeholder = getByText(l10n.en.emptyChatPlaceholder);
const placeholder = getByTestId('empty-state-component');
expect(placeholder).toBeDefined();
});

Expand Down
Loading

0 comments on commit 416e1c5

Please sign in to comment.