Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new onboarding pages #272

Merged
merged 2 commits into from
Dec 6, 2023
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
33 changes: 22 additions & 11 deletions appviews/src/Administrate/screens/ExemptUsersScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ const ExemptUsersScreen: React.FC<Props> = ({ users, emit }) => {
</div>
<ul className="mt-4 space-y-2 flex-grow">
{users.value.map((user) => (
<User
<ExemptUser
key={user.id}
name={user.name}
isExempt={user.isExempt}
isAdmin={user.isAdmin}
onToggle={() =>
emit({
case: `setUserExemption`,
Expand Down Expand Up @@ -93,31 +94,41 @@ const ExemptUsersScreen: React.FC<Props> = ({ users, emit }) => {
);
};

interface UserProps {
interface ExemptUserProps {
name: string;
isExempt: boolean;
onToggle(): unknown;
isAdmin?: boolean;
}

const User: React.FC<UserProps> = ({ name, isExempt, onToggle }) => (
export const ExemptUser: React.FC<ExemptUserProps> = ({
name,
isExempt,
isAdmin,
onToggle,
}) => (
<div
onClick={onToggle}
className={cx(
`flex items-center justify-start rounded-xl p-2 pl-4`,
isExempt && `bg-red-50 dark:bg-red-500/10`,
)}
className={cx(`flex items-center justify-start rounded-xl p-2 pl-4`)}
>
<button
className={cx(
`w-5 h-5 rounded-full border-slate-300 dark:border-slate-700 border mr-4 flex justify-center items-center hover:scale-105 transition-[transform,border-color,border,background-color] duration-100`,
isExempt && `bg-red-500 !border-red-500 dark:border-red-500`,
isExempt && `bg-violet-500 !border-violet-500 dark:border-violet-500`,
)}
>
<i className="fa-solid fa-check text-white dark:text-slate-900 text-xs" />
</button>
<div className="flex items-center space-x-2 grow">
<h3 className="font-bold dark:text-white grow">{name}</h3>
<span className="text-red-500 dark:text-red-400 pr-2">
<div className="flex justify-between items-center space-x-2 flex-grow">
<div className="flex items-center">
<h3 className="font-bold dark:text-white grow mr-2">{name}</h3>
{isAdmin && (
<span className="text-fuchsia-500 font-medium uppercase text-xs bg-fuchsia-100 rounded-full px-2 py-0">
admin
</span>
)}
</div>
<span className="text-violet-500 dark:text-violet-400 pr-2 ml-4">
{isExempt ? `exempt from filtering - unrestricted internet access` : ``}
</span>
</div>
Expand Down
6 changes: 6 additions & 0 deletions appviews/src/Onboarding/Onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,15 @@ export const Onboarding: React.FC<Props> = ({
os === `venturaOrLater` ? `System Settings` : `System Preferences`,
emit,
dispatch,
otherUsers: users.filter((user) => user.id !== currentUser?.id),
}}
>
<StepSwitcher ready={receivedAppState}>
<OnboardingPage step="welcome" component={<Step.Welcome />} />
<OnboardingPage
step="appNotInApplicationsDir"
component={<Step.AppNotInApplicationsDir />}
/>
<OnboardingPage
step="confirmGertrudeAccount"
component={<Step.ConfirmGertrudeAccount />}
Expand Down Expand Up @@ -130,6 +135,7 @@ export const Onboarding: React.FC<Props> = ({
component={<Step.InstallSysExt step="installSysExt_success" />}
confetti
/>
<OnboardingPage step="exemptUsers" component={<Step.ExemptUsers />} />
<OnboardingPage step="locateMenuBarIcon" component={<Step.LocateMenuBarIcon />} />
<OnboardingPage step="viewHealthCheck" component={<Step.ViewHealthCheck />} />
<OnboardingPage step="howToUseGertrude" component={<Step.HowToUseGertrude />} />
Expand Down
10 changes: 9 additions & 1 deletion appviews/src/Onboarding/OnboardingContext.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { createContext } from 'react';
import type { AppEvent, OnboardingStep, OSGroup, ViewAction } from './onboarding-store';
import type {
AppEvent,
MacOSUser,
OnboardingStep,
OSGroup,
ViewAction,
} from './onboarding-store';

const OnboardingContext = createContext<{
otherUsers: MacOSUser[];
currentStep: OnboardingStep;
os: OSGroup;
systemSettingsName: string;
emit(event: AppEvent): unknown;
dispatch(event: ViewAction): unknown;
}>({
otherUsers: [],
currentStep: `welcome`,
os: `venturaOrLater`,
systemSettingsName: `System Settings`,
Expand Down
1 change: 1 addition & 0 deletions appviews/src/Onboarding/StepSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const StepSwitcher: React.FC<Props> = ({ children, ready }) => {
const progressStep = (() => {
switch (currentStep) {
case `welcome`:
case `appNotInApplicationsDir`:
case `confirmGertrudeAccount`:
case `noGertrudeAccount`:
return 1;
Expand Down
26 changes: 26 additions & 0 deletions appviews/src/Onboarding/Steps/AppNotInApplicationsDir.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import ExpandableContent from '../ExpandableContent';
import * as Onboarding from '../UtilityComponents';

const AppNotInApplicationsDir: React.FC = () => (
<Onboarding.Centered direction="row" className="gap-12">
<div className="flex flex-col items-start">
<Onboarding.Heading className="max-w-sm">
Hmm, something&apos;s not quite right...
</Onboarding.Heading>
<Onboarding.Text className="mt-4 max-w-2xl">
Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore
culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim
cupidatat excepteur officia.
</Onboarding.Text>
<Onboarding.PrimaryButton className="mt-8">Quit Gertrude</Onboarding.PrimaryButton>
</div>
<ExpandableContent
asset={{ type: `image`, url: ``, render: true }}
width={300}
height={200}
/>
</Onboarding.Centered>
);

export default AppNotInApplicationsDir;
37 changes: 37 additions & 0 deletions appviews/src/Onboarding/Steps/ExemptUsers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { inflect } from '@shared/string';
import React, { useContext } from 'react';
import { ExemptUser } from '../../Administrate/screens/ExemptUsersScreen';
import OnboardingContext from '../OnboardingContext';
import * as Onboarding from '../UtilityComponents';

const ExemptUsers: React.FC = () => {
const { otherUsers } = useContext(OnboardingContext);
return (
<Onboarding.Centered>
<Onboarding.Heading>Grant other users internet access</Onboarding.Heading>
<Onboarding.Text centered className="max-w-3xl mt-4">
For safety, Gertrude will block all internet access for other users unless you
explicitly exempt them from filtering. You have {otherUsers.length} other{` `}
{inflect(`user`, otherUsers.length)} on this computer; if you want them to have
access to the internet, click the corresponding checkbox below. Make sure your
child doesn&apos;t know the password for these unpretected users.
</Onboarding.Text>
<div className="min-w-[660px] border border-slate-200 bg-white rounded-2xl mt-8">
{otherUsers.map((user) => (
<ExemptUser
name={user.name}
isExempt={true}
onToggle={() => alert(`TODO`)}
isAdmin={user.isAdmin}
/>
))}
</div>
<Onboarding.PrimaryButton className="mt-8">
Continue
<i className="fa-solid fa-arrow-right ml-3" />
</Onboarding.PrimaryButton>
</Onboarding.Centered>
);
};

export default ExemptUsers;
2 changes: 2 additions & 0 deletions appviews/src/Onboarding/Steps/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { default as Welcome } from './Welcome';
export { default as AppNotInApplicationsDir } from './AppNotInApplicationsDir';
export { default as ConfirmGertrudeAccount } from './ConfirmGertrudeAccount';
export { default as GetConnectionCode } from './GetConnectionCode';
export { default as NoGertrudeAccount } from './NoGertrudeAccount';
Expand All @@ -8,6 +9,7 @@ export { default as AllowScreenshots } from './AllowScreenshots';
export { default as AllowNotifications } from './AllowNotifications';
export { default as AllowKeylogging } from './AllowKeylogging';
export { default as InstallSysExt } from './InstallSysExt';
export { default as ExemptUsers } from './ExemptUsers';
export { default as LocateMenuBarIcon } from './LocateMenuBarIcon';
export { default as ViewHealthCheck } from './ViewHealthCheck';
export { default as HowToUseGertrude } from './HowToUseGertrude';
Expand Down
2 changes: 2 additions & 0 deletions appviews/src/Onboarding/onboarding-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type RequestState<T = void, E = string> =
// begin codegen
export type OnboardingStep =
| 'welcome'
| 'appNotInApplicationsDir'
| 'confirmGertrudeAccount'
| 'noGertrudeAccount'
| 'macosUserAccountType'
Expand All @@ -29,6 +30,7 @@ export type OnboardingStep =
| 'installSysExt_allow'
| 'installSysExt_failed'
| 'installSysExt_success'
| 'exemptUsers'
| 'locateMenuBarIcon'
| 'viewHealthCheck'
| 'howToUseGertrude'
Expand Down
11 changes: 11 additions & 0 deletions storybook/src/macos-app/Onboarding.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const Welcome: Story = props({
keyloggingPermissionGranted: false,
currentUser: { id: 502, name: `Suzy`, isAdmin: false },
users: [
{ id: 503, name: `Little Jimmy`, isAdmin: false },
{ id: 501, name: `Bob McParent`, isAdmin: true },
{ id: 502, name: `Suzy`, isAdmin: false },
],
Expand All @@ -27,6 +28,11 @@ export const Welcome: Story = props({
receivedAppState: true,
});

export const AppNotInApplicationsDir: Story = props({
...Welcome.args,
step: `appNotInApplicationsDir`,
});

export const ConfirmGertrudeAcct: Story = props({
...Welcome.args,
step: `confirmGertrudeAccount`,
Expand Down Expand Up @@ -181,6 +187,11 @@ export const InstallSysExtSuccess: Story = props({
step: `installSysExt_success`,
});

export const ExemptUsers: Story = props({
...Welcome.args,
step: `exemptUsers`,
});

export const LocateMenuBarIcon: Story = props({
...Welcome.args,
step: `locateMenuBarIcon`,
Expand Down
11 changes: 11 additions & 0 deletions storybook/src/macos-app/OnboardingStatefulSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ const OnboardingStatefulSwitcher: React.FC = () => {
case `welcome`:
setTimeout(() => setStep(`confirmGertrudeAccount`), 1000); // this is handled in the component, but need to simulate it here
break;
case `appNotInApplicationsDir`:
setStep(`confirmGertrudeAccount`);
break;
case `confirmGertrudeAccount`:
setStep(`noGertrudeAccount`);
break;
Expand Down Expand Up @@ -76,6 +79,9 @@ const OnboardingStatefulSwitcher: React.FC = () => {
setStep(`installSysExt_success`);
break;
case `installSysExt_success`:
setStep(`exemptUsers`);
break;
case `exemptUsers`:
setStep(`locateMenuBarIcon`);
break;
case `locateMenuBarIcon`:
Expand All @@ -95,6 +101,10 @@ const OnboardingStatefulSwitcher: React.FC = () => {
>
<StepSwitcher ready>
<OnboardingPage step="welcome" component={<Step.Welcome />} />
<OnboardingPage
step="appNotInApplicationsDir"
component={<Step.AppNotInApplicationsDir />}
/>
<OnboardingPage
step="confirmGertrudeAccount"
component={<Step.ConfirmGertrudeAccount />}
Expand Down Expand Up @@ -186,6 +196,7 @@ const OnboardingStatefulSwitcher: React.FC = () => {
component={<Step.InstallSysExt step="installSysExt_success" />}
confetti
/>
<OnboardingPage step="exemptUsers" component={<Step.ExemptUsers />} />
<OnboardingPage step="locateMenuBarIcon" component={<Step.LocateMenuBarIcon />} />
<OnboardingPage step="viewHealthCheck" component={<Step.ViewHealthCheck />} />
<OnboardingPage step="howToUseGertrude" component={<Step.HowToUseGertrude />} />
Expand Down
Loading