Skip to content

Commit

Permalink
Feat: Add support for .mid file mints (#410)
Browse files Browse the repository at this point in the history
* Add mini support

* checkpoint

* Render same style as audio nfts in display feed

* Update UI

* Update function names, add disclaimer

* Update import order

* Use html-midi-player and add volume slider

* Uninstall old libs & deps

* Add some aliases as the global definition in vite config is causing some issues in the libs

* Creates the function to automatically generate midi cover based on track and notes

* Add padding on left and right

* Create feed list for midi nfts

* Fix auto generation code

* add start/stop event listeners to disable volume slider
  • Loading branch information
kittypurrry authored Jul 3, 2024
1 parent af60898 commit c4218c9
Show file tree
Hide file tree
Showing 15 changed files with 1,733 additions and 438 deletions.
1,387 changes: 1,086 additions & 301 deletions package-lock.json

Large diffs are not rendered by default.

273 changes: 140 additions & 133 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,137 +1,144 @@
{
"name": "teia-ui",
"version": "0.1.0",
"private": true,
"dependencies": {
"@taquito/beacon-wallet": "^17.4.0",
"@taquito/michelson-encoder": "^17.4.0",
"@taquito/taquito": "^17.4.0",
"axios": "^0.27.2",
"base-x": "^4.0.0",
"bs58check": "^2.1.2",
"canvas": "^2.11.2",
"classnames": "^2.3.2",
"compressorjs": "^1.1.1",
"fflate": "^0.7.4",
"framer-motion": "^9.0.1",
"graphql": "^16.4.0",
"graphql-request": "^4.2.0",
"json5": "^2.2.3",
"keyboardjs": "^2.7.0",
"markdown-to-jsx": "^7.1.9",
"mime-types": "^2.1.35",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.43.1",
"react-infinite-scroller": "^1.2.6",
"react-intersection-observer": "^9.4.2",
"react-lazy-load-image-component": "^1.5.6",
"react-masonry-css": "^1.0.16",
"react-router": "^6.8.1",
"react-router-dom": "^6.8.1",
"react-select": "^5.7.0",
"react-use": "^17.4.0",
"react-use-clipboard": "^1.0.9",
"screenfull": "^6.0.2",
"swr": "^1.3.0"
"name": "teia-ui",
"version": "0.1.0",
"private": true,
"dependencies": {
"@magenta/music": "^1.23.1",
"@taquito/beacon-wallet": "^17.4.0",
"@taquito/michelson-encoder": "^17.4.0",
"@taquito/taquito": "^17.4.0",
"@tonejs/midi": "^2.0.28",
"axios": "^0.27.2",
"base-x": "^4.0.0",
"bs58check": "^2.1.2",
"classnames": "^2.3.2",
"compressorjs": "^1.1.1",
"fflate": "^0.7.4",
"focus-visible": "^5.2.0",
"framer-motion": "^9.0.1",
"graphql": "^16.4.0",
"graphql-request": "^4.2.0",
"html-midi-player": "^1.5.0",
"json5": "^2.2.3",
"keyboardjs": "^2.7.0",
"markdown-to-jsx": "^7.1.9",
"mime-types": "^2.1.35",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.43.1",
"react-infinite-scroller": "^1.2.6",
"react-intersection-observer": "^9.4.2",
"react-lazy-load-image-component": "^1.5.6",
"react-masonry-css": "^1.0.16",
"react-router": "^6.8.1",
"react-router-dom": "^6.8.1",
"react-select": "^5.7.0",
"react-use": "^17.4.0",
"react-use-clipboard": "^1.0.9",
"screenfull": "^6.0.2",
"swr": "^1.3.0"
},
"scripts": {
"analyze": "source-map-explorer 'build/assets/*.js'",
"start": "vite",
"serve": "vite preview",
"build": "vite build",
"build-dev": "vite --mode development build",
"test": "vite test",
"screenshots": "playwright test",
"eject": "react-scripts eject",
"format": "prettier --write \"./src/**/*.{js,jsx,scss}\"",
"prepare": "husky install",
"lint": "eslint src --ext .js,.jsx",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
"eslintConfig": {
"extends": "react-app"
},
"lint-staged": {
"./src/**/*.{js,jsx,scss}": "prettier --write"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@airgap/beacon-types": "^3.3.3",
"@babel/preset-react": "^7.18.6",
"@google/model-viewer": "^3.0.1",
"@hookform/devtools": "^4.3.0",
"@storybook/addon-essentials": "^7.6.11",
"@storybook/addon-interactions": "^7.6.11",
"@storybook/addon-links": "^7.6.11",
"@storybook/blocks": "^7.6.11",
"@storybook/react": "^7.6.11",
"@storybook/react-vite": "^7.6.11",
"@storybook/testing-library": "^0.2.2",
"@testing-library/jest-dom": "^6.4.0",
"@testing-library/react": "^14.2.0",
"@testing-library/user-event": "^14.5.2",
"@vitejs/plugin-react": "^3.1.0",
"assert": "^2.0.0",
"buffer": "^6.0.3",
"cross-env": "^7.0.3",
"cssnano": "^5.1.14",
"eslint": "^8.34.0",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-react": "^7.32.2",
"fnv1a": "^1.1.1",
"fs-extra": "^11.1.0",
"husky": "^7.0.4",
"libsodium-wrappers": "^0.7.11",
"lodash": "^4.17.21",
"path-browserify": "^1.0.1",
"postcss": "^8.4.21",
"postcss-flexbugs-fixes": "^5.0.2",
"postcss-preset-env": "^7.8.3",
"prettier": "^2.8.4",
"process": "^0.11.10",
"prop-types": "^15.8.1",
"react-pdf": "^6.2.2",
"rollup-plugin-node-polyfills": "^0.2.1",
"rollup-plugin-polyfill-node": "^0.12.0",
"sass": "^1.58.1",
"source-map-explorer": "^2.5.3",
"storybook": "^7.6.11",
"stylelint": "^14.16.1",
"stylelint-config-standard-scss": "^6.1.0",
"twemoji": "^14.0.2",
"typescript": "^4.9.5",
"vite": "^4.1.1",
"vite-compatible-readable-stream": "^3.6.1",
"vite-plugin-ejs": "^1.6.4",
"vite-plugin-eslint": "^1.8.1",
"vite-plugin-filter-replace": "^0.1.10",
"vite-plugin-markdown": "^2.1.0",
"vite-plugin-node-polyfills": "^0.7.0",
"vite-plugin-node-stdlib-browser": "^0.1.1",
"vite-plugin-svgr": "^2.4.0",
"vite-tsconfig-paths": "^4.0.5",
"zustand": "^4.3.3"
},
"overrides": {
"vite-plugin-markdown": {
"vite": "$vite"
},
"scripts": {
"analyze": "source-map-explorer 'build/assets/*.js'",
"start": "vite",
"serve": "vite preview",
"build": "vite build",
"build-dev": "vite --mode development build",
"test": "vite test",
"screenshots": "playwright test",
"eject": "react-scripts eject",
"format": "prettier --write \"./src/**/*.{js,jsx,scss,css,ts,tsx}\"",
"prepare": "husky install",
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
"eslintConfig": {
"extends": "react-app"
},
"lint-staged": {
"./src/**/*.{js,jsx,scss,css,ts,tsx,json}": "prettier --write"
},
"browserslist": {
"production": [">0.2%", "not dead", "not op_mini all"],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@airgap/beacon-types": "^3.3.3",
"@babel/preset-react": "^7.18.6",
"@google/model-viewer": "^3.0.1",
"@hookform/devtools": "^4.3.0",
"@storybook/addon-essentials": "^7.6.11",
"@storybook/addon-interactions": "^7.6.11",
"@storybook/addon-links": "^7.6.11",
"@storybook/blocks": "^7.6.11",
"@storybook/react": "^7.6.11",
"@storybook/react-vite": "^7.6.11",
"@storybook/testing-library": "^0.2.2",
"@testing-library/jest-dom": "^6.4.0",
"@testing-library/react": "^14.2.0",
"@testing-library/user-event": "^14.5.2",
"@vitejs/plugin-react": "^3.1.0",
"assert": "^2.0.0",
"buffer": "^6.0.3",
"cross-env": "^7.0.3",
"cssnano": "^5.1.14",
"eslint": "^8.34.0",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-react": "^7.32.2",
"fnv1a": "^1.1.1",
"fs-extra": "^11.1.0",
"husky": "^7.0.4",
"libsodium-wrappers": "^0.7.11",
"lodash": "^4.17.21",
"path-browserify": "^1.0.1",
"postcss": "^8.4.21",
"postcss-flexbugs-fixes": "^5.0.2",
"postcss-preset-env": "^7.8.3",
"prettier": "^2.8.4",
"process": "^0.11.10",
"prop-types": "^15.8.1",
"react-pdf": "^6.2.2",
"rollup-plugin-node-polyfills": "^0.2.1",
"rollup-plugin-polyfill-node": "^0.12.0",
"sass": "^1.58.1",
"source-map-explorer": "^2.5.3",
"storybook": "^7.6.11",
"stylelint": "^14.16.1",
"stylelint-config-standard-scss": "^6.1.0",
"twemoji": "^14.0.2",
"typescript": "^4.9.5",
"vite": "^4.1.1",
"vite-compatible-readable-stream": "^3.6.1",
"vite-plugin-ejs": "^1.6.4",
"vite-plugin-eslint": "^1.8.1",
"vite-plugin-filter-replace": "^0.1.10",
"vite-plugin-markdown": "^2.1.0",
"vite-plugin-node-polyfills": "^0.7.0",
"vite-plugin-node-stdlib-browser": "^0.1.1",
"vite-plugin-svgr": "^2.4.0",
"vite-tsconfig-paths": "^4.0.5",
"zustand": "^4.3.3"
},
"overrides": {
"vite-plugin-markdown": {
"vite": "$vite"
},
"vite-plugin-node-stdlib-browser": {
"vite": "$vite"
}
},
"module": "commonjs",
"optionalDependencies": {
"@playwright/test": "^1.41.1"
"vite-plugin-node-stdlib-browser": {
"vite": "$vite"
}
},
"module": "commonjs",
"optionalDependencies": {
"@playwright/test": "^1.41.1"
}
}
23 changes: 20 additions & 3 deletions src/components/form/MintForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ import { useMintStore } from '@context/mintStore'
import { useFormContext, useFormState } from 'react-hook-form'
import { useModalStore } from '@context/modalStore'
import { processTypedInput } from '@utils/typed-art'
import { generateTypedArtCoverImage } from '@utils/mint'
import {
convertFileToFileForm,
generateMidiCover,
generateTypedArtCoverImage,
} from '@utils/mint'
import { AUTO_GENERATE_COVER_MIMETYPES } from '@constants'
import { Midi } from '@tonejs/midi'
import { processMidiCover } from '@utils/midi'

export default function MintForm() {
const {
Expand Down Expand Up @@ -45,7 +52,7 @@ export default function MintForm() {
if (artifact)
setNeedsCover(
!artifact?.mimeType?.startsWith('image') &&
artifact?.mimeType !== 'text/plain'
!AUTO_GENERATE_COVER_MIMETYPES.includes(artifact?.mimeType)
)

/** Typed */
Expand All @@ -68,6 +75,7 @@ export default function MintForm() {
setPreview(undefined)
}
}, [isTypedArt, typedinput, isMonoType])

Check warning on line 77 in src/components/form/MintForm.jsx

View workflow job for this annotation

GitHub Actions / build (18)

React Hook useEffect has a missing dependency: 'generateCoverImagePreview'. Either include it or remove the dependency array

const generateCoverImagePreview = async (inputText) => {
try {
const imageFile = await generateTypedArtCoverImage(inputText, isMonoType)
Expand All @@ -81,7 +89,10 @@ export default function MintForm() {
const onSubmit = async (data) => {
try {
// other non-typed nft mints that involves file upload
if (!data.typedinput && data.artifact) {
if (
!AUTO_GENERATE_COVER_MIMETYPES.includes(data.artifact?.mimeType) &&
data.artifact
) {
if (data.artifact.file?.size && data.artifact.file?.size / 1e6 > 2000) {
throw new Error(`File too big: ${data.artifact.file.size / 1e6}mb`)
}
Expand All @@ -90,6 +101,12 @@ export default function MintForm() {
data.artifact.reader = URL.createObjectURL(data.artifact.file)
} else if (data.typedinput) {
data = await processTypedInput(data)
} else if (
data.artifact.mimeType == 'audio/midi' ||

Check warning on line 105 in src/components/form/MintForm.jsx

View workflow job for this annotation

GitHub Actions / build (18)

Expected '===' and instead saw '=='
data.artifact.mimeType == 'audio/mid'

Check warning on line 106 in src/components/form/MintForm.jsx

View workflow job for this annotation

GitHub Actions / build (18)

Expected '===' and instead saw '=='
) {
// generate midi cover and set as data.object
data = await processMidiCover(data)
}

useMintStore.setState({ ...data, isValid: true })
Expand Down
1 change: 1 addition & 0 deletions src/components/header/feed_toolbar/FeedToolbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const locationMap = new Map([
['/feed/pdf', 'PDF'],
['/feed/md', 'Markdown'],
['/feed/txt', 'Text'],
['/feed/midi', 'Midi'],
])

const locationNeedSync = ['/feed/friends']
Expand Down
14 changes: 14 additions & 0 deletions src/components/media-types/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Container } from './container'
import { MD } from './md'
import { useMemo } from 'react'
import { NFT } from '@types'
import { MidiComponent } from './midi'
import { TXT } from './text'

interface RenderMediaTypeProps {
Expand All @@ -38,6 +39,7 @@ export const RenderMediaType = ({
displayView,
details,
}: RenderMediaTypeProps) => {

const parsedArtifactUri = useMemo(
() =>
nft.artifact_uri
Expand Down Expand Up @@ -185,6 +187,18 @@ export const RenderMediaType = ({
nft={nft}
/>
)
/** MIDI AUDIO FILES */
case MIMETYPE.MIDI:
case MIMETYPE.MID:
return (
<MidiComponent
artifactUri={parsedArtifactUri}
displayUri={parsedDisplayUri}
displayView={displayView}
previewUri={previewUri}
nft={nft}
/>
)

/** ASCII TYPED ART */
case MIMETYPE.TXT:
Expand Down
Loading

0 comments on commit c4218c9

Please sign in to comment.