Skip to content

Commit

Permalink
Merge pull request #189 from Sphereon-Opensource/feature/SPRIND-17
Browse files Browse the repository at this point in the history
integrated credential-branding dep into mobile-wallet
  • Loading branch information
nklomp authored Jun 28, 2024
2 parents 282da90 + 2ea5a5a commit 773fc10
Show file tree
Hide file tree
Showing 25 changed files with 90 additions and 377 deletions.
Empty file modified android/gradlew
100644 → 100755
Empty file.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@
"@sphereon/ssi-sdk.vc-handler-ld-local": "0.26.0",
"@sphereon/ssi-sdk.xstate-machine-persistence": "0.26.0",
"@sphereon/ssi-types": "0.26.0",
"@sphereon/ui-components.core": "0.2.0",
"@sphereon/ui-components.ssi-react-native": "0.2.0",
"@sphereon/ui-components.core": "0.2.1-unstable.44",
"@sphereon/ui-components.ssi-react-native": "0.2.1-unstable.44",
"@sphereon/ui-components.credential-branding": "0.2.1-unstable.44",
"@veramo/core": "4.2.0",
"@veramo/credential-w3c": "4.2.0",
"@veramo/data-store": "4.2.0",
Expand Down
4 changes: 2 additions & 2 deletions src/components/fields/SSIImageField/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import {
SSIImageFieldHeaderContainerStyled as HeaderContainer,
SSITextH5LightStyled as HeaderLabel,
} from '../../../styles/components';
import {ICredentialDetailsRow} from '../../../types';
import {CredentialDetailsRow} from '@sphereon/ui-components.credential-branding';

