wip split IrisAccount into smaller components

This commit is contained in:
Martti Malmi 2023-08-22 16:57:21 +03:00
parent 8c81d6dd3a
commit 6c21f112b9
5 changed files with 178 additions and 161 deletions

View File

@ -3,7 +3,7 @@ import Appearance from './Appearance';
import Backup from './Backup';
import ContentPage from './Content';
import Dev from './Dev';
import IrisAccount from './IrisAccount.js';
import IrisAccount from './irisaccount/IrisAccount.tsx';
import Language from './Language';
import Network from './Network.js';
import Payments from './Payments';

View File

@ -0,0 +1,30 @@
import { route } from 'preact-router';
export default function AccountName({ name, link = true }) {
return (
<>
<p>
Username: <b>{name}</b>
</p>
<p>
Short link:{' '}
{link ? (
<a
href={`https://iris.to/${name}`}
onClick={(e) => {
e.preventDefault();
route(`/${name}`);
}}
>
iris.to/{name}
</a>
) : (
<>iris.to/{name}</>
)}
</p>
<p>
Nostr address (nip05): <b>{name}@iris.to</b>
</p>
</>
);
}

View File

@ -0,0 +1,35 @@
import Key from '@/nostr/Key.ts';
import SocialNetwork from '@/nostr/SocialNetwork.ts';
import AccountName from '@/views/settings/irisaccount/AccountName.tsx';
export default function ActiveAccount({ name }) {
const setAsPrimary = () => {
const newNip = name + '@iris.to';
const timeout = setTimeout(() => {
SocialNetwork.setMetadata({ nip05: newNip });
}, 2000);
SocialNetwork.getProfile(Key.getPubKey(), (p) => {
if (p) {
clearTimeout(timeout);
if (p.nip05 !== newNip) {
p.nip05 = newNip;
SocialNetwork.setMetadata(p);
}
}
});
};
return (
<div>
<div className="negative">
You have an active iris.to account:
<AccountName name={name} />
</div>
<p>
<button className="btn btn-sm btn-primary" onClick={setAsPrimary}>
Set as primary Nostr address (nip05)
</button>
</p>
</div>
);
}

View File

