fix(#250): update cancel flows

This commit is contained in:
Paolo Miguel de Leon
2023-01-13 17:08:04 +08:00
parent a7d16322b6
commit 334c0cb31f
13 changed files with 140 additions and 34 deletions

View File

@@ -197,7 +197,7 @@
},
"rejected": {
"title": "Notice",
"message": "You rejected {{sender}}'s {{vcLabel}}"
"message": "You discarded {{sender}}'s {{vcLabel}}"
},
"disconnected": {
"title": "Disconnected",
@@ -240,7 +240,9 @@
"exchangingDeviceInfo": "Exchanging device info...",
"exchangingDeviceInfoTimeout": "It's taking a while to exchange device info. You may have to reconnect.",
"invalid": "Invalid QR Code",
"offline": "Please connect to the internet to scan QR codes using Online sharing mode"
"offline": "Please connect to the internet to scan QR codes using Online sharing mode",
"sent": "{{ vcLabel }} has been sent...",
"sentHint": "Waiting for receiver to save or discard your {{ vcLabel }}"
}
},
"SelectVcOverlay": {
@@ -266,7 +268,7 @@
},
"rejected": {
"title": "Notice",
"message": "Your {{vcLabel}} was rejected by {{receiver}}"
"message": "Your {{vcLabel}} was discarded by {{receiver}}"
}
},
"consentToPhotoVerification": "I give consent to have my photo taken for authentication"

View File

@@ -197,7 +197,7 @@
},
"rejected": {
"title": "Paunawa",
"message": "Tinanggihan mo ang {{vcLabel}} ni {{sender}}"
"message": "Iwinaksi ang {{vcLabel}} ni {{sender}}"
},
"disconnected": {
"title": "Nadiskonekta",
@@ -240,7 +240,9 @@
"exchangingDeviceInfo": "Nagpapalitan ng impormasyon ng device...",
"exchangingDeviceInfoTimeout": "Medyo nagtatagal ang paglabas ng impormasyon ng device. Bukas ba ang ibang device para sa mga koneksyon?",
"invalid": "Di-wasto ang QR Code",
"offline": "Mangyaring kumonekta sa internet upang makapag-scan ng QR codes na gumagamit ng Online sharing mode"
"offline": "Mangyaring kumonekta sa internet upang makapag-scan ng QR codes na gumagamit ng Online sharing mode",
"sent": "Naibahagi na ang {{vcLabel}}...",
"sentHint": "Iniintay ang nakatanggap na itabi o iwaksi ang iyong {{vcLabel}}"
}
},
"SelectVcOverlay": {
@@ -266,7 +268,7 @@
},
"rejected": {
"title": "Pansinin",
"message": "Ang iyong {{vcLabel}} ay tinanggihan ng {{receiver}}"
"message": "Iwinaksi ni {{receiver}} ang iyong {{vcLabel}}"
}
},
"consentToPhotoVerification": "Nagbibigay ako ng pahintulot na kunin ang aking larawan para sa pagpapatunay"

View File