export interface IProps {
item: ICredentialDetailsRow;
item: CredentialDetailsRow;
index?: number;
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/fields/SSITextField/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import {
SSITextH5LightStyled as HeaderLabel,
SSITextFieldStatusLabelContainerStyled as StatusLabelContainer,
} from '../../../styles/components';
import {ICredentialDetailsRow} from '../../../types';
import {SSIStatusLabel} from '@sphereon/ui-components.ssi-react-native';
import {CredentialDetailsRow} from '@sphereon/ui-components.credential-branding';

export interface IProps {
item: ICredentialDetailsRow;
item: CredentialDetailsRow;
index?: number;
}

Expand Down
8 changes: 4 additions & 4 deletions src/components/views/SSICredentialDetailsView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ import {
SSICredentialDetailsViewFooterLabelValueStyled as IssuedBy,
SSICredentialDetailsViewFooterLabelCaptionStyled as IssuedByLabel,
} from '../../../styles/components';
import {ICredentialDetailsRow} from '../../../types';
import {CredentialDetailsRow} from '@sphereon/ui-components.credential-branding';
import SSIImageField from '../../fields/SSIImageField';
import SSITextField from '../../fields/SSITextField';

export interface IProps {
credentialProperties: Array<ICredentialDetailsRow>;
credentialProperties: Array<CredentialDetailsRow>;
issuer?: string;
}

// TODO we are now using this for more than just credential information. Would be nice to refactor it to be a more general usage component

const SSICredentialDetailsView: FC<IProps> = (props: IProps): JSX.Element => {
const renderItem = (itemInfo: ListRenderItemInfo<ICredentialDetailsRow>) => {
const renderItem = (itemInfo: ListRenderItemInfo<CredentialDetailsRow>) => {
if (itemInfo.item.imageSize) {
return <SSIImageField item={itemInfo.item} index={itemInfo.index} />;
} else {
Expand All @@ -47,7 +47,7 @@ const SSICredentialDetailsView: FC<IProps> = (props: IProps): JSX.Element => {
// TODO has a ItemSeparatorComponent which is a bit nicer to use then the logic now with margins
data={props.credentialProperties}
renderItem={renderItem}
keyExtractor={(item: ICredentialDetailsRow) => item.id}
keyExtractor={(item: CredentialDetailsRow) => item.id}
initialNumToRender={DETAILS_INITIAL_NUMBER_TO_RENDER}
removeClippedSubviews
ListFooterComponent={renderFooter}
Expand Down
4 changes: 2 additions & 2 deletions src/components/views/SSICredentialViewItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import {
SSITextH4LightStyled as IssuerCaption,
SSICredentialViewItemTitleCaptionStyled as TitleCaption,
} from '../../../styles/components';
import {ICredentialSummary} from '../../../types';
import {CredentialSummary} from '@sphereon/ui-components.credential-branding';
import {toLocalDateString, toLocalDateTimeString} from '../../../utils/DateUtils';
import {View} from 'react-native';

// TODO fix to many properties
export interface Props extends ICredentialSummary {
export interface Props extends CredentialSummary {
// TODO should only contain info this screen needs, ICredentialSummary is to much
showTime?: boolean;
}
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/IntentHandler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import store from '../../store';
import {storeVerifiableCredential} from '../../store/actions/credential.actions';
import {NavigationBarRoutesEnum, ScreenRoutesEnum, ToastTypeEnum} from '../../types';
import {parseDeepLink} from '../../utils';
import {toNonPersistedCredentialSummary} from '../../utils/mappers/credential/CredentialMapper';
import {toNonPersistedCredentialSummary} from '@sphereon/ui-components.credential-branding';
import {showToast} from '../../utils';
import LockingHandler from '../LockingHandler';

Expand Down
2 changes: 1 addition & 1 deletion src/navigation/machines/oid4vciStateNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ import {
OID4VCIProviderProps,
OID4VCIContext as OID4VCIContextType,
} from '@sphereon/ssi-sdk.oid4vci-holder';
import {toNonPersistedCredentialSummary} from '../../utils/mappers/credential/CredentialMapper';
import {translate} from '../../localization/Localization';
import RootNavigation from './../rootNavigation';
import {APP_ID} from '../../@config/constants';
import {MainRoutesEnum, NavigationBarRoutesEnum, PopupImagesEnum, ScreenRoutesEnum} from '../../types';
import {toNonPersistedCredentialSummary} from '@sphereon/ui-components.credential-branding';

const debug: Debugger = Debug(`${APP_ID}:oid4vciStateNavigation`);

Expand Down
5 changes: 3 additions & 2 deletions src/screens/Onboarding/SSISummaryScreen/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import SSICredentialDetailsView from '../../../components/views/SSICredentialDet
import SSITabView from '../../../components/views/SSITabView';
import {translate} from '../../../localization/Localization';
import {SSIBasicHorizontalCenterContainerStyled as Container} from '../../../styles/components';
import {ICredentialDetailsRow, ITabViewRoute, ScreenRoutesEnum, StackParamList} from '../../../types';
import {ITabViewRoute, ScreenRoutesEnum, StackParamList} from '../../../types';
import {backgroundColors} from '@sphereon/ui-components.core';
import {CredentialDetailsRow} from '@sphereon/ui-components.credential-branding';

type Props = NativeStackScreenProps<StackParamList, ScreenRoutesEnum.ONBOARDING_SUMMARY>;

Expand All @@ -35,7 +36,7 @@ const SSIOnboardingSummaryScreen: FC<Props> = (props: Props): JSX.Element => {
return true;
});

const getProperties = (): Array<ICredentialDetailsRow> => {
const getProperties = (): Array<CredentialDetailsRow> => {
return [
{
id: uuidv4(),
Expand Down
7 changes: 3 additions & 4 deletions src/screens/SSICredentialDetailsScreen/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import {PrimaryButton, SecondaryButton, SSICredentialCardView} from '@sphereon/u
import SSIActivityView from '../../components/views/SSIActivityView';
import SSICredentialDetailsView from '../../components/views/SSICredentialDetailsView';
import SSITabView from '../../components/views/SSITabView';
import {getCredentialStatus} from '../../utils/CredentialUtils';
import {getIssuerLogo} from '../../utils/mappers/credential/CredentialMapper';
import {CredentialSummary, getCredentialStatus, getIssuerLogo} from '@sphereon/ui-components.credential-branding';
import {translate} from '../../localization/Localization';
import {
SSICredentialDetailsScreenButtonContainer as ButtonContainer,
Expand All @@ -16,7 +15,7 @@ import {
SSICredentialDetailsScreenContentContainer as ContentContainer,
SSIStatusBarDarkModeStyled as StatusBar,
} from '../../styles/components';
import {ICredentialSummary, ITabViewRoute, ScreenRoutesEnum, StackParamList} from '../../types';
import {ITabViewRoute, ScreenRoutesEnum, StackParamList} from '../../types';
import {useBackHandler} from '@react-native-community/hooks';

type Props = NativeStackScreenProps<StackParamList, ScreenRoutesEnum.CREDENTIAL_DETAILS>;
Expand All @@ -26,7 +25,7 @@ enum CredentialTabRoutesEnum {
ACTIVITY = 'activity',
}

const getCredentialCardLogo = (credential: ICredentialSummary): ImageAttributes | undefined => {
const getCredentialCardLogo = (credential: CredentialSummary): ImageAttributes | undefined => {
if (credential.branding?.logo?.uri || credential.branding?.logo?.dataUri) {
return credential.branding.logo;
}
Expand Down
12 changes: 7 additions & 5 deletions src/screens/SSICredentialsOverviewScreen/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ import {
SSIRippleContainerStyled as ItemContainer,
SSIStatusBarDarkModeStyled as StatusBar,
} from '../../styles/components';
import {ICredentialSummary, IUser, IUserIdentifier, MainRoutesEnum, RootState, ScreenRoutesEnum, StackParamList} from '../../types';
import {IUser, IUserIdentifier, MainRoutesEnum, RootState, ScreenRoutesEnum, StackParamList} from '../../types';
import {getOriginalVerifiableCredential} from '../../utils/CredentialUtils';
import {backgroundColors, borderColors} from '@sphereon/ui-components.core';
import {CredentialSummary} from '@sphereon/ui-components.credential-branding';

interface IProps extends NativeStackScreenProps<StackParamList, ScreenRoutesEnum.CREDENTIALS_OVERVIEW> {
getVerifiableCredentials: () => void;
deleteVerifiableCredential: (credentialHash: string) => void;
verifiableCredentials: Array<ICredentialSummary>;
verifiableCredentials: Array<CredentialSummary>;
activeUser: IUser;
}

Expand Down Expand Up @@ -59,7 +60,7 @@ class SSICredentialsOverviewScreen extends PureComponent<IProps, IState> {
});
};

onItemPress = async (credential: ICredentialSummary): Promise<void> => {
onItemPress = async (credential: CredentialSummary): Promise<void> => {
getVerifiableCredential({hash: credential.hash}).then((vc: VerifiableCredential) =>
this.props.navigation.navigate(ScreenRoutesEnum.CREDENTIAL_DETAILS, {
rawCredential: getOriginalVerifiableCredential(vc),
Expand All @@ -69,7 +70,7 @@ class SSICredentialsOverviewScreen extends PureComponent<IProps, IState> {
);
};

renderItem = (itemInfo: ListRenderItemInfo<ICredentialSummary>): JSX.Element => {
renderItem = (itemInfo: ListRenderItemInfo<CredentialSummary>): JSX.Element => {
const {activeUser, verifiableCredentials} = this.props;

const credentialItem = (
Expand Down Expand Up @@ -113,12 +114,13 @@ class SSICredentialsOverviewScreen extends PureComponent<IProps, IState> {
};

render() {
console.log('this.props.verifiableCredentials:', this.props.verifiableCredentials);
return (
<Container>
<StatusBar />
<SwipeListView
data={this.props.verifiableCredentials}
keyExtractor={(itemInfo: ICredentialSummary) => itemInfo.hash}
keyExtractor={(itemInfo: CredentialSummary) => itemInfo.hash}
renderItem={this.renderItem}
closeOnRowOpen
closeOnRowBeginSwipe
Expand Down
6 changes: 3 additions & 3 deletions src/screens/SSICredentialsRequiredScreen/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import {
SSIBasicContainerStyled as Container,
SSIStatusBarDarkModeStyled as StatusBar,
} from '../../styles/components';
import {ICredentialSummary, ScreenRoutesEnum, StackParamList} from '../../types';
import {ScreenRoutesEnum, StackParamList} from '../../types';
import {getMatchingUniqueVerifiableCredential, getOriginalVerifiableCredential} from '../../utils';
import {toCredentialSummary} from '../../utils/mappers/credential/CredentialMapper';
import {JSONPath} from '@astronautlabs/jsonpath';
import {CredentialSummary, toCredentialSummary} from '@sphereon/ui-components.credential-branding';

type Props = NativeStackScreenProps<StackParamList, ScreenRoutesEnum.CREDENTIALS_REQUIRED>;

Expand Down Expand Up @@ -174,7 +174,7 @@ const SSICredentialsRequiredScreen: FC<Props> = (props: Props): JSX.Element => {
const credentialBranding: ICredentialBranding | undefined = credentialsBranding.find(
(branding: ICredentialBranding): boolean => branding.vcHash === uniqueVC.hash,
);
const credentialSummary: ICredentialSummary = await toCredentialSummary(uniqueVC, credentialBranding?.localeBranding);
const credentialSummary: CredentialSummary = await toCredentialSummary(uniqueVC, credentialBranding?.localeBranding);
const rawCredential: OriginalVerifiableCredential = getOriginalVerifiableCredential(uniqueVC.verifiableCredential);
const isSelected: boolean = userSelectedCredentials
.get(inputDescriptorId)!
Expand Down
2 changes: 1 addition & 1 deletion src/screens/Veramo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {connect} from 'react-redux';

import {createIdentifier, getIdentifiers} from '../services/identityService';
import {CredentialIssuanceStateEnum, RootState, ScreenRoutesEnum, StackParamList} from '../types';
import {toNonPersistedCredentialSummary} from '../utils/mappers/credential/CredentialMapper';
import {toNonPersistedCredentialSummary} from '@sphereon/ui-components.credential-branding';

interface IProps extends NativeStackScreenProps<StackParamList, 'Veramo'> {
contacts: Array<Party>;
Expand Down
34 changes: 2 additions & 32 deletions src/services/brandingService.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import {IBasicCredentialLocaleBranding, IBasicIssuerLocaleBranding, ICredentialBranding} from '@sphereon/ssi-sdk.data-store';
import {ICredentialBranding} from '@sphereon/ssi-sdk.data-store';
import {IDeletionResult} from '@sphereon/ssi-sdk.issuance-branding';
import Debug, {Debugger} from 'debug';

import {APP_ID} from '../@config/constants';
import {ibAddCredentialBranding, ibRemoveCredentialBranding} from '../agent';
import Localization from '../localization/Localization';
import {IAddCredentialBrandingArgs, IRemoveCredentialBrandingArgs, ISelectAppLocaleBrandingArgs} from '../types';
import {preloadImage} from '../utils/ImageUtils';
import {IAddCredentialBrandingArgs, IRemoveCredentialBrandingArgs} from '../types';

const debug: Debugger = Debug(`${APP_ID}:brandingService`);

Expand All @@ -19,31 +17,3 @@ export const removeCredentialBranding = async (args: IRemoveCredentialBrandingAr
debug(`removeCredentialBranding(${JSON.stringify(args)})...`);
return ibRemoveCredentialBranding(args);
};

export const selectAppLocaleBranding = async (
args: ISelectAppLocaleBrandingArgs,
): Promise<IBasicCredentialLocaleBranding | IBasicIssuerLocaleBranding | undefined> => {
// We need to retrieve the locale of the app and select a matching branding or fallback on a branding without a locale
// We search for a first match that starts with the app locale
const appLocale: string = Localization.getLocale();
const localeBranding: IBasicCredentialLocaleBranding | IBasicIssuerLocaleBranding | undefined = args.localeBranding?.find(
(branding: IBasicCredentialLocaleBranding | IBasicIssuerLocaleBranding) =>
branding.locale?.startsWith(appLocale) || branding.locale === undefined,
);

const logo: string | undefined = localeBranding?.logo?.dataUri || localeBranding?.logo?.uri;
if (logo) {
preloadImage([{uri: logo}]).catch((): void => {
//ignore
});
}

const backgroundImage: string | undefined = localeBranding?.background?.image?.dataUri || localeBranding?.background?.image?.uri;
if (backgroundImage) {
preloadImage([{uri: backgroundImage}]).catch((): void => {
//ignore
});
}

return localeBranding;
};
19 changes: 10 additions & 9 deletions src/store/actions/credential.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
getVerifiableCredentialsFromStorage,
storeVerifiableCredential as storeCredential,
} from '../../services/credentialService';
import {ICredentialSummary, RootState, ToastTypeEnum} from '../../types';
import {RootState, ToastTypeEnum} from '../../types';
import {
CREATE_CREDENTIAL_FAILED,
CREATE_CREDENTIAL_SUCCESS,
Expand All @@ -24,7 +24,8 @@ import {
STORE_CREDENTIAL_SUCCESS,
} from '../../types/store/credential.action.types';
import {showToast} from '../../utils/ToastUtils';
import {toCredentialSummary} from '../../utils/mappers/credential/CredentialMapper';
import {CredentialSummary, toCredentialSummary} from '@sphereon/ui-components.credential-branding';
import {getCredentialIssuerContact} from '../../utils';

export const getVerifiableCredentials = (): ThunkAction<Promise<void>, RootState, unknown, Action> => {
return async (dispatch: ThunkDispatch<RootState, unknown, Action>): Promise<void> => {
Expand All @@ -35,12 +36,12 @@ export const getVerifiableCredentials = (): ThunkAction<Promise<void>, RootState
vcHash: uniqueCredential.hash,
}));
const credentialsBranding: Array<ICredentialBranding> = await ibGetCredentialBranding({filter: vcHashes});
const credentialSummaries: Array<ICredentialSummary> = await Promise.all(
credentials.map(async (uniqueVC: UniqueVerifiableCredential): Promise<ICredentialSummary> => {
const credentialSummaries: Array<CredentialSummary> = await Promise.all(
credentials.map(async (uniqueVC: UniqueVerifiableCredential): Promise<CredentialSummary> => {
const credentialBranding: ICredentialBranding | undefined = credentialsBranding.find(
(branding: ICredentialBranding): boolean => branding.vcHash === uniqueVC.hash,
);
return await toCredentialSummary(uniqueVC, credentialBranding?.localeBranding);
return await toCredentialSummary(uniqueVC, credentialBranding?.localeBranding, getCredentialIssuerContact(uniqueVC.verifiableCredential));
}),
);
dispatch({type: GET_CREDENTIALS_SUCCESS, payload: [...credentialSummaries]});
Expand All @@ -54,11 +55,11 @@ export const storeVerifiableCredential = (vc: VerifiableCredential): ThunkAction
dispatch({type: CREDENTIALS_LOADING});
const mappedVc: VerifiableCredential = CredentialMapper.toUniformCredential(vc as OriginalVerifiableCredential) as VerifiableCredential;
storeCredential({vc: mappedVc})
.then(async (hash: string): Promise<ICredentialSummary> => {
.then(async (hash: string): Promise<CredentialSummary> => {
const credentialBranding: Array<ICredentialBranding> = await ibGetCredentialBranding({filter: [{vcHash: hash}]});
return toCredentialSummary({verifiableCredential: mappedVc, hash}, credentialBranding?.[0]?.localeBranding);
})
.then((summary: ICredentialSummary): void => {
.then((summary: CredentialSummary): void => {
dispatch({
type: STORE_CREDENTIAL_SUCCESS,
payload: summary,
Expand All @@ -83,7 +84,7 @@ export const dispatchVerifiableCredential = (
.then((credentialBranding: Array<ICredentialBranding>) =>
toCredentialSummary({verifiableCredential: mappedVc, hash: credentialHash}, credentialBranding?.[0]?.localeBranding),
)
.then((summary: ICredentialSummary): void => {
.then((summary: CredentialSummary): void => {
dispatch({
type: STORE_CREDENTIAL_SUCCESS,
payload: summary,
Expand Down Expand Up @@ -126,7 +127,7 @@ export const createVerifiableCredential = (args: ICreateVerifiableCredentialArgs
createCredential(args)
.then((vc: VerifiableCredential): void => {
storeCredential({vc}).then((hash: string) =>
toCredentialSummary({verifiableCredential: vc, hash}).then((summary: ICredentialSummary) =>
toCredentialSummary({verifiableCredential: vc, hash}).then((summary: CredentialSummary) =>
// TODO fix mismatch in types
dispatch({
type: CREATE_CREDENTIAL_SUCCESS,
Expand Down
4 changes: 2 additions & 2 deletions src/store/reducers/credential.reducer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {ICredentialSummary} from '../../types';
import {
CLEAR_CREDENTIALS,
CREATE_CREDENTIAL_FAILED,
Expand All @@ -13,6 +12,7 @@ import {
STORE_CREDENTIAL_SUCCESS,
} from '../../types/store/credential.action.types';
import {ICredentialState} from '../../types/store/credential.types';
import {CredentialSummary} from '@sphereon/ui-components.credential-branding';

const initialState: ICredentialState = {
loading: false,
Expand Down Expand Up @@ -58,7 +58,7 @@ const credentialReducer = (state: ICredentialState = initialState, action: Crede
case DELETE_CREDENTIAL_SUCCESS: {
return {
...state,
verifiableCredentials: state.verifiableCredentials.filter((vc: ICredentialSummary) => vc.hash !== action.payload),
verifiableCredentials: state.verifiableCredentials.filter((vc: CredentialSummary) => vc.hash !== action.payload),
loading: false,
};
}
Expand Down
2 changes: 0 additions & 2 deletions src/types/component/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ export interface IHeaderMenuButton extends IButton {
fontColor?: ColorValue;
}

export type LabelStatus = CredentialStatus | IssuerStatus;

export interface ITabRoute {
key: string;
title: string;
Expand Down
Loading

0 comments on commit 773fc10

Please sign in to comment.