@ -1,12 +1,13 @@
import debounce from 'lodash/debounce';
import { Event, UnsignedEvent } from 'nostr-tools';
import { Component } from 'preact';
import { route } from 'preact-router';
import Events from '../../nostr/Events';
import Key from '../../nostr/Key';
import SocialNetwork from '../../nostr/SocialNetwork';
import localState from '../../state/LocalState.ts';
import AccountName from '@/views/settings/irisaccount/AccountName.tsx';
import ActiveAccount from '@/views/settings/irisaccount/ActiveAccount.tsx';
import ReservedAccount from '@/views/settings/irisaccount/ReservedAccount.tsx';
import Events from '../../../nostr/Events.ts';
import Key from '../../../nostr/Key.ts';
import SocialNetwork from '../../../nostr/SocialNetwork.ts';
declare global {
interface Window {
@ -26,75 +27,16 @@ export default class IrisAccount extends Component {
invalidUsernameMessage: null as any,
};
renderAccountName(name, link = true) {
return (
<>
<p>
Username: <b>{name}</b>
</p>
<p>
Short link:{' '}
{link ? (
<a
href={`https://iris.to/${name}`}
onClick={(e) => {
e.preventDefault();
route(`/${name}`);
}}
>
iris.to/{name}
</a>
) : (
<>iris.to/{name}</>
)}
</p>
<p>
Nostr address (nip05): <b>{name}@iris.to</b>
</p>
</>
);
}
render() {
let view: any;
if (this.state.irisToActive) {
const username = this.state.profile.nip05.split('@')[0];
view = this.renderAccountName(username);
view = <AccountName name={username} />;
} else if (this.state.existing && this.state.existing.confirmed) {
view = (
<div>
<div className="negative">
You have an active iris.to account:
{this.renderAccountName(this.state.existing.name)}
</div>
<p>
<button className="btn btn-sm btn-primary" onClick={() => this.setAsPrimary()}>
Set as primary Nostr address (nip05)
</button>
</p>
</div>
);
view = <ActiveAccount name={this.state.existing.name} />;
} else if (this.state.existing) {
view = (
<div>
<p className="text-iris-green">
Username iris.to/<b>{this.state.existing.name}</b> is reserved for you until 12 March
2023!
</p>
{this.renderAccountName(this.state.existing.name, false)}
<p>
<button className="btn btn-sm btn-primary" onClick={() => this.enableReserved()}>
Yes please
</button>
</p>
<p>
<button className="btn btn-sm btn-neutral" onClick={() => this.declineReserved()}>
No thanks
</button>
</p>
</div>
);
view = <ReservedAccount name={this.state.existing.name} />;
} else if (this.state.error) {
view = <div className="text-iris-red">Error: {this.state.error}</div>;
} else if (this.state.showChallenge) {
@ -134,7 +76,7 @@ export default class IrisAccount extends Component {
{this.state.newUserNameValid ? (
<>
<span className="text-iris-green">Username is available</span>
{this.renderAccountName(this.state.newUserName, false)}
<AccountName name={this.state.newUserName} link={false} />
</>
) : (
<span className="text-iris-red">{this.state.invalidUsernameMessage}</span>
@ -261,97 +203,6 @@ export default class IrisAccount extends Component {
}
}
setAsPrimary() {
const newNip = this.state.existing.name + '@iris.to';
const timeout = setTimeout(() => {
SocialNetwork.setMetadata({ nip05: newNip });
}, 2000);
SocialNetwork.getProfile(Key.getPubKey(), (p) => {
if (p) {
clearTimeout(timeout);
if (p.nip05 !== newNip) {
p.nip05 = newNip;
SocialNetwork.setMetadata(p);
}
}
this.setState({ profile: p, irisToActive: true });
});
}
async enableReserved() {
const pubkey = Key.getPubKey();
const event: any = {
content: `iris.to/${this.state.existing.name}`,
kind: 1,
tags: [],
pubkey,
created_at: Math.floor(Date.now() / 1000),
};
event.id = Events.getEventHash(event);
event.sig = await Key.sign(event);
// post signed event as request body to https://api.iris.to/user/confirm_user
const res = await fetch('https://api.iris.to/user/confirm_user', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(event),
});
localState.get('showNoIrisToAddress').put(false);
localState.get('existingIrisToAddress').put({ confirmed: true, name });
if (res.status === 200) {
this.setState({
error: null,
existing: { confirmed: true, name: this.state.existing.name },
});
} else {
res
.json()
.then((json) => {
this.setState({ error: json.message || 'error' });
})
.catch(() => {
this.setState({ error: 'error' });
});
}
}
async declineReserved() {
if (!confirm(`Are you sure you want to decline iris.to/${this.state.existing.name}?`)) {
return;
}
const pubkey = Key.getPubKey();
const event: Partial<Event> = {
content: `decline iris.to/${this.state.existing.name}`,
kind: 1,
tags: [],
pubkey,
created_at: Math.floor(Date.now() / 1000),
};
event.id = Events.getEventHash(event as UnsignedEvent);
event.sig = await Key.sign(event as UnsignedEvent);
// post signed event as request body to https://api.iris.to/user/confirm_user
const res = await fetch('https://api.iris.to/user/decline_user', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(event),
});
if (res.status === 200) {
this.setState({ confirmSuccess: false, error: null, existing: null });
} else {
res
.json()
.then((json) => {
this.setState({ error: json.message || 'error' });
})
.catch(() => {
this.setState({ error: 'error' });
});
}
}
componentDidMount() {
const myPub = Key.getPubKey();
SocialNetwork.getProfile(

View File

@ -0,0 +1,101 @@
import { Event, UnsignedEvent } from 'nostr-tools';
import Events from '@/nostr/Events.ts';
import Key from '@/nostr/Key.ts';
import localState from '@/state/LocalState.ts';
import AccountName from '@/views/settings/irisaccount/AccountName.tsx';
export default function ReservedAccount({ name }) {
const enableReserved = async () => {
const pubkey = Key.getPubKey();
const event: any = {
content: `iris.to/${name}`,
kind: 1,
tags: [],
pubkey,
created_at: Math.floor(Date.now() / 1000),
};
event.id = Events.getEventHash(event);
event.sig = await Key.sign(event);
// post signed event as request body to https://api.iris.to/user/confirm_user
const res = await fetch('https://api.iris.to/user/confirm_user', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(event),
});
localState.get('showNoIrisToAddress').put(false);
localState.get('existingIrisToAddress').put({ confirmed: true, name });
if (res.status === 200) {
this.setState({
error: null,
existing: { confirmed: true, name: name },
});
} else {
res
.json()
.then((json) => {
this.setState({ error: json.message || 'error' });
})
.catch(() => {
this.setState({ error: 'error' });
});
}
};
const declineReserved = async () => {
if (!confirm(`Are you sure you want to decline iris.to/${name}?`)) {
return;
}
const pubkey = Key.getPubKey();
const event: Partial<Event> = {
content: `decline iris.to/${name}`,
kind: 1,
tags: [],
pubkey,
created_at: Math.floor(Date.now() / 1000),
};
event.id = Events.getEventHash(event as UnsignedEvent);
event.sig = await Key.sign(event as UnsignedEvent);
// post signed event as request body to https://api.iris.to/user/confirm_user
const res = await fetch('https://api.iris.to/user/decline_user', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(event),
});
if (res.status === 200) {
this.setState({ confirmSuccess: false, error: null, existing: null });
} else {
res
.json()
.then((json) => {
this.setState({ error: json.message || 'error' });
})
.catch(() => {
this.setState({ error: 'error' });
});
}
};
return (
<div>
<p className="text-iris-green">
Username iris.to/<b>{name}</b> is reserved for you!
</p>
<AccountName name={name} link={false} />
<p>
<button className="btn btn-sm btn-primary" onClick={() => enableReserved()}>
Yes please
</button>
</p>
<p>
<button className="btn btn-sm btn-neutral" onClick={() => declineReserved()}>
No thanks
</button>
</p>
</div>
);
}