Skip to content

Commit

Permalink
feat: Metadata management page (#760)
Browse files Browse the repository at this point in the history
* build: bump polkadot/api version to latest

* fix: red boxes on registering networks

* build: mess with upgrades and lint

* feat: can delete unused metadata (except for built-in probably)
  • Loading branch information
Slesarew authored Apr 28, 2021
1 parent 32b2485 commit 4cb7d39
Show file tree
Hide file tree
Showing 8 changed files with 230 additions and 50 deletions.
98 changes: 98 additions & 0 deletions src/components/MetadataManagerTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React, { ReactElement } from 'react';
import { StyleSheet, Text, View } from 'react-native';

import TouchableItem from './TouchableItem';
import Separator from './Separator';

import FastQrScannerTab from 'components/FastQrScannerTab';
//import SwitchShowAllMetadata from 'components/SwitchShowAllMetadata';
//import SwitchMetadataDeletion from 'components/SwitchMetadataDeletion';
import colors from 'styles/colors';
import fontStyles from 'styles/fontStyles';
import { ButtonListener } from 'types/props';

type MetadataManagerTabProps = {
deletion: ButtonListener;
showall: ButtonListener;
isDeletion: boolean;
};

export default function MetadataManagerTab({
deletion,
showall,
isDeletion
}: MetadataManagerTabProps): React.ReactElement {
return (
<View style={styles.body}>
<Separator
shadow={true}
style={{ backgroundColor: 'transparent', marginVertical: 0 }}
shadowStyle={{ height: 16, marginTop: -16 }}
/>
<View style={styles.tab}>
<TouchableItem
accessibilityComponentType="button"
onPress={deletion}
style={styles.derivationButton}
>
<Text style={isDeletion ? styles.activeIcon : styles.icon}>🗑</Text>
<Text style={isDeletion ? styles.textLabelActive : styles.textLabel}>
Delete metadata mode
</Text>
</TouchableItem>
</View>
<View style={styles.tab}>
<FastQrScannerTab />
</View>
<View style={styles.tab}>
<TouchableItem
accessibilityComponentType="button"
onPress={showall}
style={styles.derivationButton}
>
<Text style={styles.icon}></Text>
<Text style={styles.textLabel}>Show all metadata</Text>
</TouchableItem>
</View>
</View>
);
}

const styles = StyleSheet.create({
activeIcon: {
...fontStyles.i_large,
color: colors.signal.error,
fontWeight: 'bold',
marginTop: 8
},
body: { flexDirection: 'row' },
derivationButton: {
alignItems: 'center',
backgroundColor: colors.background.os,
borderBottomColor: colors.background.app,
borderBottomWidth: 1,
height: 72,
justifyContent: 'center',
paddingVertical: 9
},
icon: {
...fontStyles.i_large,
color: colors.signal.main,
fontWeight: 'bold',
marginTop: 8
},
tab: {
flex: 1,
flexGrow: 1
},
textLabel: {
...fontStyles.a_text,
color: colors.text.faded,
marginTop: 4
},
textLabelActive: {
...fontStyles.a_text,
color: colors.text.alert,
marginTop: 4
}
});
54 changes: 33 additions & 21 deletions src/modules/network/screens/FullMetadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,53 +14,60 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

// This screen is not functional yet
// This screen should show full contents of chosen metadata

import React, {
ReactElement /*, useContext, useEffect, useState*/
} from 'react';
import { StyleSheet } from 'react-native';
import React, { ReactElement, useContext, useEffect, useState } from 'react';
import { StyleSheet, Text } from 'react-native';
import { TypeRegistry } from '@polkadot/types';
import { Metadata } from '@polkadot/metadata';
import { expandMetadata } from '@polkadot/metadata/decorate';

import { SafeAreaScrollViewContainer } from 'components/SafeAreaContainer';
//import { NetworksContext } from 'stores/NetworkContext';
import { NetworksContext } from 'stores/NetworkContext';
import { NavigationProps } from 'types/props';
//import { getSubstrateNetworkKeyByPathId } from 'utils/identitiesUtils';
//import { getMetadata } from 'utils/db';
import { getSubstrateNetworkKeyByPathId } from 'utils/identitiesUtils';
import { getMetadata } from 'utils/db';
//import { useFullMetadataHook } from 'modules/network/networksHooks';
import colors from 'styles/colors';
import fonts from 'styles/fonts';
import fontStyles from 'styles/fontStyles';

export default function FullMetadata({}: // navigation,
// route
NavigationProps<'NetworkSettings'>): React.ReactElement {
/*const networkPathId = route.params.pathId;
export default function FullMetadata({
navigation,
route
}: NavigationProps<'FullMetadataViewer'>): React.ReactElement {
const networkPathId = route.params.pathId;
const { networks } = useContext(NetworksContext);
const [savedMetadata, setSavedMetadata] = useState<string>('');
const networkKey = getSubstrateNetworkKeyByPathId(networkPathId, networks);
const metadataHandle = networks.get(networkKey).metadata;
const [metadataReady, setMetadataReady] = useState<bool>(false);
const metadataHandle = networks.get(networkKey)!.metadata;
const [metadataReady, setMetadataReady] = useState<boolean>(false);

useEffect(() => {
const getSavedMetadata = async function (): Promise<void> {
const newSavedMetadata = await getMetadata(metadataHandle);
setSavedMetadata(newSavedMetadata);
const registry = new TypeRegistry();
const metadata = new Metadata(registry, newSavedMetadata);
const decorated = expandMetadata(registry, metadata);
setSavedMetadata(JSON.stringify(decorated));
setMetadataReady(true);
};
getSavedMetadata();
}, [setSavedMetadata, setMetadataReady, metadataHandle]);
console.log(typeof savedMetadata);
console.log(metadataReady);

function showFullMetadata(): React.ReactNode {
if (metadataReady) {
return <Text>{savedMetadata}</Text>;
return <Text style={styles.titleText}>{savedMetadata}</Text>;
} else {
return;
}
}
{showFullMetadata()} //call it below
*/
return <SafeAreaScrollViewContainer style={styles.body} />;

return (
<SafeAreaScrollViewContainer style={styles.body}>
{showFullMetadata()}
</SafeAreaScrollViewContainer>
);
}

const styles = StyleSheet.create({
Expand All @@ -83,5 +90,10 @@ const styles = StyleSheet.create({
fontSize: 18,
paddingBottom: 10,
textAlign: 'center'
},
titleText: {
...fontStyles.t_codeS,
color: colors.text.main,
paddingHorizontal: 16
}
});
52 changes: 39 additions & 13 deletions src/modules/network/screens/MetadataManagement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,52 @@ import { NavigationProps } from 'types/props';
import { getSubstrateNetworkKeyByPathId } from 'utils/identitiesUtils';
import { MetadataHandle } from 'types/metadata';
import ScreenHeading from 'components/ScreenHeading';
import { getRelevantMetadata } from 'utils/db';
import FastQrScannerTab from 'components/FastQrScannerTab';
import { getRelevantMetadata, getAllMetadata, deleteMetadata } from 'utils/db';
import MetadataManagerTab from 'components/MetadataManagerTab';

export default function MetadataManagement({
navigation,
route
}: NavigationProps<'MetadataManagement'>): React.ReactElement {
const networkPathId = route.params.pathId;
const { networks, getSubstrateNetwork, setMetadataVersion } = useContext(
NetworksContext
);
const {
networks,
getSubstrateNetwork,
setMetadataVersion,
isMetadataActive
} = useContext(NetworksContext);
const networkKey = getSubstrateNetworkKeyByPathId(networkPathId, networks);
const networkParams = getSubstrateNetwork(networkKey);
const [knownMetadata, setKnownMetadata] = useState<Array<MetadataHandle>>([]);
const [showAll, setShowAll] = useState<boolean>(false);
const [deletionMode, setDeletionMode] = useState<boolean>(false);

useEffect(() => {
const getKnownMetadata = async function (specName: string): Promise<void> {
const newKnownMetadata = await getRelevantMetadata(specName);
setKnownMetadata(newKnownMetadata);
if (showAll) {
const newKnownMetadata = await getAllMetadata();
setKnownMetadata(newKnownMetadata);
} else {
const newKnownMetadata = await getRelevantMetadata(specName);
setKnownMetadata(newKnownMetadata);
}
};
if (networkParams.metadata)
getKnownMetadata(networkParams.metadata.specName);
}, [networkParams]);
}, [networkParams, showAll]);

function setMetadata(metadataHandle: MetadataHandle): void {
setMetadataVersion(networkKey, metadataHandle);
function chooseMetadata(metadataHandle: MetadataHandle): void {
if (deletionMode) {
console.log(metadataHandle);
console.log(networkParams.metadata);
if (isMetadataActive(metadataHandle)) {
console.warn('Metadata in use, please release it first');
} else {
deleteMetadata(metadataHandle);
}
} else {
setMetadataVersion(networkKey, metadataHandle);
}
navigation.goBack();
}

Expand All @@ -59,20 +79,26 @@ export default function MetadataManagement({
specName={item.specName}
specVersion={String(item.specVersion)}
metadataHash={item.hash}
onPress={(): void => setMetadata(item)}
onPress={(): void => chooseMetadata(item)}
/>
);
};

return (
<SafeAreaViewContainer>
<ScreenHeading title={networkParams.title} />
<ScreenHeading
title={deletionMode ? 'Delete metadata record' : networkParams.title}
/>
<FlatList
data={knownMetadata}
renderItem={renderMetadata}
keyExtractor={(item: MetadataHandle): string => item.hash}
/>
<FastQrScannerTab />
<MetadataManagerTab
deletion={(): void => setDeletionMode(!deletionMode)}
showall={(): void => setShowAll(!showAll)}
isDeletion={deletionMode}
/>
</SafeAreaViewContainer>
);
}
51 changes: 39 additions & 12 deletions src/stores/NetworkContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,14 @@ const networkTypesMap: NetworkTypesMap = {
centrifuge: {
alias: 'centrifuge-chain',
chains: {
centrifuge_amber: 'centrifuge-chain-amber'
centrifuge_amber: 'centrifuge-chain-amber',
edgeware: 'edgeware'
}
},
kusama: { chains: {} },
polkadot: {
chains: {
westend: 'Westend'
}
},
rococo: { chains: {} }
polkadot: { chains: {} },
rococo: { chains: {} },
westend: { chains: {} }
};

export const getOverrideTypes = (
Expand Down Expand Up @@ -115,6 +113,7 @@ export type NetworksContextState = {
) => TypeRegistry | null;
updateTypeRegistries: () => Promise<void>;
initTypeRegistry: (networkKey: string) => Promise<TypeRegistry | null>;
isMetadataActive: (metadataHandle: MetadataHandle) => boolean;
setMetadataVersion: (
networkKey: string,
metadataHandle: MetadataHandle
Expand Down Expand Up @@ -157,19 +156,23 @@ export function useNetworksContext(): NetworksContextState {
console.log('Populating registries...');
const initRegistries = new Map();
for (const networkKey of Array.from(initNetworkSpecs.keys())) {
console.log('Registering network:');
console.log(networkKey);
try {
const networkParams = initNetworkSpecs.get(networkKey)!;
console.log('Registering network:');
console.log(networkParams.pathId);
const metadataHandle = networkParams.metadata;
const networkMetadataRaw = await getMetadata(metadataHandle);
const newRegistry = new TypeRegistry();
//const overrideTypes = getOverrideTypes(newRegistry, networkParams.pathId);
//console.log(overrideTypes);
//newRegistry.register(overrideTypes);
const overrideTypes = getOverrideTypes(
newRegistry,
networkParams.pathId
);
//const overrideTypes = getSpecTypes(newRegistry, networkParams.pathId, metadataHandle.specName, Number.MAX_SAFE_INTEGER);
newRegistry.register(overrideTypes);
const metadata = new Metadata(newRegistry, networkMetadataRaw);
newRegistry.setMetadata(metadata);
initRegistries.set(networkKey, newRegistry);
console.log('Success!!!');
} catch (e) {
console.log('Init network registration error', e);
}
Expand Down Expand Up @@ -285,13 +288,37 @@ export function useNetworksContext(): NetworksContextState {
setRegistries(newRegistries);
}

function isMetadataActive(metadataHandle: MetadataHandle): boolean {
//weird development tool
//console.log('-----========------');
//console.log(dumpNetworksData());
//console.log('-----========------');

for (const network of substrateNetworks.entries()) {
if (
network[1].metadata &&
network[1].metadata.hash === metadataHandle.hash
) {
console.log('Its a match');
return true;
}
}
return false;
}

//This is a placeholder function to emulate rust-based native db
function dumpNetworksData(): string {
return JSON.stringify(Array.from(substrateNetworks.entries()));
}

return {
addNetwork,
allNetworks,
getNetwork,
getSubstrateNetwork: getSubstrateNetworkParams,
getTypeRegistry,
initTypeRegistry,
isMetadataActive,
networks: substrateNetworks,
pathIds,
populateNetworks,
Expand Down
1 change: 1 addition & 0 deletions src/styles/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default {
main: '#FF4077'
},
text: {
alert: '#D73400',
faded: '#9A9A9A',
main: '#C0C0C0'
}
Expand Down
1 change: 1 addition & 0 deletions src/types/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type RootStackParamList = {
NetworkSettings: undefined;
MetadataManagement: { pathId: string };
FullMetadata: { pathId: string };
FullMetadataViewer: { pathId: string };
PathDerivation: { parentPath: string };
PathDetails: { path: string };
PathManagement: { path: string };
Expand Down
Loading

0 comments on commit 4cb7d39

Please sign in to comment.