Android robo-identities

This commit is contained in:
KoalaSat 2024-04-28 14:34:32 +02:00
parent 28cc3d6715
commit 66e9fc46c5
No known key found for this signature in database
GPG Key ID: 2F7F61C6146AB157
17 changed files with 99 additions and 46 deletions

View File

@ -178,7 +178,7 @@ const Onboarding = ({
/> />
</Grid> </Grid>
{slot?.hashId ? ( {slot?.nickname ? (
<Grid item> <Grid item>
<Typography align='center'>{t('Hi! My name is')}</Typography> <Typography align='center'>{t('Hi! My name is')}</Typography>
<Typography component='h5' variant='h5'> <Typography component='h5' variant='h5'>

View File

@ -64,7 +64,7 @@ const ProfileDialog = ({ open = false, onClose }: Props): JSX.Element => {
<ListItem className='profileNickname'> <ListItem className='profileNickname'>
<ListItemText> <ListItemText>
<Typography component='h6' variant='h6'> <Typography component='h6' variant='h6'>
{garage.getSlot()?.nickname !== undefined && ( {!garage.getSlot()?.nickname && (
<div style={{ position: 'relative', left: '-7px' }}> <div style={{ position: 'relative', left: '-7px' }}>
<div <div
style={{ style={{

View File

@ -81,7 +81,7 @@ class RoboGenerator {
hash, hash,
size, size,
) => { ) => {
const cacheKey = `${size}px;${hash}`; const cacheKey = `${hash};${size}`;
if (this.assetsCache[cacheKey]) { if (this.assetsCache[cacheKey]) {
return this.assetsCache[cacheKey]; return this.assetsCache[cacheKey];
} else { } else {

View File

@ -5,6 +5,7 @@ import { SendReceiveIcon } from '../Icons';
import placeholder from './placeholder.json'; import placeholder from './placeholder.json';
// import { robohash } from './RobohashGenerator'; // import { robohash } from './RobohashGenerator';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext'; import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
import { roboidentitiesClient } from '../../services/Roboidentities';
interface Props { interface Props {
shortAlias?: string | undefined; shortAlias?: string | undefined;
@ -53,22 +54,21 @@ const RobotAvatar: React.FC<Props> = ({
const backgroundImage = `url(data:${backgroundData.mime};base64,${backgroundData.data})`; const backgroundImage = `url(data:${backgroundData.mime};base64,${backgroundData.data})`;
const className = placeholderType === 'loading' ? 'loadingAvatar' : 'generatingAvatar'; const className = placeholderType === 'loading' ? 'loadingAvatar' : 'generatingAvatar';
// useEffect(() => { useEffect(() => {
// // TODO: HANDLE ANDROID AVATARS TOO (when window.NativeRobosats !== undefined) if (hashId !== undefined) {
// if (hashId !== undefined) { roboidentitiesClient
// robohash .generateRobohash(hashId, small ? 'small' : 'large')
// .generate(hashId, small ? 'small' : 'large') .then((avatar) => {
// .then((avatar) => { setAvatarSrc(avatar);
// setAvatarSrc(avatar); })
// }) .catch(() => {
// .catch(() => { setAvatarSrc('');
// setAvatarSrc(''); });
// }); setTimeout(() => {
// setTimeout(() => { setActiveBackground(false);
// setActiveBackground(false); }, backgroundFadeTime);
// }, backgroundFadeTime); }
// } }, [hashId]);
// }, [hashId]);
useEffect(() => { useEffect(() => {
if (shortAlias !== undefined) { if (shortAlias !== undefined) {

View File

@ -6,6 +6,7 @@ import {
type Order, type Order,
type Garage, type Garage,
} from '.'; } from '.';
import { roboidentitiesClient } from '../services/Roboidentities';
import { apiClient } from '../services/api'; import { apiClient } from '../services/api';
import { validateTokenEntropy } from '../utils'; import { validateTokenEntropy } from '../utils';
import { compareUpdateLimit } from './Limit.model'; import { compareUpdateLimit } from './Limit.model';
@ -174,9 +175,9 @@ export class Coordinator {
}; };
generateAllMakerAvatars = async (data: [PublicOrder]): Promise<void> => { generateAllMakerAvatars = async (data: [PublicOrder]): Promise<void> => {
// for (const order of data) { for (const order of data) {
// void robohash.generate(order.maker_hash_id, 'small'); roboidentitiesClient.generateRobohash(order.maker_hash_id, 'small');
// } }
}; };
loadBook = (onDataLoad: () => void = () => {}): void => { loadBook = (onDataLoad: () => void = () => {}): void => {

View File

@ -8,13 +8,12 @@ class Slot {
this.token = token; this.token = token;
this.hashId = sha256(sha256(this.token)); this.hashId = sha256(sha256(this.token));
this.nickname = ''; this.nickname = null;
roboidentitiesClient.generateRoboname(this.hashId).then((nickname) => { roboidentitiesClient.generateRoboname(this.hashId).then((nickname) => {
this.nickname = nickname; this.nickname = nickname;
}); });
// trigger RoboHash avatar generation in webworker and store in RoboHash class cache. roboidentitiesClient.generateRobohash(this.hashId, 'small');
// void robohash.generate(this.hashId, 'small'); roboidentitiesClient.generateRobohash(this.hashId, 'large');
// void robohash.generate(this.hashId, 'large');
this.robots = shortAliases.reduce((acc: Record<string, Robot>, shortAlias: string) => { this.robots = shortAliases.reduce((acc: Record<string, Robot>, shortAlias: string) => {
acc[shortAlias] = new Robot(robotAttributes); acc[shortAlias] = new Robot(robotAttributes);

View File

@ -1,20 +1,43 @@
import { type RoboidentitiesClient } from '..'; import { type RoboidentitiesClient } from '..';
import NativeRobosats from '../../Native';
class RoboidentitiesNativeClient implements RoboidentitiesClient { class RoboidentitiesNativeClient implements RoboidentitiesClient {
constructor() { private robonames: Record<string, string> = {};
window.NativeRobosats = new NativeRobosats(); private robohashes: Record<string, string> = {};
}
public loading = true;
public generateRoboname: (initialString: string) => Promise<string> = async (initialString) => { public generateRoboname: (initialString: string) => Promise<string> = async (initialString) => {
if (this.robonames[initialString]) {
return this.robonames[initialString];
} else {
const response = await window.NativeRobosats?.postMessage({ const response = await window.NativeRobosats?.postMessage({
category: 'roboIdentities', category: 'roboidentities',
type: 'roboname', type: 'roboname',
detail: initialString, detail: initialString,
}); });
return response ? Object.values(response)[0] : ''; const result = response ? Object.values(response)[0] : '';
this.robonames[initialString] = result;
return result;
}
};
public generateRobohash: (initialString: string, size: string) => Promise<string> = async (
initialString,
size,
) => {
const key = `${initialString};${size === 'small' ? 80 : 256}`;
if (this.robohashes[key]) {
return this.robohashes[key];
} else {
const response = await window.NativeRobosats?.postMessage({
category: 'roboidentities',
type: 'robohash',
detail: key,
});
const result = response ? Object.values(response)[0] : '';
const image = `data:image/png;base64,${result}`;
this.robohashes[key] = image;
return image;
}
}; };
} }

View File

@ -7,6 +7,15 @@ class RoboidentitiesClientWebClient implements RoboidentitiesClient {
// resolve(generate_roboname(initialString)) // resolve(generate_roboname(initialString))
}); });
}; };
public generateRobohash: (initialString: string, size: string) => Promise<string> = async (
initialString,
size,
) => {
return new Promise<string>(async (resolve, _reject) => {
// resolve(generate_roboname(initialString))
});
};
} }
export default RoboidentitiesClientWebClient; export default RoboidentitiesClientWebClient;

View File

@ -3,6 +3,7 @@ import RoboidentitiesClientWebClient from './RoboidentitiesWebClient';
export interface RoboidentitiesClient { export interface RoboidentitiesClient {
generateRoboname: (initialString: string) => Promise<string>; generateRoboname: (initialString: string) => Promise<string>;
generateRobohash: (initialString: string, size: string) => Promise<string>;
} }
export const roboidentitiesClient: RoboidentitiesClient = export const roboidentitiesClient: RoboidentitiesClient =

View File

@ -30,7 +30,6 @@ class ApiNativeClient implements ApiClient {
}; };
private readonly parseResponse = (response: Record<string, any>): object => { private readonly parseResponse = (response: Record<string, any>): object => {
console.log('response', response);
if (response.headers['set-cookie'] != null) { if (response.headers['set-cookie'] != null) {
response.headers['set-cookie'].forEach((cookie: string) => { response.headers['set-cookie'].forEach((cookie: string) => {
const keySplit: string[] = cookie.split('='); const keySplit: string[] = cookie.split('=');

View File

@ -132,8 +132,11 @@ const App = () => {
} }
} else if (data.category === 'roboidentities') { } else if (data.category === 'roboidentities') {
if (data.type === 'roboname') { if (data.type === 'roboname') {
const roboname = RoboIdentitiesModule.generateRoboname(data.detail); const roboname = await RoboIdentitiesModule.generateRoboname(data.detail);
injectMessageResolve(data.id, roboname); injectMessageResolve(data.id, { roboname });
} else if (data.type === 'robohash') {
const robohash = await RoboIdentitiesModule.generateRobohash(data.detail);
injectMessageResolve(data.id, { robohash });
} }
} }
}; };

View File

@ -1,14 +1,22 @@
package com.robosats; package com.robosats;
import android.util.Log;
public class RoboIdentities { public class RoboIdentities {
static { static {
System.loadLibrary("robonames"); System.loadLibrary("robonames");
System.loadLibrary("robohash");
} }
public String generateRoboname(String initial_string) { public String generateRoboname(String initial_string) {
return nativeGenerateRoboname(initial_string); return nativeGenerateRoboname(initial_string);
} }
public String generateRobohash(String initial_string) {
return nativeGenerateRobohash(initial_string);
}
// Native functions implemented in Rust. // Native functions implemented in Rust.
private static native String nativeGenerateRoboname(String initial_string); private static native String nativeGenerateRoboname(String initial_string);
private static native String nativeGenerateRobohash(String initial_string);
} }

View File

@ -2,9 +2,13 @@ package com.robosats.modules;
import android.util.Log; import android.util.Log;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.robosats.RoboIdentities; import com.robosats.RoboIdentities;
public class RoboIdentitiesModule extends ReactContextBaseJavaModule { public class RoboIdentitiesModule extends ReactContextBaseJavaModule {
@ -20,7 +24,14 @@ public class RoboIdentitiesModule extends ReactContextBaseJavaModule {
} }
@ReactMethod @ReactMethod
public String generateRoboname(String initial_string) { public void generateRoboname(String initial_string, final Promise promise) {
return new RoboIdentities().generateRoboname(initial_string); String roboname = new RoboIdentities().generateRoboname(initial_string);
promise.resolve(roboname);
}
@ReactMethod
public void generateRobohash(String initial_string, final Promise promise) {
String robohash = new RoboIdentities().generateRobohash(initial_string);
promise.resolve(robohash);
} }
} }

View File

@ -43,7 +43,6 @@ public class TorModule extends ReactContextBaseJavaModule {
@ReactMethod @ReactMethod
public void sendRequest(String action, String url, String headers, String body, final Promise promise) throws JSONException { public void sendRequest(String action, String url, String headers, String body, final Promise promise) throws JSONException {
Log.d("RobosatsUrl", url);
OkHttpClient client = new OkHttpClient.Builder() OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS) // Set connection timeout .connectTimeout(60, TimeUnit.SECONDS) // Set connection timeout
.readTimeout(30, TimeUnit.SECONDS) // Set read timeout .readTimeout(30, TimeUnit.SECONDS) // Set read timeout
@ -75,7 +74,6 @@ public class TorModule extends ReactContextBaseJavaModule {
@Override @Override
public void onResponse(Call call, Response response) throws IOException { public void onResponse(Call call, Response response) throws IOException {
Log.d("RobosatsCode", String.valueOf(response.code()));
String body = response.body() != null ? response.body().string() : "{}"; String body = response.body() != null ? response.body().string() : "{}";
JSONObject headersJson = new JSONObject(); JSONObject headersJson = new JSONObject();
response.headers().names().forEach(name -> { response.headers().names().forEach(name -> {

Binary file not shown.

View File

@ -2,7 +2,8 @@ import { NativeModules } from 'react-native';
const { RoboIdentitiesModule } = NativeModules; const { RoboIdentitiesModule } = NativeModules;
interface RoboIdentitiesModuleInterface { interface RoboIdentitiesModuleInterface {
generateRoboname: (initialString: String) => String; generateRoboname: (initialString: String) => Promise<string>;
generateRobohash: (initialString: String) => Promise<string>;
} }
export default RoboIdentitiesModule as RoboIdentitiesModuleInterface; export default RoboIdentitiesModule as RoboIdentitiesModuleInterface;