@@ -304,6 +304,12 @@ export const requestMachine =
},
reviewing: {
invoke: {
src: 'sendVcResponse',
data: {
status: 'RECEIVED',
},
},
exit: 'disconnect',
initial: 'idle',
states: {
@@ -399,7 +405,7 @@ export const requestMachine =
},
},
accepted: {
entry: ['sendVcReceived', 'logReceived'],
entry: ['updateReceivedVcs', 'logReceived'],
invoke: {
src: 'sendVcResponse',
data: {
@@ -634,7 +640,7 @@ export const requestMachine =
{ to: (context) => context.serviceRefs.activityLog }
),
sendVcReceived: send(
updateReceivedVcs: send(
(context) => {
return VcEvents.VC_RECEIVED(VC_ITEM_STORE_KEY(context.incomingVc));
},
@@ -796,7 +802,7 @@ export const requestMachine =
}
},
sendVcResponse: (context, _event, meta) => () => {
sendVcResponse: (context, _event, meta) => async () => {
const event: SendVcResponseEvent = {
type: 'send-vc:response',
data: meta.data.status,
@@ -807,7 +813,8 @@ export const requestMachine =
// pass
});
} else {
onlineSend(event);
await GoogleNearbyMessages.unpublish();
await onlineSend(event);
}
},

View File

@@ -35,7 +35,8 @@ export interface Typegen0 {
sendDisconnect: 'done.invoke.request.cancelling:invocation[0]';
sendVcResponse:
| 'done.invoke.request.reviewing.accepted:invocation[0]'
| 'done.invoke.request.reviewing.rejected:invocation[0]';
| 'done.invoke.request.reviewing.rejected:invocation[0]'
| 'done.invoke.request.reviewing:invocation[0]';
verifyVp: 'done.invoke.request.reviewing.verifyingVp:invocation[0]';
};
'missingImplementations': {
@@ -86,7 +87,6 @@ export interface Typegen0 {
| 'FACE_VALID'
| 'done.invoke.request.reviewing.verifyingVp:invocation[0]';
requestReceiverInfo: 'CONNECTED';
sendVcReceived: 'STORE_RESPONSE';
setIncomingVc: 'VC_RECEIVED';
setReceiveLogTypeDiscarded: 'CANCEL' | 'REJECT';
setReceiveLogTypeRegular: 'ACCEPT';
@@ -96,6 +96,7 @@ export interface Typegen0 {
setSenderInfo: 'EXCHANGE_DONE';
storeVc: 'STORE_RESPONSE';
switchProtocol: 'SWITCH_PROTOCOL';
updateReceivedVcs: 'STORE_RESPONSE';
};
'eventsCausingDelays': {
CANCEL_TIMEOUT: 'CANCEL';
@@ -122,7 +123,7 @@ export interface Typegen0 {
receiveVc: 'EXCHANGE_DONE';
requestBluetooth: 'BLUETOOTH_DISABLED';
sendDisconnect: 'CANCEL';
sendVcResponse: 'CANCEL' | 'REJECT' | 'STORE_RESPONSE';
sendVcResponse: 'CANCEL' | 'REJECT' | 'STORE_RESPONSE' | 'VC_RECEIVED';
verifyVp: never;
};
'matchesStates':

View File

@@ -61,6 +61,7 @@ const model = createModel(
VERIFY_AND_ACCEPT_REQUEST: () => ({}),
VC_ACCEPTED: () => ({}),
VC_REJECTED: () => ({}),
VC_SENT: () => ({}),
CANCEL: () => ({}),
DISMISS: () => ({}),
CONNECTED: () => ({}),
@@ -232,12 +233,15 @@ export const scanMachine =
initial: 'selectingVc',
states: {
selectingVc: {
invoke: {
src: 'monitorCancellation',
},
on: {
UPDATE_REASON: {
actions: 'setReason',
},
DISCONNECT: {
target: '#scan.findingConnection',
target: '#scan.disconnected',
},
SELECT_VC: {
actions: 'setSelectedVc',
@@ -256,6 +260,7 @@ export const scanMachine =
actions: 'toggleShouldVerifyPresence',
},
},
exit: ['onlineUnsubscribe'],
},
cancelling: {
invoke: {
@@ -291,16 +296,26 @@ export const scanMachine =
},
},
},
sent: {
description:
'VC data has been shared and the receiver should now be viewing it',
on: {
VC_ACCEPTED: {
target: '#scan.reviewing.accepted',
},
VC_REJECTED: {
target: '#scan.reviewing.rejected',
},
},
},
},
on: {
DISCONNECT: {
target: '#scan.findingConnection',
},
VC_ACCEPTED: {
target: 'accepted',
},
VC_REJECTED: {
target: 'rejected',
VC_SENT: {
target: '#scan.reviewing.sendingVc.sent',
internal: true,
},
},
},
@@ -610,6 +625,10 @@ export const scanMachine =
shouldVerifyPresence: false,
}),
}),
onlineUnsubscribe: () => {
GoogleNearbyMessages.unsubscribe();
},
},
services: {
@@ -649,6 +668,14 @@ export const scanMachine =
}
},
monitorCancellation: (context) => async (callback) => {
if (context.sharingProtocol === 'ONLINE') {
await onlineSubscribe('disconnect', null, () =>
callback({ type: 'DISCONNECT' })
);
}
},
checkLocationStatus: () => (callback) => {
checkLocation(
() => callback(model.events.LOCATION_ENABLED()),
@@ -737,10 +764,15 @@ export const scanMachine =
};
const statusCallback = (status: SendVcStatus) => {
console.log('[scan] statusCallback', status);
if (typeof status === 'number') return;
callback({
type: status === 'ACCEPTED' ? 'VC_ACCEPTED' : 'VC_REJECTED',
});
if (status === 'RECEIVED') {
callback({ type: 'VC_SENT' });
} else {
callback({
type: status === 'ACCEPTED' ? 'VC_ACCEPTED' : 'VC_REJECTED',
});
}
};
if (context.sharingProtocol === 'OFFLINE') {
@@ -896,6 +928,10 @@ export function selectIsRejected(state: State) {
return state.matches('reviewing.rejected');
}
export function selectIsSent(state: State) {
return state.matches('reviewing.sendingVc.sent');
}
export function selectIsInvalid(state: State) {
return state.matches('invalid');
}
@@ -928,6 +964,10 @@ export function selectIsOffline(state: State) {
return state.matches('offline');
}
export function selectIsDisconnected(state: State) {
return state.matches('disconnected');
}
async function sendVc(
vc: VC,
callback: (status: SendVcStatus) => void,
@@ -968,7 +1008,9 @@ async function sendVc(
},
});
} else if (typeof status === 'string') {
GoogleNearbyMessages.unsubscribe();
if (status === 'ACCEPTED' || status === 'REJECTED') {
GoogleNearbyMessages.unsubscribe();
}
callback(status);
}
},

