Skip to content

Commit

Permalink
🔀 Merge epubMetadata branch to deploy/rinkeby
Browse files Browse the repository at this point in the history
  • Loading branch information
AuroraHuang22 committed Nov 1, 2023
2 parents fcf9ac1 + 6614425 commit 246e87f
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 8 deletions.
23 changes: 23 additions & 0 deletions components/IscnRegisterForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ export enum AuthorDialogType {
export default class IscnRegisterForm extends Vue {
@Prop({ default: [] }) readonly fileRecords!: any[]
@Prop({ default: [] }) readonly uploadArweaveList!: any[]
@Prop() readonly epubMetadata!: any | null
@Prop(String) readonly ipfsHash!: string
@Prop(String) readonly arweaveId!: string
Expand Down Expand Up @@ -835,6 +836,7 @@ export default class IscnRegisterForm extends Vue {
currentAuthorDialogType: AuthorDialogType = AuthorDialogType.stakeholder
sameAsList: any = []
language: string = ''
get ipfsHashList() {
const list = []
Expand Down Expand Up @@ -1002,6 +1004,8 @@ export default class IscnRegisterForm extends Vue {
likerIdsAddresses: this.likerIdsAddresses,
authorDescriptions: this.authorDescriptions,
contentFingerprints: this.customContentFingerprints,
inLanguage: this.language,
thumbnail: this.epubMetadata.thumbnail,
}
}
Expand Down Expand Up @@ -1080,6 +1084,16 @@ export default class IscnRegisterForm extends Vue {
if (this.arweaveId){
this.uploadArweaveIdList.push(this.arweaveId)
}
if (this.epubMetadata) {
this.name = this.epubMetadata.title;
this.description = this.extractText(this.epubMetadata.description);
this.author.name = this.epubMetadata.author;
this.language = this.epubMetadata.language
this.tags = this.epubMetadata.tags
if (this.author.name) { this.authors.push(this.author) }
}
this.uploadStatus = 'loading'
// ISCN Fee needs Arweave fee to calculate
await this.calculateISCNFee()
Expand Down Expand Up @@ -1425,5 +1439,14 @@ export default class IscnRegisterForm extends Vue {
this.displayImageSrc = this.fileRecords[index].fileData
this.displayExifInfo = this.fileRecords[index].exifInfo
}
// eslint-disable-next-line class-methods-use-this
extractText(htmlString: string) {
if (!htmlString) return ''
const div = document.createElement('div');
div.innerHTML = htmlString;
div.innerHTML = div.innerHTML.replace(/<br\s*[/]?>/gi, "\n");
return div.textContent || div.innerText;
}
}
</script>
139 changes: 134 additions & 5 deletions components/IscnUploadForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,11 @@ import { namespace } from 'vuex-class'
import exifr from 'exifr'
import Hash from 'ipfs-only-hash'
import BigNumber from 'bignumber.js'
import ePub from 'epubjs';
import { OfflineSigner } from '@cosmjs/proto-signing'
import { IS_CHAIN_UPGRADING, UPLOAD_FILESIZE_MAX } from '~/constant'
import { IS_CHAIN_UPGRADING, UPLOAD_FILESIZE_MAX, IPFS_VIEW_GATEWAY_URL } from '~/constant'
import { logTrackerEvent } from '~/utils/logger'
import { estimateBundlrFilePrice, uploadSingleFileToBundlr } from '~/utils/arweave/v2'
import {
Expand Down Expand Up @@ -314,8 +315,6 @@ export default class UploadForm extends Vue {
string, { transactionHash?: string, arweaveId?: string }
>()
likerId: string = ''
likerIdsAddresses: (string | void)[] = []
error: string = ''
Expand All @@ -325,6 +324,8 @@ export default class UploadForm extends Vue {
signDialogError = ''
balance = new BigNumber(0)
epubMetadataList: any[] = []
get formClasses() {
return [
'flex',
Expand Down Expand Up @@ -412,6 +413,10 @@ export default class UploadForm extends Vue {
}
}
mounted() {
this.epubMetadataList = []
}
async onFileUpload(event: DragEvent) {
logTrackerEvent(this, 'ISCNCreate', 'SelectFile', '', 1)
this.isSizeExceeded = false
Expand Down Expand Up @@ -478,6 +483,10 @@ export default class UploadForm extends Vue {
console.error(err)
}
}
if (file.type === 'application/epub+zip') {
// eslint-disable-next-line no-await-in-loop
await this.processEPub({ buffer: fileBytes, file })
}
}
} else {
this.isSizeExceeded = true
Expand All @@ -487,6 +496,112 @@ export default class UploadForm extends Vue {
}
}
async processEPub({ buffer, file }: { buffer: ArrayBuffer; file: File }) {
try {
const Book = ePub(buffer)
await Book.ready
const epubMetadata: any = {}
// Get metadata
const { metadata } = Book.packaging
if (metadata) {
epubMetadata.epubFileName = file.name
epubMetadata.title = metadata.title
epubMetadata.author = metadata.creator
epubMetadata.language = this.formatLanguage(metadata.language)
epubMetadata.description = metadata.description
}
// Get tags
const opfFilePath = await (Book.path as any).path
const opfContent = await Book.archive.getText(opfFilePath)
const parser = new DOMParser()
const opfDocument = parser.parseFromString(opfContent, 'application/xml')
const dcSubjectElements = opfDocument.querySelectorAll(
'dc\\:subject, subject',
)
const subjects: string[] = []
dcSubjectElements.forEach((element) => {
const subject = element.textContent
subject && subjects.push(subject)
})
epubMetadata.tags = subjects
// Get cover file
const coverUrl = (Book as any).cover
if (!coverUrl) {
this.epubMetadataList.push(epubMetadata)
return
}
const blobData = await Book.archive.getBlob(coverUrl)
if (blobData) {
const coverFile = new File([blobData], `${metadata.title}_cover.jpeg`, {
type: 'image/jpeg',
})
const fileBytes = (await fileToArrayBuffer(
coverFile,
)) as unknown as ArrayBuffer
if (fileBytes) {
const [
fileSHA256,
imageType,
ipfsHash,
// eslint-disable-next-line no-await-in-loop
] = await Promise.all([
digestFileSHA256(fileBytes),
readImageType(fileBytes),
Hash.of(Buffer.from(fileBytes)),
])
const fileRecord: any = {
fileName: coverFile.name,
fileSize: coverFile.size,
fileType: coverFile.type,
fileBlob: coverFile,
ipfsHash,
fileSHA256,
isFileImage: !!imageType,
}
epubMetadata.thumbnail = {
"@type": "ImageObject",
url: `${IPFS_VIEW_GATEWAY_URL}${ipfsHash}`,
name: `${file.name}_cover`,
description: `${file.name}_cover`,
encodingFormat: "image/jpeg",
};
const reader = new FileReader()
reader.onload = (e) => {
if (!e.target) return
fileRecord.fileData = e.target.result as string
}
reader.readAsDataURL(coverFile)
this.epubMetadataList = [
...this.epubMetadataList,
epubMetadata,
]
this.fileRecords.push(fileRecord)
}
}
} catch (err) {
console.error(err)
}
}
// eslint-disable-next-line class-methods-use-this
formatLanguage(language: string) {
if (language && language.toLowerCase().startsWith('en')) {
return 'en'
}
if (language && language.toLowerCase().startsWith('zh')) {
return 'zh'
}
return language
}
onEnterURL() {
if (
!(
Expand All @@ -508,7 +623,13 @@ export default class UploadForm extends Vue {
}
handleDeleteFile(index: number) {
this.fileRecords.splice(index, 1)
const deletedFile = this.fileRecords[index];
this.fileRecords.splice(index, 1);
const indexToDelete = this.epubMetadataList.findIndex(item => item.epubFileName === deletedFile.fileName);
if (indexToDelete !== -1) {
this.epubMetadataList.splice(indexToDelete, 1);
}
}
handleClickExifInfo(index: number) {
Expand Down Expand Up @@ -546,6 +667,10 @@ export default class UploadForm extends Vue {
}
if (arweaveId) {
this.sentArweaveTransactionHashes.set(ipfsHash, { transactionHash: '', arweaveId });
const metadata = this.epubMetadataList.find((data: any) => data.thumbnail?.url === ipfsHash)
if(metadata){
metadata.thumbnail.contentUrl = `https://arweave.net/${arweaveId}`
}
}
if (!this.arweaveFeeTargetAddress) {
this.arweaveFeeTargetAddress = address;
Expand Down Expand Up @@ -621,6 +746,10 @@ export default class UploadForm extends Vue {
if (arweaveId) {
const uploadedData = this.sentArweaveTransactionHashes.get(records.ipfsHash) || {};
this.sentArweaveTransactionHashes.set(records.ipfsHash, { ...uploadedData, arweaveId });
if (tempRecord.fileName === 'cover.jpeg') {
const metadata = this.epubMetadataList.find((file: any) => file.ipfsHash === records.thumbnail.url)
metadata.thumbnail.contentUrl = `https://arweave.net/${arweaveId}`
}
this.$emit('arweaveUploaded', { arweaveId })
this.isOpenSignDialog = false
} else {
Expand Down Expand Up @@ -675,7 +804,7 @@ export default class UploadForm extends Vue {
}
const uploadArweaveIdList = Array.from(this.sentArweaveTransactionHashes.values()).map(entry => entry.arweaveId);
this.$emit('submit', { fileRecords: this.fileRecords, arweaveIds: uploadArweaveIdList })
this.$emit('submit', { fileRecords: this.fileRecords, arweaveIds: uploadArweaveIdList, epubMetadata: this.epubMetadataList[0] })
}
handleSignDialogClose() {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"core-js": "^3.15.1",
"cosmjs-types": "^0.8.0",
"easyqrcodejs": "^4.4.6",
"epubjs": "^0.3.93",
"exifr": "^7.1.2",
"express": "^4.17.1",
"fast-json-stable-stringify": "^2.1.0",
Expand Down
7 changes: 7 additions & 0 deletions pages/new/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
:ipfs-hash="urlIpfsHash"
:arweave-id="urlArweaveId"
:upload-arweave-list=uploadArweaveList
:epub-metadata="epubMetadata"

:step="step"
@txBroadcasted="onISCNTxInfo"
Expand Down Expand Up @@ -135,6 +136,7 @@ export default class NewIndexPage extends Vue {
uploadFileRecords: any[] = []
urlFileRecords: any[] = []
epubMetadata: any | null = null
get shouldSkipToMintNFT(): boolean {
return this.$route.query.mint === '1'
Expand Down Expand Up @@ -190,16 +192,21 @@ export default class NewIndexPage extends Vue {
onSubmitUpload({
fileRecords,
arweaveIds,
epubMetadata,
}: {
fileRecords: any[] | []
arweaveIds: any[] | []
epubMetadata: any
}) {
if (fileRecords && fileRecords.length) {
this.uploadFileRecords = [...fileRecords]
}
if (arweaveIds && arweaveIds.length) {
this.uploadArweaveList = [...arweaveIds]
}
if (epubMetadata) {
this.epubMetadata = {...epubMetadata}
}
this.state = 'iscn'
logTrackerEvent(this, 'ISCNCreate', 'ISCNConfirmFile', '', 1)
}
Expand Down
2 changes: 2 additions & 0 deletions utils/cosmos/iscn/iscn.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export interface ISCNRegisterPayload {
stakeholders?: any[];
recordNotes?: string;
memo?: string;
inLanguage?: string;
thumbnail?: any;
}
export interface ISCNRecordWithID extends ISCNRecord {
id: string;
Expand Down
Loading

0 comments on commit 246e87f

Please sign in to comment.