Skip to content

Commit

Permalink
More cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
technoplato committed Mar 26, 2024
1 parent c416b07 commit b9b0d76
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 148 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ import {

import { unimplementedPermissionMachineActions } from './permission.actions';
import {
InitialPermissionStatusMap,
Permission,
PermissionMachineEvents,
PermissionStatus,
PermissionStatusMapType,
PermissionStatuses,
Permissions,
} from './permission.types';
import { InitialPermissionStatusMap } from './permission.fixtures';

export type ParentEvent =
export type PermissionMonitoringMachineEvents =
| {
type: 'allPermissionsChecked';
statuses: PermissionStatusMapType;
Expand All @@ -46,6 +46,7 @@ export type ParentEvent =
type ApplicationLifecycleState =
| 'applicationForegrounded'
| 'applicationBackgrounded';

type ApplicationStateChangeHandler = (event: ApplicationLifecycleState) => void;
const stubSubscribeToApplicationStateChanges = (
handleApplicationStateChange: ApplicationStateChangeHandler
Expand Down Expand Up @@ -116,7 +117,7 @@ describe('Permission Requester and Checker Machine', () => {
};

const parentMachine = setup({
types: {} as { events: ParentEvent },
types: {} as { events: PermissionMonitoringMachineEvents },
actors: {
permissionCheckerAndRequesterMachine,
},
Expand Down Expand Up @@ -193,7 +194,7 @@ describe('Permission Requester and Checker Machine', () => {
};

const parentMachine = setup({
types: {} as { events: ParentEvent },
types: {} as { events: PermissionMonitoringMachineEvents },
actors: {
permissionCheckerAndRequesterMachine,
},
Expand Down Expand Up @@ -243,7 +244,7 @@ describe('Permission Monitoring Machine', () => {
it('handle the happy path of being invoked, checking permission initially and then handle a permission request', async () => {
const permissionMonitoringMachine = setup({
types: {} as {
events: ParentEvent;
events: PermissionMonitoringMachineEvents;
context: { permissionsStatuses: PermissionStatusMapType };
},
actors: {
Expand Down Expand Up @@ -416,18 +417,18 @@ describe('Permission Monitoring Machine', () => {
const permissionCheckerAndRequesterMachine = setup({
types: {
context: {} as {
parent?: ActorRef<Snapshot<unknown>, ParentEvent>;
parent?: ActorRef<Snapshot<unknown>, PermissionMonitoringMachineEvents>;
statuses: PermissionStatusMapType;
},
events: {} as PermissionMachineEvents,
input: {} as {
parent?: ActorRef<Snapshot<unknown>, ParentEvent>;
parent?: ActorRef<Snapshot<unknown>, PermissionMonitoringMachineEvents>;
},
},

actions: {
checkedSendParent: enqueueActions(
({ context, enqueue }, event: ParentEvent) => {
({ context, enqueue }, event: PermissionMonitoringMachineEvents) => {
if (!context.parent) {
console.log(
'WARN: an attempt to send an event to a non-existent parent'
Expand Down
137 changes: 1 addition & 136 deletions libs/permissions/permissionLogic/src/lib/permission-logic.ts
Original file line number Diff line number Diff line change
@@ -1,136 +1 @@
import { fromCallback, raise, setup } from 'xstate';

export const Permissions = {
bluetooth: 'bluetooth',
microphone: 'microphone',
} as const;
export type Permission = (typeof Permissions)[keyof typeof Permissions];
export const PermissionStatuses = {
unasked: 'unasked',
granted: 'granted',
denied: 'denied',
revoked: 'revoked',
blocked: 'blocked',
} as const;
export type PermissionStatus =
(typeof PermissionStatuses)[keyof typeof PermissionStatuses];

type PermissionStatusMapType = Record<Permission, PermissionStatus>;
const PermissionStatusMap: PermissionStatusMapType = {
[Permissions.bluetooth]: PermissionStatuses.unasked,
[Permissions.microphone]: PermissionStatuses.unasked,
} as const;

type PermissionMonitoringMachineContext = {
permissionStatuses: PermissionStatusMapType;
};
type PermissionMonitoringMachineEvents =
| { type: 'checkPermissions' }
| {
type: 'permissionChecked';
permission: Permission;
status: PermissionStatus;
}
| { type: 'applicationForegrounded' }
| { type: 'applicationBackgrounded' };

const ApplicationLifecycleEvents = {
applicationForegrounded: 'applicationForegrounded',
applicationBackgrounded: 'applicationBackgrounded',
} as const;

type ApplicationLifecycleEvent =
(typeof ApplicationLifecycleEvents)[keyof typeof ApplicationLifecycleEvents];

// type PermissionMonitoringMachineInput = {
// subscribeToApplicationLifecycleEvents: (
// event: ApplicationLifecycleEvent
// ) => void;
// checkBluetoothPermission: () => Promise<PermissionStatus>;
// checkMicrophonePermission: () => Promise<PermissionStatus>;
// requestBluetoothPermission: () => Promise<PermissionStatus>;
// requestMicrophonePermission: () => Promise<PermissionStatus>;
// };

const permissionMonitoringMachine = setup({
types: {
// input: {} as PermissionMonitoringMachineInput,
context: {} as PermissionMonitoringMachineContext,
events: {} as PermissionMonitoringMachineEvents,
},
actions: {
triggerPermissionCheck: raise({ type: 'checkPermissions' }),
// decrement: assign({
// count: ({ context }) => context.count - 1,
// }),
},
actors: {
subscribeToApplicationLifecycleEvents: fromCallback(
({ input, sendBack, receive, self, system }) => {
// ...
// i have to have a default implementation here... what should it be?
// I'm leaning towards unimplemented to avoid confusion
/*
can't "forward" input to child actor...
input.subscribeToApplicationLifecycleEvents((event) => {
if (event === 'applicationForegrounded') {
sendBack({ type: 'applicationForegrounded' });
} else if (event === 'applicationBackgrounded') {
sendBack({ type: 'applicationBackgrounded' });
}
});
*/
}
),
bluetoothPermissionActor: fromCallback(
({ input, sendBack, receive, self, system }) => {
const checkPermission = (): Promise<PermissionStatus> => {
return Promise.resolve(PermissionStatuses.granted);
};

const requestPermission = (): Promise<PermissionStatus> => {
return Promise.resolve(PermissionStatuses.granted);
};

receive(async (event) => {
if (event.type === 'checkPermissions') {
const result = await checkPermission();
sendBack({
type: 'permissionChecked',
permission: Permissions.bluetooth,
status: result,
});
} else if (event.type === 'requestPermission') {
const result = await requestPermission();
sendBack({
type: 'permissionChecked',
permission: Permissions.bluetooth,
status: result,
});
}
});
// ...
// needs to listen for 'checkPermissions' and 'requestPermission' events and then
// return results back to parent actor
// also needs to ensure mapping of library type -> permission status type that we recognize and respond to
}
),
},
}).createMachine({
invoke: {
src: 'subscribeToApplicationLifecycleEvents',
id: 'applicationLifecycleEventsSubscriber',
},
context: { permissionStatuses: PermissionStatusMap },
on: {
applicationForegrounded: { target: 'application is in foreground' },
applicationBackgrounded: { target: 'application is in background' },
},
states: {
'application is in foreground': {
entry: ['triggerPermissionCheck'],
},
'application is in background': {},
},
});
export const foo = 'bar';
10 changes: 10 additions & 0 deletions libs/permissions/permissionLogic/src/lib/permission.fixtures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {
PermissionStatuses,
PermissionStatusMapType,
Permissions,
} from './permission.types';

export const InitialPermissionStatusMap: PermissionStatusMapType = {
[Permissions.bluetooth]: PermissionStatuses.unasked,
[Permissions.microphone]: PermissionStatuses.unasked,
} as const;
4 changes: 0 additions & 4 deletions libs/permissions/permissionLogic/src/lib/permission.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ export interface PermissionMachineActions {
}

export type PermissionStatusMapType = Record<Permission, PermissionStatus>;
export const InitialPermissionStatusMap: PermissionStatusMapType = {
[Permissions.bluetooth]: PermissionStatuses.unasked,
[Permissions.microphone]: PermissionStatuses.unasked,
} as const;

export const ApplicationLifecycleStates = {
applicationInForeground: 'application is in foreground',
Expand Down

0 comments on commit b9b0d76

Please sign in to comment.