View File

@@ -8,6 +8,10 @@ export interface Typegen0 {
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'error.platform.scan.reviewing.creatingVp:invocation[0]': {
type: 'error.platform.scan.reviewing.creatingVp:invocation[0]';
data: unknown;
};
'xstate.after(CANCEL_TIMEOUT)#scan.reviewing.cancelling': {
type: 'xstate.after(CANCEL_TIMEOUT)#scan.reviewing.cancelling';
};
@@ -33,6 +37,7 @@ export interface Typegen0 {
createVp: 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
discoverDevice: 'done.invoke.scan.connecting:invocation[0]';
exchangeDeviceInfo: 'done.invoke.scan.exchangingDeviceInfo:invocation[0]';
monitorCancellation: 'done.invoke.scan.reviewing.selectingVc:invocation[0]';
monitorConnection: 'done.invoke.scan:invocation[0]';
sendDisconnect: 'done.invoke.scan.reviewing.cancelling:invocation[0]';
sendVc: 'done.invoke.scan.reviewing.sendingVc:invocation[0]';
@@ -73,6 +78,14 @@ export interface Typegen0 {
| 'xstate.stop';
logFailedVerification: 'FACE_INVALID';
logShared: 'VC_ACCEPTED';
onlineUnsubscribe:
| 'ACCEPT_REQUEST'
| 'CANCEL'
| 'DISCONNECT'
| 'SCREEN_BLUR'
| 'SCREEN_FOCUS'
| 'VERIFY_AND_ACCEPT_REQUEST'
| 'xstate.stop';
openSettings: 'LOCATION_REQUEST';
registerLoggers:
| 'DISCONNECT'
@@ -110,6 +123,7 @@ export interface Typegen0 {
SHARING_TIMEOUT:
| 'ACCEPT_REQUEST'
| 'FACE_VALID'
| 'VC_SENT'
| 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
};
'eventsCausingGuards': {
@@ -125,11 +139,17 @@ export interface Typegen0 {
exchangeDeviceInfo:
| 'CONNECTED'
| 'xstate.after(CONNECTION_TIMEOUT)#scan.exchangingDeviceInfo';
monitorCancellation:
| 'CANCEL'
| 'DISMISS'
| 'EXCHANGE_DONE'
| 'error.platform.scan.reviewing.creatingVp:invocation[0]';
monitorConnection: 'xstate.init';
sendDisconnect: 'CANCEL';
sendVc:
| 'ACCEPT_REQUEST'
| 'FACE_VALID'
| 'VC_SENT'
| 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
};
'matchesStates':
@@ -163,6 +183,7 @@ export interface Typegen0 {
| 'reviewing.selectingVc'
| 'reviewing.sendingVc'
| 'reviewing.sendingVc.inProgress'
| 'reviewing.sendingVc.sent'
| 'reviewing.sendingVc.timeout'
| 'reviewing.verifyingIdentity'
| {
@@ -184,7 +205,7 @@ export interface Typegen0 {
| 'selectingVc'
| 'sendingVc'
| 'verifyingIdentity'
| { sendingVc?: 'inProgress' | 'timeout' };
| { sendingVc?: 'inProgress' | 'sent' | 'timeout' };
};
'tags': never;
}

View File

@@ -8,9 +8,9 @@ export interface Typegen0 {
'invokeSrcNameMap': {};
'missingImplementations': {
actions: never;
services: never;
guards: never;
delays: never;
guards: never;
services: never;
};
'eventsCausingActions': {
getReceivedVcsResponse: 'GET_RECEIVED_VCS';
@@ -24,11 +24,11 @@ export interface Typegen0 {
setMyVcs: 'STORE_RESPONSE';
setReceivedVcs: 'STORE_RESPONSE';
};
'eventsCausingServices': {};
'eventsCausingDelays': {};
'eventsCausingGuards': {
hasExistingReceivedVc: 'VC_RECEIVED';
};
'eventsCausingDelays': {};
'eventsCausingServices': {};
'matchesStates':
| 'init'
| 'init.myVcs'

View File

@@ -10,7 +10,7 @@
},
"rejected": {
"title": "Notice",
"message": "You rejected {{sender}}'s {{vcLabel}}"
"message": "You discarded {{sender}}'s {{vcLabel}}"
},
"disconnected": {
"title": "Disconnected",

View File

@@ -10,6 +10,7 @@ import { useScanLayout } from './ScanLayoutController';
import { LanguageSelector } from '../../components/LanguageSelector';
import { ScanScreen } from './ScanScreen';
import { I18nManager, Platform } from 'react-native';
import { Message } from '../../components/Message';
const ScanStack = createNativeStackNavigator();
@@ -68,6 +69,14 @@ export const ScanLayout: React.FC = () => {
progress={!controller.isInvalid}
onBackdropPress={controller.DISMISS_INVALID}
/>
{controller.isDisconnected && (
<Message
title={t('RequestScreen:status.disconnected.title')}
message={t('RequestScreen:status.disconnected.message')}
onBackdropPress={controller.DISMISS}
/>
)}
</React.Fragment>
);
};

View File

@@ -16,6 +16,8 @@ import {
selectIsReviewing,
selectIsScanning,
selectIsOffline,
selectIsSent,
selectIsDisconnected,
} from '../../machines/scan';
import { selectVcLabel } from '../../machines/settings';
import { MainBottomTabParamList } from '../../routes/main';
@@ -30,6 +32,8 @@ type ScanLayoutNavigation = NavigationProp<
ScanStackParamList & MainBottomTabParamList
>;
// TODO: refactor
// eslint-disable-next-line sonarjs/cognitive-complexity
export function useScanLayout() {
const { t } = useTranslation('ScanScreen');
const { appService } = useContext(GlobalContext);
@@ -65,6 +69,9 @@ export function useScanLayout() {
selectIsExchangingDeviceInfoTimeout
);
const isOffline = useSelector(scanService, selectIsOffline);
const isSent = useSelector(scanService, selectIsSent);
const vcLabel = useSelector(settingsService, selectVcLabel);
const onCancel = () => scanService.send(ScanEvents.CANCEL());
let statusOverlay: Pick<
@@ -91,6 +98,11 @@ export function useScanLayout() {
hint: t('status.exchangingDeviceInfoTimeout'),
onCancel,
};
} else if (isSent) {
statusOverlay = {
message: t('status.sent', { vcLabel: vcLabel.singular }),
hint: t('status.sentHint', { vcLabel: vcLabel.singular }),
};
} else if (isInvalid) {
statusOverlay = {
message: t('status.invalid'),
@@ -130,12 +142,14 @@ export function useScanLayout() {
}, [isDone, isReviewing, isScanning]);
return {
vcLabel: useSelector(settingsService, selectVcLabel),
vcLabel,
isInvalid,
isDone,
isDisconnected: useSelector(scanService, selectIsDisconnected),
statusOverlay,
DISMISS: () => scanService.send(ScanEvents.DISMISS()),
DISMISS_INVALID: () =>
isInvalid ? scanService.send(ScanEvents.DISMISS()) : null,
};

View File

@@ -18,6 +18,8 @@
"exchangingDeviceInfo": "Exchanging device info...",
"exchangingDeviceInfoTimeout": "It's taking a while to exchange device info. You may have to reconnect.",
"invalid": "Invalid QR Code",
"offline": "Please connect to the internet to scan QR codes using Online sharing mode"
"offline": "Please connect to the internet to scan QR codes using Online sharing mode",
"sent": "{{ vcLabel }} has been sent...",
"sentHint": "Waiting for receiver to save or discard your {{ vcLabel }}"
}
}

View File

@@ -15,7 +15,7 @@
},
"rejected": {
"title": "Notice",
"message": "Your {{vcLabel}} was rejected by {{receiver}}"
"message": "Your {{vcLabel}} was discarded by {{receiver}}"
}
},
"consentToPhotoVerification": "I give consent to have my photo taken for authentication"

View File

@@ -23,6 +23,7 @@ export function onlineSubscribe<T extends SmartshareEventType>(
}
const response = SmartshareEvent.fromString<T>(foundMessage);
if (response.type === 'disconnect') {
GoogleNearbyMessages.unsubscribe();
disconectCallback(response.data);
} else if (response.type === eventType) {
!config?.keepAlive && GoogleNearbyMessages.unsubscribe();
@@ -34,7 +35,12 @@ export function onlineSubscribe<T extends SmartshareEventType>(
console.log('\n[request] MESSAGE_LOST', lostMessage.slice(0, 100));
}
}
);
).catch((error: Error) => {
if (error.message.includes('existing callback is already subscribed')) {
console.log('Existing callback found. Unsubscribing then retrying...');
return onlineSubscribe(eventType, callback, disconectCallback, config);
}
});
}
export function onlineSend(event: SmartshareEvents) {
@@ -113,7 +119,7 @@ export interface SendVcEvent {
};
}
export type SendVcStatus = 'ACCEPTED' | 'REJECTED';
export type SendVcStatus = 'ACCEPTED' | 'REJECTED' | 'RECEIVED';
export interface SendVcResponseEvent {
type: 'send-vc:response';
data: SendVcStatus | number;