Skip to content

Commit

Permalink
mob: refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
NoodleOfDeath committed Oct 9, 2023
1 parent 93a1d23 commit 54e5625
Show file tree
Hide file tree
Showing 33 changed files with 255 additions and 228 deletions.
167 changes: 87 additions & 80 deletions src/core/src/client/contexts/session/SessionContext.tsx

Large diffs are not rendered by default.

69 changes: 43 additions & 26 deletions src/core/src/client/contexts/session/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import {
} from '~/api';
import { Locale } from '~/locales';

export type BookmarkConstructorProps = {
export type TimelineEventProps = {
createdAt: Date;
expiresIn?: string;
};

export class Bookmark<T> {
export class TimelineEvent<T> {

item: T;
createdAt: Date;
Expand All @@ -31,7 +31,7 @@ export class Bookmark<T> {
constructor(item: T, {
createdAt = new Date(),
expiresIn,
}: Partial<BookmarkConstructorProps> = {}) {
}: Partial<TimelineEventProps> = {}) {
this.item = item;
this.createdAt = createdAt;
if (expiresIn) {
Expand Down Expand Up @@ -109,26 +109,26 @@ export type Resource =

export type SessionEvent = Activity | ResourceActivity | `${ResourceActivity}-${Resource}` | `${ResourceActivity}-${Resource}-${number}` | `poll-${string}`;

export type Preferences = {
export type StoredValues = {

// system state
latestVersion?: string;
rotationLock?: OrientationType;
searchHistory?: string[];
viewedFeatures?: { [key: string]: Bookmark<boolean> };
viewedFeatures?: { [key: string]: TimelineEvent<boolean> };
hasReviewed?: boolean;
lastRequestForReview: number;
loadedInitialUrl?: boolean;

// user state
uuid?: string;
pushNotificationsEnabled?: boolean;
pushNotifications?: { [key: string]: PushNotificationSettings };
fcmToken?: string;
userStats?: UserStats;

// summary state
readSummaries?: { [key: number]: Bookmark<boolean> };
bookmarkedSummaries?: { [key: number]: Bookmark<PublicSummaryGroup> };
readSummaries?: { [key: number]: TimelineEvent<boolean> };
bookmarkedSummaries?: { [key: number]: TimelineEvent<PublicSummaryGroup> };
bookmarkCount: number;
unreadBookmarkCount: number;
removedSummaries?: { [key: number]: boolean };
Expand Down Expand Up @@ -170,7 +170,7 @@ export type Preferences = {
triggerWords?: { [key: string]: string };
};

export const PREFERENCE_TYPES: { [key in keyof Preferences]: 'boolean' | 'number' | 'string' | 'object' | 'array' } = {
export const STORED_VALUE_TYPES: { [key in keyof StoredValues]: 'boolean' | 'number' | 'string' | 'object' | 'array' } = {
bookmarkCount: 'number',
bookmarkedSummaries: 'object',
colorScheme: 'string',
Expand All @@ -192,7 +192,6 @@ export const PREFERENCE_TYPES: { [key in keyof Preferences]: 'boolean' | 'number
lastRequestForReview: 'number',
letterSpacing: 'number',
lineHeightMultiplier: 'number',
loadedInitialUrl: 'boolean',
locale: 'string',
preferredReadingFormat: 'string',
preferredShortPressFormat: 'string',
Expand All @@ -209,6 +208,7 @@ export const PREFERENCE_TYPES: { [key in keyof Preferences]: 'boolean' | 'number
summaryTranslations: 'object',
triggerWords: 'object',
unreadBookmarkCount: 'number',
userStats: 'object',
uuid: 'string',
viewedFeatures: 'object',
};
Expand All @@ -226,31 +226,47 @@ export type PreferenceMutation<E extends SessionEvent> =
any;

export type PreferenceState<E extends SessionEvent> =
E extends `${'unbookmark' | 'bookmark'}-summary` ? Preferences['bookmarkedSummaries'] :
E extends `${'read' | 'unread'}-summary` ? Preferences['readSummaries'] :
E extends `${'read' | 'unread'}-recap` ? Preferences['readRecaps'] :
E extends `${string}-summary` ? Preferences['removedSummaries'] :
E extends `${string}-publisher` ? Preferences['followedPublishers'] :
E extends `${string}-category` ? Preferences['followedCategories'] :
E extends `${'unbookmark' | 'bookmark'}-summary` ? StoredValues['bookmarkedSummaries'] :
E extends `${'read' | 'unread'}-summary` ? StoredValues['readSummaries'] :
E extends `${'read' | 'unread'}-recap` ? StoredValues['readRecaps'] :
E extends `${string}-summary` ? StoredValues['removedSummaries'] :
E extends `${string}-publisher` ? StoredValues['followedPublishers'] :
E extends `${string}-category` ? StoredValues['followedCategories'] :
// eslint-disable-next-line @typescript-eslint/no-explicit-any
any;

export type SessionContextType = Preferences & {
export type Streak = {
start: Date;
end: Date;
length: number;
};

export type UserStats = {
lastSeen?: Date;
streak?: Streak;
longestStreak?: Streak;
};

export type SessionContextType = StoredValues & {
ready?: boolean;

loadedInitialUrl?: boolean;
setLoadedInitialUrl: React.Dispatch<React.SetStateAction<boolean | undefined>>;
categories?: Record<string, PublicCategoryAttributes>;
setCategories: React.Dispatch<React.SetStateAction<Record<string, PublicCategoryAttributes> | undefined>>;
publishers?: Record<string, PublicPublisherAttributes>;
setPublishers: React.Dispatch<React.SetStateAction<Record<string, PublicPublisherAttributes> | undefined>>;


userStats?: UserStats;

// state setters
setPreference: <K extends keyof Preferences, V extends Preferences[K] | ((value?: Preferences[K]) => (Preferences[K] | undefined))>(key: K, value?: V, emit?: boolean) => Promise<void>;
getPreference: <K extends keyof Preferences>(key: K) => Promise<Preferences[K] | undefined>;
resetPreferences: (hard?: boolean) => Promise<void>;
setStoredValue: <K extends keyof StoredValues, V extends StoredValues[K] | ((value?: StoredValues[K]) => (StoredValues[K] | undefined))>(key: K, value?: V, emit?: boolean) => Promise<void>;
getStoredValue: <K extends keyof StoredValues>(key: K) => Promise<StoredValues[K] | undefined>;
resetStoredValues: (hard?: boolean) => Promise<void>;
storeTranslations: <
Target extends RecapAttributes | PublicSummaryGroup,
PrefKey extends Target extends RecapAttributes ? 'recapTranslations' : Target extends PublicSummaryGroup ? 'summaryTranslations' : never
>(item: Target, translations: { [key in keyof Target]?: string }, prefKey: PrefKey) => Promise<void>;
StoredValueKey extends Target extends RecapAttributes ? 'recapTranslations' : Target extends PublicSummaryGroup ? 'summaryTranslations' : never
>(item: Target, translations: { [key in keyof Target]?: string }, prefKey: StoredValueKey) => Promise<void>;
hasPushEnabled: (key: string) => boolean;
enablePush: (key: string, settings?: PushNotificationSettings) => Promise<void>;
hasViewedFeature: (...features: string[]) => boolean;
Expand Down Expand Up @@ -297,7 +313,7 @@ export const DEFAULT_SESSION_CONTEXT: SessionContextType = {
followCount: 0,
followFilter: '',
followPublisher: () => Promise.resolve(),
getPreference: () => Promise.resolve(undefined),
getStoredValue: () => Promise.resolve(undefined),
hasPushEnabled: () => false,
hasViewedFeature: () => false,
isExcludingCategory: () => false,
Expand All @@ -309,10 +325,11 @@ export const DEFAULT_SESSION_CONTEXT: SessionContextType = {
readRecap: () => Promise.resolve(),
readSummary: () => Promise.resolve(),
removeSummary: () => Promise.resolve(),
resetPreferences: () => Promise.resolve(),
resetStoredValues: () => Promise.resolve(),
setCategories: () => Promise.resolve(),
setPreference: () => Promise.resolve(),
setLoadedInitialUrl: () => Promise.resolve(),
setPublishers: () => Promise.resolve(),
setStoredValue: () => Promise.resolve(),
storeTranslations: () => Promise.resolve(undefined),
unreadBookmarkCount: 0,
viewFeature: () => Promise.resolve(),
Expand Down
2 changes: 1 addition & 1 deletion src/mobile/src/LeftDrawerScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ const LeftDrawer = createDrawerNavigator();
export function LeftDrawerScreen() {
return (
<LeftDrawer.Navigator
id="LeftDrawer"
id="leftDrawerNav"
initialRouteName={ 'home' }
screenOptions={ ({ route: _route }) => ({
headerShown: false,
Expand Down
6 changes: 3 additions & 3 deletions src/mobile/src/NavigationController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default function NavigationController() {
hasViewedFeature,
lastRequestForReview = 0,
readSummaries,
setPreference,
setStoredValue,
} = React.useContext(SessionContext);
const {
isTablet,
Expand Down Expand Up @@ -87,7 +87,7 @@ export default function NavigationController() {
}
setShowedReview(success);
emitEvent(success ? 'in-app-review' : 'in-app-review-failed');
setPreference('lastRequestForReview', Date.now());
setStoredValue('lastRequestForReview', Date.now());
} catch (error) {
console.error(error);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -111,7 +111,7 @@ export default function NavigationController() {
};

}
}, [ready, isTablet, lockRotation, showedReview, lastRequestForReview, unlockRotation, readSummaries, setPreference, emitEvent]);
}, [ready, isTablet, lockRotation, showedReview, lastRequestForReview, unlockRotation, readSummaries, setStoredValue, emitEvent]);

const refreshSources = React.useCallback(() => {
if (lastFetchFailed || (Date.now() - lastFetch < ms('10s'))) {
Expand Down
6 changes: 3 additions & 3 deletions src/mobile/src/RightDrawerScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,16 @@ const RightDrawer = createDrawerNavigator();
export function RightDrawerScreen() {
return (
<RightDrawer.Navigator
id="RightDrawer"
initialRouteName="LeftDrawer"
id="rightDrawerNav"
initialRouteName="leftDrawer"
screenOptions={ ({ route: _route }) => ({
drawerPosition: 'right',
headerShown: false,
swipeEnabled: false,
}) }
drawerContent={ (props) => <RightDrawerContent { ...props } /> }>
<RightDrawer.Screen
name='LeftDrawer'
name='leftDrawer'
component={ LeftDrawerScreen } />
</RightDrawer.Navigator>
);
Expand Down
4 changes: 2 additions & 2 deletions src/mobile/src/components/common/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function DrawerToggle(props: ButtonProps) {
accessible
accessibilityLabel={ strings.axe_menu }
onPress={ () => {
navigation?.getParent('LeftDrawer')?.openDrawer?.();
(navigation?.getParent('leftDrawerNav') as typeof navigation)?.openDrawer?.();
} }
{ ...props } />
</View>
Expand All @@ -37,7 +37,7 @@ export function SettingsToggle(props: ButtonProps) {
accessibilityLabel={ strings.axe_settings }
iconSize={ 24 }
onPress={ () => {
navigation?.getParent('RightDrawer')?.openDrawer?.();
(navigation?.getParent('rightDrawerNav') as typeof navigation)?.openDrawer?.();
} }
{ ...props } />
</View>
Expand Down
6 changes: 3 additions & 3 deletions src/mobile/src/components/common/RoutedScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ import { useNavigation } from '~/hooks';
export function RoutedScreen({ ...props }: ScreenProps) {

const { navigation, router } = useNavigation();
const { loadedInitialUrl, setPreference } = React.useContext(SessionContext);
const { loadedInitialUrl, setLoadedInitialUrl } = React.useContext(SessionContext);

useFocusEffect(React.useCallback(() => {
const subscriber = Linking.addEventListener('url', router);
if (!loadedInitialUrl) {
Linking.getInitialURL().then((url) => {
if (url) {
setPreference('loadedInitialUrl', true);
setLoadedInitialUrl(true);
router({ stackNav: navigation?.getParent('stackNav'), url });
}
});
}
return () => subscriber.remove();
}, [router, navigation, loadedInitialUrl, setPreference]));
}, [router, navigation, loadedInitialUrl, setLoadedInitialUrl]));

return (
<Screen { ...props } />
Expand Down
4 changes: 2 additions & 2 deletions src/mobile/src/components/common/SearchMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function SearchMenu({

const {
searchHistory,
setPreference,
setStoredValue,
} = React.useContext(SessionContext);
const { screenWidth } = React.useContext(LayoutContext);

Expand Down Expand Up @@ -102,7 +102,7 @@ export function SearchMenu({
</Button>
</View>
<View gap={ 6 }>
<Button caption onPress={ () => setPreference('searchHistory', []) }>
<Button caption onPress={ () => setStoredValue('searchHistory', []) }>
{strings.action_clearSearchHistory}
</Button>
<Divider />
Expand Down
6 changes: 3 additions & 3 deletions src/mobile/src/components/dialogs/FeedbackDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function FeedbackDialog({ payload, ...props }: SheetProps<FeedbackDialogP

const { summary, onClose } = React.useMemo(() => ({ ...payload }), [payload]);

const { setPreference } = React.useContext(SessionContext);
const { setStoredValue } = React.useContext(SessionContext);

const { interactWithSummary } = useApiClient();

Expand Down Expand Up @@ -65,7 +65,7 @@ export function FeedbackDialog({ payload, ...props }: SheetProps<FeedbackDialogP
selectedValues.includes('offensive') ||
selectedValues.includes('spam')
) {
setPreference('removedSummaries', (prev) => {
setStoredValue('removedSummaries', (prev) => {
const summaries = { ...prev };
if (summaries[summary.id]) {
delete summaries[summary.id];
Expand All @@ -84,7 +84,7 @@ export function FeedbackDialog({ payload, ...props }: SheetProps<FeedbackDialogP
setSelectedValues([]);
setOtherValue('');
setSuccess(true);
}, [selectedValues, interactWithSummary, summary, setPreference]);
}, [selectedValues, interactWithSummary, summary, setStoredValue]);

return (
<ActionSheet id={ props.sheetId }>
Expand Down
6 changes: 3 additions & 3 deletions src/mobile/src/components/pickers/ColorSchemePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function ColorSchemePicker({
...props
}: ColorSchemePickerProps) {

const { colorScheme, setPreference } = React.useContext(SessionContext);
const { colorScheme, setStoredValue } = React.useContext(SessionContext);

if (variant === 'table') {
return (
Expand All @@ -33,7 +33,7 @@ export function ColorSchemePicker({
] }
initialValue={ colorScheme ?? 'system' }
onValueChange={ (colorScheme) => {
setPreference('colorScheme', colorScheme);
setStoredValue('colorScheme', colorScheme);
} }>
<ScrollView my={ 12 } scrollEnabled={ false }>
<Summary
Expand All @@ -58,7 +58,7 @@ export function ColorSchemePicker({
textCenter: true,
} }
initialValue={ colorScheme ?? 'system' }
onValueChange={ (value) => setPreference('colorScheme', value) }
onValueChange={ (value) => setStoredValue('colorScheme', value) }
options={ [
{ label: strings.settings_light, value: 'light' as ColorScheme },
{ label: strings.settings_system, value: 'system' as ColorScheme },
Expand Down
8 changes: 4 additions & 4 deletions src/mobile/src/components/pickers/FontPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function FontPicker({
...props
}: FontPickerProps = {}) {

const { fontFamily = DEFAULT_PREFERRED_FONT, setPreference } = React.useContext(SessionContext);
const { fontFamily = DEFAULT_PREFERRED_FONT, setStoredValue } = React.useContext(SessionContext);
const style = useStyles(props);

if (variant === 'grid') {
Expand All @@ -38,7 +38,7 @@ export function FontPicker({
initialValue={ fontFamily as FontFamily }
buttonProps={ ({ option }) => ({ fontFamily: option.value }) }
onValueChange={ (font) => {
setPreference('fontFamily', font);
setStoredValue('fontFamily', font);
} } />
);
} else
Expand All @@ -59,7 +59,7 @@ export function FontPicker({
leftIcon={ fontFamily === font ? 'check' : undefined }
fontFamily={ font }
onPress={ () => {
setPreference('fontFamily', font);
setStoredValue('fontFamily', font);
} }>
{font}
</Button>
Expand All @@ -74,7 +74,7 @@ export function FontPicker({
options={ [...AVAILABLE_FONTS] }
initialValue={ fontFamily as FontFamily }
cellProps={ ({ option }) => ({ titleTextStyle: { fontFamily: option.value } }) }
onValueChange={ (font) => setPreference('fontFamily', font) }>
onValueChange={ (font) => setStoredValue('fontFamily', font) }>
<ScrollView my={ 12 } scrollEnabled={ false }>
<Summary
sample
Expand Down
2 changes: 1 addition & 1 deletion src/mobile/src/components/pickers/NumericPrefPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function NumericPrefPicker<K extends keyof NumericPreferences>({
}
}
setValue(newValue);
context.setPreference(prefKey, newValue);
context.setStoredValue(prefKey, newValue);
}, [min, max, context, prefKey]);

return (
Expand Down
2 changes: 1 addition & 1 deletion src/mobile/src/components/pickers/PrefSwitch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function PrefSwitch<K extends keyof BooleanPreferences>({
value={ value }
onValueChange={ (value) => {
setValue(value);
context.setPreference(prefKey, value);
context.setStoredValue(prefKey, value);
onValueChange?.(value);
} }
{ ...props } />
Expand Down
Loading

0 comments on commit 54e5625

Please sign in to comment.