Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/renderer/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useContext } from 'react';
import {
Navigate,
Route,
Expand All @@ -10,7 +9,7 @@ import {
import { BaseStyles, ThemeProvider } from '@primer/react';

import { AppLayout } from './components/layout/AppLayout';
import { AppContext, AppProvider } from './context/App';
import { AppProvider, useAppContext } from './context/App';
import { AccountsRoute } from './routes/Accounts';
import { FiltersRoute } from './routes/Filters';
import { LoginRoute } from './routes/Login';
Expand All @@ -22,7 +21,7 @@ import { SettingsRoute } from './routes/Settings';
import './App.css';

function RequireAuth({ children }) {
const { isLoggedIn } = useContext(AppContext);
const { isLoggedIn } = useAppContext();
const location = useLocation();

return isLoggedIn ? (
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/AllRead.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type FC, useContext, useMemo } from 'react';
import { type FC, useMemo } from 'react';

import { Constants } from '../constants';
import { AppContext } from '../context/App';
import { useAppContext } from '../context/App';
import { hasActiveFilters } from '../utils/notifications/filters/filter';
import { EmojiSplash } from './layout/EmojiSplash';

Expand All @@ -12,7 +12,7 @@ interface AllReadProps {
export const AllRead: FC<AllReadProps> = ({
fullHeight = true,
}: AllReadProps) => {
const { settings } = useContext(AppContext);
const { settings } = useAppContext();

const hasFilters = hasActiveFilters(settings);

Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type FC, useContext } from 'react';
import type { FC } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';

import {
Expand All @@ -15,7 +15,7 @@ import { IconButton, Stack } from '@primer/react';
import { APPLICATION } from '../../shared/constants';

import { Constants } from '../constants';
import { AppContext } from '../context/App';
import { useAppContext } from '../context/App';
import { quitApp } from '../utils/comms';
import {
openGitHubIssues,
Expand All @@ -37,7 +37,7 @@ export const Sidebar: FC = () => {
auth,
unreadNotificationCount,
hasUnreadNotifications,
} = useContext(AppContext);
} = useAppContext();

// We naively assume that the first account is the primary account for the purposes of our sidebar quick links
const primaryAccountHostname =
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/filters/FilterSection.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { type ReactNode, useContext } from 'react';
import type { ReactNode } from 'react';

import type { Icon } from '@primer/octicons-react';
import { Stack, Text } from '@primer/react';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import type { FilterSettingsState, FilterSettingsValue } from '../../types';
import type { Filter } from '../../utils/notifications/filters';
import { Checkbox } from '../fields/Checkbox';
Expand All @@ -29,7 +29,7 @@ export const FilterSection = <T extends FilterSettingsValue>({
tooltip,
layout = 'vertical',
}: FilterSectionProps<T>) => {
const { updateFilter, settings, notifications } = useContext(AppContext);
const { updateFilter, settings, notifications } = useAppContext();

return (
<fieldset id={id}>
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/filters/SearchFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type FC, useContext, useEffect, useState } from 'react';
import { type FC, useEffect, useState } from 'react';

import {
CheckCircleFillIcon,
Expand All @@ -10,7 +10,7 @@ import {
} from '@primer/octicons-react';
import { Stack, Text } from '@primer/react';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { IconColor, type SearchToken, Size } from '../../types';
import { cn } from '../../utils/cn';
import {
Expand All @@ -22,7 +22,7 @@ import { RequiresDetailedNotificationWarning } from './RequiresDetailedNotificat
import { TokenSearchInput } from './TokenSearchInput';

export const SearchFilter: FC = () => {
const { updateFilter, settings } = useContext(AppContext);
const { updateFilter, settings } = useAppContext();

// biome-ignore lint/correctness/useExhaustiveDependencies: only run on search filter changes
useEffect(() => {
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/filters/SearchFilterSuggestions.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { type FC, useContext } from 'react';
import type { FC } from 'react';

import { Popover, Stack, Text } from '@primer/react';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { Opacity } from '../../types';
import { cn } from '../../utils/cn';
import {
Expand All @@ -20,7 +20,7 @@ export const SearchFilterSuggestions: FC<SearchFilterSuggestionsProps> = ({
open,
inputValue,
}) => {
const { settings } = useContext(AppContext);
const { settings } = useAppContext();

if (!open) {
return null;
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/metrics/MetricGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type FC, useContext } from 'react';
import type { FC } from 'react';

import {
CommentIcon,
Expand All @@ -7,7 +7,7 @@ import {
TagIcon,
} from '@primer/octicons-react';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { IconColor } from '../../types';
import type { Notification } from '../../typesGitHub';
import { getPullRequestReviewIcon } from '../../utils/icons';
Expand All @@ -20,7 +20,7 @@ interface MetricGroupProps {
export const MetricGroup: FC<MetricGroupProps> = ({
notification,
}: MetricGroupProps) => {
const { settings } = useContext(AppContext);
const { settings } = useAppContext();

const commentsPillDescription = `${notification.subject.comments} ${
notification.subject.comments > 1 ? 'comments' : 'comment'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { type FC, type MouseEvent, useContext, useMemo, useState } from 'react';
import { type FC, type MouseEvent, useMemo, useState } from 'react';

import { GitPullRequestIcon, IssueOpenedIcon } from '@primer/octicons-react';
import { Button, Stack } from '@primer/react';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { type Account, type GitifyError, Size } from '../../types';
import type { Notification } from '../../typesGitHub';
import { hasMultipleAccounts } from '../../utils/auth/utils';
Expand Down Expand Up @@ -38,7 +38,7 @@ export const AccountNotifications: FC<AccountNotificationsProps> = (
) => {
const { account, showAccountHeader, notifications } = props;

const { auth, settings } = useContext(AppContext);
const { auth, settings } = useAppContext();

const [showAccountNotifications, setShowAccountNotifications] =
useState(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { type FC, type MouseEvent, useContext } from 'react';
import type { FC, MouseEvent } from 'react';

import { Stack } from '@primer/react';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { GroupBy, Opacity, Size } from '../../types';
import type { Notification } from '../../typesGitHub';
import { cn } from '../../utils/cn';
Expand All @@ -16,7 +16,7 @@ interface NotificationHeaderProps {
export const NotificationHeader: FC<NotificationHeaderProps> = ({
notification,
}: NotificationHeaderProps) => {
const { settings } = useContext(AppContext);
const { settings } = useAppContext();

const repoSlug = notification.repository.full_name;

Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/notifications/NotificationRow.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { type FC, useCallback, useContext, useState } from 'react';
import { type FC, useCallback, useState } from 'react';

import { BellSlashIcon, CheckIcon, ReadIcon } from '@primer/octicons-react';
import { Stack, Text, Tooltip } from '@primer/react';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { GroupBy, Opacity, Size } from '../../types';
import type { Notification } from '../../typesGitHub';
import { cn } from '../../utils/cn';
Expand All @@ -29,7 +29,7 @@ export const NotificationRow: FC<NotificationRowProps> = ({
markNotificationsAsRead,
markNotificationsAsDone,
unsubscribeNotification,
} = useContext(AppContext);
} = useAppContext();
const [animateExit, setAnimateExit] = useState(false);

const handleNotification = useCallback(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { type FC, type MouseEvent, useContext, useState } from 'react';
import { type FC, type MouseEvent, useState } from 'react';

import { CheckIcon, ReadIcon } from '@primer/octicons-react';
import { Button, Stack } from '@primer/react';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { Opacity, Size } from '../../types';
import type { Notification } from '../../typesGitHub';
import { cn } from '../../utils/cn';
Expand All @@ -25,7 +25,7 @@ export const RepositoryNotifications: FC<RepositoryNotificationsProps> = ({
repoNotifications,
}) => {
const { settings, markNotificationsAsRead, markNotificationsAsDone } =
useContext(AppContext);
useAppContext();
const [animateExit, setAnimateExit] = useState(false);
const [showRepositoryNotifications, setShowRepositoryNotifications] =
useState(true);
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/primitives/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { type FC, useContext } from 'react';
import type { FC } from 'react';
import { useNavigate } from 'react-router-dom';

import { ArrowLeftIcon, type Icon } from '@primer/octicons-react';
import { IconButton, Stack } from '@primer/react';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { Title } from './Title';

interface HeaderProps {
Expand All @@ -16,7 +16,7 @@ interface HeaderProps {
export const Header: FC<HeaderProps> = (props: HeaderProps) => {
const navigate = useNavigate();

const { fetchNotifications } = useContext(AppContext);
const { fetchNotifications } = useAppContext();

return (
<div className="pl-4 pr-5 pt-3 pb-1">
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/settings/AppearanceSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type FC, useContext } from 'react';
import type { FC } from 'react';

import {
PaintbrushIcon,
Expand All @@ -15,7 +15,7 @@ import {
Text,
} from '@primer/react';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { Theme } from '../../types';
import { hasMultipleAccounts } from '../../utils/auth/utils';
import {
Expand All @@ -31,7 +31,7 @@ import { FieldLabel } from '../fields/FieldLabel';
import { Title } from '../primitives/Title';

export const AppearanceSettings: FC = () => {
const { auth, settings, updateSetting } = useContext(AppContext);
const { auth, settings, updateSetting } = useAppContext();
const zoomPercentage = zoomLevelToPercentage(window.gitify.zoom.getLevel());

return (
Expand Down
12 changes: 3 additions & 9 deletions src/renderer/components/settings/NotificationSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
type FC,
type MouseEvent,
useContext,
useEffect,
useState,
} from 'react';
import { type FC, type MouseEvent, useEffect, useState } from 'react';

import {
BellIcon,
Expand All @@ -25,7 +19,7 @@ import { formatDuration, millisecondsToMinutes } from 'date-fns';
import { APPLICATION } from '../../../shared/constants';

import { Constants } from '../../constants';
import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { FetchType, GroupBy, Size } from '../../types';
import { openGitHubParticipatingDocs } from '../../utils/links';
import { Checkbox } from '../fields/Checkbox';
Expand All @@ -34,7 +28,7 @@ import { RadioGroup } from '../fields/RadioGroup';
import { Title } from '../primitives/Title';

export const NotificationSettings: FC = () => {
const { settings, updateSetting } = useContext(AppContext);
const { settings, updateSetting } = useAppContext();
const [fetchInterval, setFetchInterval] = useState<number>(
settings.fetchInterval,
);
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/settings/SettingsReset.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { type FC, useContext } from 'react';
import type { FC } from 'react';

import { Button, Stack, useConfirm } from '@primer/react';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { rendererLogInfo } from '../../utils/logger';

export const SettingsReset: FC = () => {
const { resetSettings } = useContext(AppContext);
const { resetSettings } = useAppContext();

const confirm = useConfirm();

Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/settings/SystemSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { type FC, useContext } from 'react';
import type { FC } from 'react';

import { DeviceDesktopIcon, SyncIcon } from '@primer/octicons-react';
import { Button, ButtonGroup, IconButton, Stack, Text } from '@primer/react';

import { APPLICATION } from '../../../shared/constants';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { defaultSettings } from '../../context/defaults';
import { OpenPreference } from '../../types';
import {
Expand All @@ -21,7 +21,7 @@ import { VolumeUpIcon } from '../icons/VolumeUpIcon';
import { Title } from '../primitives/Title';

export const SystemSettings: FC = () => {
const { settings, updateSetting } = useContext(AppContext);
const { settings, updateSetting } = useAppContext();

return (
<fieldset>
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/settings/TraySettings.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { type FC, useContext } from 'react';
import type { FC } from 'react';

import { DevicesIcon } from '@primer/octicons-react';
import { Stack, Text } from '@primer/react';

import { APPLICATION } from '../../../shared/constants';

import { AppContext } from '../../context/App';
import { useAppContext } from '../../context/App';
import { Checkbox } from '../fields/Checkbox';
import { Title } from '../primitives/Title';

export const TraySettings: FC = () => {
const { settings, updateSetting } = useContext(AppContext);
const { settings, updateSetting } = useAppContext();

return (
<fieldset>
Expand Down
13 changes: 13 additions & 0 deletions src/renderer/context/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
createContext,
type ReactNode,
useCallback,
useContext,
useEffect,
useMemo,
useState,
Expand Down Expand Up @@ -108,6 +109,18 @@ export interface AppContextState {

export const AppContext = createContext<Partial<AppContextState>>({});

/**
* Custom hook that provides type-safe access to AppContext.
* Throws if used outside of AppProvider.
*/
export function useAppContext(): AppContextState {
const context = useContext(AppContext);
if (!context || Object.keys(context).length === 0) {
throw new Error('useAppContext must be used within an AppProvider');
}
return context as AppContextState;
}

export const AppProvider = ({ children }: { children: ReactNode }) => {
const existingState = loadState();

Expand Down
Loading