fix(marks): add default signer #207

Merged
enes merged 3 commits from 145-default-signer into 201-toolbox-update 2024-09-19 11:24:17 +00:00
6 changed files with 145 additions and 113 deletions
Showing only changes of commit 67c3c74515 - Show all commits

View File

@ -108,7 +108,6 @@ export const CreatePage = () => {
const [drawnFiles, setDrawnFiles] = useState<SigitFile[]>([]) const [drawnFiles, setDrawnFiles] = useState<SigitFile[]>([])
const [selectedTool, setSelectedTool] = useState<DrawTool>() const [selectedTool, setSelectedTool] = useState<DrawTool>()
const [toolbox] = useState<DrawTool[]>(DEFAULT_TOOLBOX)
/** /**
* Changes the drawing tool * Changes the drawing tool
@ -833,20 +832,27 @@ export const CreatePage = () => {
</div> </div>
<div className={`${styles.paperGroup} ${styles.toolbox}`}> <div className={`${styles.paperGroup} ${styles.toolbox}`}>
{toolbox.map((drawTool: DrawTool, index: number) => { {DEFAULT_TOOLBOX.filter((drawTool) => !drawTool.isHidden).map(
(drawTool: DrawTool, index: number) => {
return ( return (
<div <div
key={index} key={index}
{...(drawTool.active && { {...(!drawTool.isComingSoon && {
onClick: () => handleToolSelect(drawTool) onClick: () => handleToolSelect(drawTool)
})} })}
className={`${styles.toolItem} ${selectedTool?.identifier === drawTool.identifier ? styles.selected : ''} ${!drawTool.active ? styles.comingSoon : ''} className={`${styles.toolItem} ${selectedTool?.identifier === drawTool.identifier ? styles.selected : ''} ${drawTool.isComingSoon ? styles.comingSoon : ''}
`} `}
> >
<FontAwesomeIcon fontSize={'15px'} icon={drawTool.icon} /> <FontAwesomeIcon
fontSize={'15px'}
icon={drawTool.icon}
/>
{drawTool.label} {drawTool.label}
{drawTool.active ? ( {!drawTool.isComingSoon ? (
<FontAwesomeIcon fontSize={'15px'} icon={faEllipsis} /> <FontAwesomeIcon
fontSize={'15px'}
icon={faEllipsis}
/>
) : ( ) : (
<span className={styles.comingSoonPlaceholder}> <span className={styles.comingSoonPlaceholder}>
Coming soon Coming soon
@ -854,7 +860,8 @@ export const CreatePage = () => {
)} )}
</div> </div>
) )
})} }
)}
</div> </div>
<Button onClick={handleCreate} variant="contained"> <Button onClick={handleCreate} variant="contained">

View File

@ -31,7 +31,10 @@ export interface DrawTool {
icon: IconDefinition icon: IconDefinition
defaultValue?: string defaultValue?: string
selected?: boolean selected?: boolean
active?: boolean /** show or hide the toolbox item */
isHidden?: boolean
/** show or hide "coming soon" message on the toolbox item */
isComingSoon?: boolean
} }
export enum MarkType { export enum MarkType {

View File

@ -21,6 +21,8 @@ export const ONE_DAY_IN_MS = 24 * 60 * 60 * 1000
export const SIGIT_RELAY = 'wss://relay.sigit.io' export const SIGIT_RELAY = 'wss://relay.sigit.io'
export const SIGIT_BLOSSOM = 'https://blossom.sigit.io'
export const DEFAULT_LOOK_UP_RELAY_LIST = [ export const DEFAULT_LOOK_UP_RELAY_LIST = [
SIGIT_RELAY, SIGIT_RELAY,
'wss://user.kindpag.es', 'wss://user.kindpag.es',

View File

@ -3,14 +3,26 @@ import { hexToNpub } from './nostr.ts'
import { Meta, SignedEventContent } from '../types' import { Meta, SignedEventContent } from '../types'
import { Event } from 'nostr-tools' import { Event } from 'nostr-tools'
import { EMPTY } from './const.ts' import { EMPTY } from './const.ts'
import { MarkType } from '../types/drawing.ts' import { DrawTool, MarkType } from '../types/drawing.ts'
import { import {
faT, faT,
faSignature, faSignature,
faBriefcase, faBriefcase,
faIdCard, faIdCard,
faClock, faClock,
fa1 fa1,
faCalendarDays,
faCheckDouble,
faCircleDot,
faCreditCard,
faHeading,
faImage,
faPaperclip,
faPhone,
faSquareCaretDown,
faSquareCheck,
faStamp,
faTableCellsLarge
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
/** /**
@ -140,115 +152,114 @@ const findOtherUserMarks = (marks: Mark[], pubkey: string): Mark[] => {
return marks.filter((mark) => mark.npub !== hexToNpub(pubkey)) return marks.filter((mark) => mark.npub !== hexToNpub(pubkey))
} }
export const DEFAULT_TOOLBOX = [ export const DEFAULT_TOOLBOX: DrawTool[] = [
{ {
identifier: MarkType.FULLNAME, identifier: MarkType.FULLNAME,
icon: faIdCard, icon: faIdCard,
label: 'Full Name', label: 'Full Name',
active: false isComingSoon: true
}, },
{ {
identifier: MarkType.JOBTITLE, identifier: MarkType.JOBTITLE,
icon: faBriefcase, icon: faBriefcase,
label: 'Job Title', label: 'Job Title',
active: false isComingSoon: true
}, },
{ {
identifier: MarkType.SIGNATURE, identifier: MarkType.SIGNATURE,
icon: faSignature, icon: faSignature,
label: 'Signature', label: 'Signature',
active: false isComingSoon: true
}, },
{ {
identifier: MarkType.DATETIME, identifier: MarkType.DATETIME,
icon: faClock, icon: faClock,
label: 'Date Time', label: 'Date Time',
active: false isComingSoon: true
}, },
{ {
identifier: MarkType.TEXT, identifier: MarkType.TEXT,
icon: faT, icon: faT,
label: 'Text', label: 'Text'
active: true
}, },
{ {
identifier: MarkType.NUMBER, identifier: MarkType.NUMBER,
icon: fa1, icon: fa1,
label: 'Number', label: 'Number',
active: false isComingSoon: true
},
{
identifier: MarkType.INITIALS,
icon: faHeading,
label: 'Initials',
isHidden: true
},
{
identifier: MarkType.DATE,
icon: faCalendarDays,
label: 'Date',
isHidden: true
},
{
identifier: MarkType.IMAGES,
icon: faImage,
label: 'Images',
isHidden: true
},
{
identifier: MarkType.CHECKBOX,
icon: faSquareCheck,
label: 'Checkbox',
isHidden: true
},
{
identifier: MarkType.MULTIPLE,
icon: faCheckDouble,
label: 'Multiple',
isHidden: true
},
{
identifier: MarkType.FILE,
icon: faPaperclip,
label: 'File',
isHidden: true
},
{
identifier: MarkType.RADIO,
icon: faCircleDot,
label: 'Radio',
isHidden: true
},
{
identifier: MarkType.SELECT,
icon: faSquareCaretDown,
label: 'Select',
isHidden: true
},
{
identifier: MarkType.CELLS,
icon: faTableCellsLarge,
label: 'Cells',
isHidden: true
},
{
identifier: MarkType.STAMP,
icon: faStamp,
label: 'Stamp',
isHidden: true
},
{
identifier: MarkType.PAYMENT,
icon: faCreditCard,
label: 'Payment',
isHidden: true
},
{
identifier: MarkType.PHONE,
icon: faPhone,
label: 'Phone',
isHidden: true
} }
// {
// identifier: MarkType.INITIALS,
// icon: faHeading,
// label: 'Initials',
// active: false
// },
// {
// identifier: MarkType.DATE,
// icon: faCalendarDays,
// label: 'Date',
// active: false
// },
// {
// identifier: MarkType.IMAGES,
// icon: faImage,
// label: 'Images',
// active: false
// },
// {
// identifier: MarkType.CHECKBOX,
// icon: faSquareCheck,
// label: 'Checkbox',
// active: false
// },
// {

Isn't what the first PR already doing? And similar comment to the first PR - can we rely on the active flag rather than commenting out?

Isn't what the first PR already doing? And similar comment to the first PR - can we rely on the `active` flag rather than commenting out?
Outdated
Review

I mentioned this one is branched off the 201 so it includes the other PR commit.

I mentioned this one is branched off the 201 so it includes the other PR commit.

Do you still need the other PR?

Do you still need the other PR?
Outdated
Review

I'll combine this with the 201 so there's no confusion

I'll combine this with the 201 so there's no confusion
// identifier: MarkType.MULTIPLE,
// icon: faCheckDouble,
// label: 'Multiple',
// active: false
// },
// {
// identifier: MarkType.FILE,
// icon: faPaperclip,
// label: 'File',
// active: false
// },
// {
// identifier: MarkType.RADIO,
// icon: faCircleDot,
// label: 'Radio',
// active: false
// },
// {
// identifier: MarkType.SELECT,
// icon: faSquareCaretDown,
// label: 'Select',
// active: false
// },
// {
// identifier: MarkType.CELLS,
// icon: faTableCellsLarge,
// label: 'Cells',
// active: false
// },
// {
// identifier: MarkType.STAMP,
// icon: faStamp,
// label: 'Stamp',
// active: false
// },
// {
// identifier: MarkType.PAYMENT,
// icon: faCreditCard,
// label: 'Payment',
// active: false
// },
// {
// identifier: MarkType.PHONE,
// icon: faPhone,
// label: 'Phone',
// active: false
// }
] ]
export const getToolboxLabelByMarkType = (markType: MarkType) => { export const getToolboxLabelByMarkType = (markType: MarkType) => {

View File

@ -16,6 +16,8 @@ import { CreateSignatureEventContent, Meta } from '../types'
import { hexToNpub, unixNow } from './nostr' import { hexToNpub, unixNow } from './nostr'
import { parseJson } from './string' import { parseJson } from './string'
import { hexToBytes } from '@noble/hashes/utils' import { hexToBytes } from '@noble/hashes/utils'
import { getHash } from './hash.ts'
import { SIGIT_BLOSSOM } from './const.ts'
/** /**
* Uploads a file to a file storage service. * Uploads a file to a file storage service.
@ -25,12 +27,18 @@ import { hexToBytes } from '@noble/hashes/utils'
*/ */
export const uploadToFileStorage = async (file: File) => { export const uploadToFileStorage = async (file: File) => {
// Define event metadata for authorization // Define event metadata for authorization
const hash = await getHash(await file.arrayBuffer())
if (!hash) {
throw new Error("Can't get file hash.")
}
const event: EventTemplate = { const event: EventTemplate = {
kind: 24242, kind: 24242,
content: 'Authorize Upload', content: 'Authorize Upload',
created_at: unixNow(), created_at: unixNow(),
tags: [ tags: [
['t', 'upload'], ['t', 'upload'],
['x', hash],
['expiration', String(unixNow() + 60 * 5)], // Set expiration time to 5 minutes from now ['expiration', String(unixNow() + 60 * 5)], // Set expiration time to 5 minutes from now
['name', file.name], ['name', file.name],
['size', String(file.size)] ['size', String(file.size)]
@ -47,11 +55,8 @@ export const uploadToFileStorage = async (file: File) => {
// Sign the authorization event using the dedicated key stored in user app data // Sign the authorization event using the dedicated key stored in user app data
const authEvent = finalizeEvent(event, hexToBytes(key)) const authEvent = finalizeEvent(event, hexToBytes(key))
// URL of the file storage service
const FILE_STORAGE_URL = 'https://blossom.sigit.io' // REFACTOR: should be an env
// Upload the file to the file storage service using Axios // Upload the file to the file storage service using Axios
const response = await axios.put(`${FILE_STORAGE_URL}/upload`, file, { const response = await axios.put(`${SIGIT_BLOSSOM}/upload`, file, {
headers: { headers: {
Authorization: 'Nostr ' + btoa(JSON.stringify(authEvent)), // Set authorization header Authorization: 'Nostr ' + btoa(JSON.stringify(authEvent)), // Set authorization header
'Content-Type': 'application/sigit' // Set content type header 'Content-Type': 'application/sigit' // Set content type header

View File

@ -35,6 +35,7 @@ import { getDefaultRelayMap } from './relays'
import { parseJson, removeLeadingSlash } from './string' import { parseJson, removeLeadingSlash } from './string'
import { timeout } from './utils' import { timeout } from './utils'
import { getHash } from './hash' import { getHash } from './hash'
import { SIGIT_BLOSSOM } from './const.ts'
/** /**
* Generates a `d` tag for userAppData * Generates a `d` tag for userAppData
@ -723,6 +724,11 @@ const uploadUserAppDataToBlossom = async (
type: 'application/octet-stream' type: 'application/octet-stream'
}) })
const hash = await getHash(await file.arrayBuffer())
if (!hash) {
throw new Error("Can't get file hash.")
}
// Define event metadata for authorization // Define event metadata for authorization
const event: EventTemplate = { const event: EventTemplate = {
kind: 24242, kind: 24242,
@ -730,6 +736,7 @@ const uploadUserAppDataToBlossom = async (
created_at: unixNow(), created_at: unixNow(),
tags: [ tags: [
['t', 'upload'], ['t', 'upload'],
['x', hash],
['expiration', String(unixNow() + 60 * 5)], // Set expiration time to 5 minutes from now ['expiration', String(unixNow() + 60 * 5)], // Set expiration time to 5 minutes from now
['name', file.name], ['name', file.name],
['size', String(file.size)] ['size', String(file.size)]
@ -739,11 +746,8 @@ const uploadUserAppDataToBlossom = async (
// Finalize the event with the private key // Finalize the event with the private key
const authEvent = finalizeEvent(event, hexToBytes(privateKey)) const authEvent = finalizeEvent(event, hexToBytes(privateKey))
// URL of the file storage service
const FILE_STORAGE_URL = 'https://blossom.sigit.io'
// Upload the file to the file storage service using Axios // Upload the file to the file storage service using Axios
const response = await axios.put(`${FILE_STORAGE_URL}/upload`, file, { const response = await axios.put(`${SIGIT_BLOSSOM}/upload`, file, {
headers: { headers: {
Authorization: 'Nostr ' + btoa(JSON.stringify(authEvent)) // Set authorization header Authorization: 'Nostr ' + btoa(JSON.stringify(authEvent)) // Set authorization header
} }