From caf95a2eebde73c60002c0554d03e250168abebb Mon Sep 17 00:00:00 2001 From: florian <> Date: Wed, 17 Apr 2024 09:34:49 +0200 Subject: [PATCH] feat: Improved upload and image post editor --- README.md | 62 +++++---- bun.lockb | Bin 170659 -> 168407 bytes package-lock.json | 107 +++++++++++++--- package.json | 3 + src/components/BlobList/BlobList.css | 25 +--- src/components/BlobList/BlobList.tsx | 109 ++++++++++++---- .../FileEventEditor/FileEventEditor.tsx | 48 +++++-- src/components/Layout/Layout.css | 4 +- src/components/ProgressBar/ProgressBar.tsx | 6 +- src/pages/Upload.tsx | 121 ++++++++++-------- src/useEvents.ts | 40 ++++++ src/utils/useFileMetaEvents.ts | 42 ++++++ 12 files changed, 408 insertions(+), 159 deletions(-) create mode 100644 src/useEvents.ts create mode 100644 src/utils/useFileMetaEvents.ts diff --git a/README.md b/README.md index 0d6babe..f90c355 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,48 @@ -# React + TypeScript + Vite +# Bouquet -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +A tool to manage your content on blossom severs (Upload, Distribution, Posting) -Currently, two official plugins are available: -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh -## Expanding the ESLint configuration +## TODO / Ideas -If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: +Add Blurhash +https://github.com/verbiricha/filestr/blob/master/src/blur.tsx -- Configure the top-level `parserOptions` property like this: +Upload -```js -export default { - // other rules... - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - project: ['./tsconfig.json', './tsconfig.node.json'], - tsconfigRootDir: __dirname, - }, -} -``` + Audio + Audio Event 31337, maybe Podcast 31338 + Album Event 30029 + Read ID3 INfo + Display in Metadata Editor + Post Audio Events + Option to select "Full Album" and POst Album (Playlist) Event + Upload of Album Art from Disc + Usage of Album Art from ID3 + --> Album art as new blob + + + Video + FileMeta Data Event 1063 + Video Preview + + PDF + FileMeta Data Event 1063 + + Images + FileMeta Data Event 1063 + dimensions + blurhash + +Nav + Add AUdio Player like Soundcloud + +Blob List + - Selection -> Delete Selected + +Audio List + Audio List, mit Mini Thumnnail (Artitst / Title ) + Join von Album/year aus Album (Playlist) Event ???? + Display blob as "published" when in Audio Event, else as "unlisted" -- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` -- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` -- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list diff --git a/bun.lockb b/bun.lockb index df827a52fce7b0faa1f6f3a8bf3505bd7acf0a73..9dada2bd969056394ca781f50dd25e99b1157343 100755 GIT binary patch delta 29979 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∾PpRSjU6vfw)b?=k-8r;DtoYrR$7l zVIVf~nPDJWMu2!s#1`H-9Kjd9nyxk$8JuvoH~I16J8K5@}&*MVV1%8 zYR{V6b`)I-!VThf5!>Peqqs`yXUE%^#8H%m+ZaSEEg_1zS`gSoTrF{&Eeh^Oi8myx zJMauV=8(r58AMm5a{XsM=J?~;k^=yDn|WZ<~A|BXIt^2 zw4z-}A9l4vAFkr7ma^|mQShvt*iw{^#!_+LszvDk`9Hr0uh3DfY1s&m)LB!Gt4f<( zJE0V-zGzcHP^|b=&7=SK`&e^9K&)6nQc~9Lh?HvX__pFnYkDLMPg~{TX9U#IFj6un z^&i3UkIyOQ0QwOe>ZkHQ;WU~pl#-T2i&j#Xkb*W{#m=P)w)YTMcHkIgR(7uTD@|70 zdD0fKL9X!Tt$Lsg;WMlsw1m*7(RAoKRZv-B1Yz=fY3wv^ipJ5m09{5$P9v@TYw5%oP%!W@#L}P#B?cvo(%B-JxHIqJy6HpuA-P{V|$3 z8b@D0x1dNI^qDCI>Cv?g8aJ0X`lQ|(_!^)x=YgaaRshxm6s9LbNYdj@3jjJ6Q)WmT zU@Aa8U!rlg2+siMSPG8Htpv;@0tY=SLV3xex%r4C6VY$*5J@I2(6|*KD6>5<9s#n( zDlHvmj?k4d;Lsm7p)Uz`DUABy2}L^s$gb$%SG$8lglPS(1cY>q_(9oVN6!(dU&{)@evR`3*O3z8 zIG}Oi)FT`%Q5bKxOZ4D&`QpS}nk4klz$Sp6Hkb|2B%wJm7nldk2NnQd01JWP0L>42 z{GuJu9{2?40CWU80W?=!0XLv3;0|~IolAbfmT3kAO>g)&;vR2Y#2>R3xq9!(f~P^2#f+xzL^Km!#qs^BhUz- zhkovYzX#CzavLZj+a)0XuTX9Pw}9c$X*$yMqnVWt(BiWaSP0MxNGm9~KMdH_8E`jWCX;12`tNp0`A;;hgdz=8o@u& zq$j{r;4W|tCx^Bt``swSON4D zT3LV|)qM%P0$u}efVaR6;3lve*n|3oy$I|B_5;g-WxyDq5zrWD0vG}M=$@Vh+la!; z08fDXz+!;*+VMaRkP4&$eEc|en*vclGvEOVT>|`!@M+)}a2%Kbj0Vg=GC)gV3eX<-1fV6a6VL)^4rHT@+z|+j z1X6)CU=T0_=n3=!dINodQ9vFr2Nw7may>8=mP1TG-$ zMc@*kg>x0<3lQ@G+7mf28=$>#CqP@>0A%h5d<%XaZ~z>Ec!C)?2i^qGEaH;1KXNkk8v665TBiD#7P_ML+u; z2yO=ofWyG|z;`@ipV%SyID*H3qd>Tb3kM(=2m%6unt&Hj9jFF)0DOlait(>`71`a2)GH{0Dh%myp2Ew;5XnFK>7>dK5!5C9k>JB)xv*3 z`T-At2f!16O!y~2rh5dC`JMw5NBm>p8SqroUqQYEM7qCti@ zEnE(gb`siA$^*1jRs@X5LOmr5REDgig=w7awJ`0t4ggt$(m6uX&P#q#m98P&0S}-C zKxVE3_yFEOEr85TJZ>5Be2ATp*fJOi%HUPwvPO>G?251ko13m#d0Cbf~7pQRn zU8H)UOu9(w0mK8n0ct#j`vN^^{3()pu^Nf{LnZ;#Big)EfMkGn7TQI~5@@wz9SV~b zsJGP9AprG|;%S!|1`GwV0IHPC{=VtQLH{%tr!jzT`VY-cCLayt0hIQAljlI!P5v=+ ze_-mrSb7wdshdhS4^^a^M!nAZu*cMh@xaG=JQ@6Fz$9QIKx+eeKY2az(}1bK6kr87 z#5*e&bTdKB0RFm)*(?P81+V~^5AZ>UM2}pWUlg+jSOP2s76a5;vN3VJG^z8;p_3=l zqEa3B65(aQYG5T$6QEwvlv@F;0;n9ypAAr58-aCnsj3&M+nu~vFLV*Y`ao|$cs=lb zLn$4_Q=?Is(r9W7ahrjyz!u;u;KOpZgDVhQs`mm|jLHS~0Qk3zw5 zxf1{FJFzCW`CfE%3kvc9RUWS9Z0}_|x_XD>R$|Yf@POceu)3kV*Y~1RXfq`6K!U@^ ze<*ft*E0YK!U94A0@ce0C&cu-VBFftKm2A%%qYGAS=-Lh%6{U%Ij`MsSB6p9fdO>` zf+Dn^;S}`W_CriWKp+)Ln<5q3IrCn2+*|tth^ZS;k79Q6I)}v=@hs0dEINsWoF5iL z#5?>LG#3$lvqi32PAM)^PMw}Cp{9VafS_=p5`T*Xq1BMU8VTy{-{X3z%!@Hfg1S^} z9mG^ZOrNuEvGxhW{1AiQ2Lxf!;W0;0HW|?#3H&#$^=#i@q7ex~1A@_9A(M|jf)>r< zCn2iPAe2M8*nU54z9R3atQ1t2_d6<9b=ibC8F3>VBVU*&bnHjfla&L7?R@c3v~M30 z*dRgV*W>(uy+6nn3F-v|2M2^GpA=BnUR3(srP9}x8cAYMKu{b7Jh5l>dJu8Io zYCF<$7By2fzW#gS7yTNSsk7yrw-OUfRvN;mBCCu3^Y8u}$5?wt?sumIp~xF7Oyc{F ziy`I@9nDVU7TCh5DcUd4&$xB|7pEBqXWP7s`Os`7G0NxU$Sa*2oW~mn)2Ich4wTM& zoPZq$@L?w~HX;1b37F#ne@?=Z`~QGA6L0YYw4QtfiC%mYNEiK=)03W$%(F1&w?K&) zAM%iP{8vgB&mB(U3Va?vaZ)V8mz@PaqI_p=c?!adcQ_@6xadDgf9P0o{-|E92bZ*J zFJF2JHCN#~Nz~wHkjq8?LHPcs>wJA zS;8jwJ*^ZU1QQEO_@2`kKm8ZzSA8S)U08bkCapk>lJaZ(u-7M(&Tg#QrBzwPU>?%= z_2AY&q5Jx;-M>x|HxH^7bx}z`{s%8_j0AA3ZXZu~5Ur#6;l!s?f*SBH2dL`@27Q%s zukRuh6r$QuD`*(MLg@-I>1awsuM225bZd?W(rF`D%x!;$G4-Ft-+B7CKC3gnnxG_5 znjFJ>{frj<%CnIU&uwh@8AA}uUy`Bd+ErJpAj8h^q)cBu)EjYoMwwx z(7d7vi7Q@y>WVT}fBb@W>c4?M{+s)wBg>rsrrzQ<%0Mc99M1=w6P;Z3-_m!fR%&tkC3SDAcEwy3&bsm?=R`;8 zsw@BIoER((aO3w#AMVDj&OGQM=@%g>Ab#O1u=MLag+ zaY3|jdFi2ij-9u>_7v-~P5QP*z1jq;!;Ke2r+R-K5qN~MMt^kmRxH!nlTW)KI$~n2 zx*&!~-97nbs4n`C<Qsj_~AJ7t!epo_sxY zJh*e{BIazZYHBYGIo4HvO)qGxlpGWgid~!gUlK!H_aXsqZStz0{cPXTF)%%DwVmmBf0V%%@CMsVSE#ckQ&$EH!g{-rR_Bef-j4%BA%;hd*$C2 z4X0jo$>VM6A0Tk`Rh4N3r{MYQJkr_H&6RTbPUyBM_?ULw@KmS zsP^?#B%w8TytV?{Zc2t?>}LE%d)`8hXss+I%Ha zy679vUsG~^=c?!_HTLHfuE7V|`E&1UVrv)u4FsKf|Ni#HjQA&LDV9cB1j_K~*TiO6 zgU(zNBVF}Z9c(hMJ9E79w^fvMf#e(s0lao0yeNq`D-=UQ^>-yS?EhoJ$O*|cC?PEd zLBijx!*CyU`E=2L^S;whztp&ek3e#_3ZN-|~*Sj#&V?mE_@I{@Zmi&u%3~ zi7s|#*6BL6W`4s6JCTKaeoyj{wuEpSQOd)UUv4+xvdvMt3)1bht5T`Q^m$_}L~J|C zY>2PRQ*MZkuKH^g+RwjtuhEiIZ%R^pQI{`4ihBBs7`Ay?^a#8?u5w8V{Z$R&_eZp? zU^C%VNzAjl{2ubU=r4Ept+AKY5ML-}VnVS?NB`M1zrwD&yZ`JGvoermwh?l79RgNXbAiiYQw`wecczfIv2 z!;gNhZnmo|#K3@H{NWCm8bj*gcnno-I3th`Q_ zq`2IG+uXwB*552~YN?IeLGPlrB`NfGPxw~y4iP8+y0j$5jrX{PPU$bJ=u_pDT+!X` zNl60zbr!egWIkMKe6q77Caxi0k7`}@7htf+->WB2ojwR}#xAxrO1%&XGA{QTIo8%0 z<4Ai2CeGR@egi38^>-d*xtf10oY?cBGCh=K_1h@kx(H<+j^aK4gghI?^GMfxgl{bp zou$Gk{sYKR{T&T1YjUq{yp=DY80>Deis)~3X#4y?{w|9?^GjmNbC+Vck~0r27GqrX z*G(+2FDP~%w`%~>VZ9_*TG@;*Du#1zYQ|3&qjP(kagRGNl>X+86;HAfI#l@18adE# z>fA@K2$j~%YR=Q{U_rgqT)j2?`!a5|;JZ+Zi~fF&z0O{xclPRi4Yknvh;`44|8Yn3 zt4H5$IAa;mU-&W3rh7`tr{Wh%b8t@>B9|0IbCEqS}&MMqiByO$6C z9i~t(pR&VGQt(|qJiv8(vC@CBrgDEye^S#Iy`jM41RNa3*X{BCIKYKAEX@8g5 zxb%wzLl>=?-1eU6WF7{Uww8pr1N#?MTw*DSeZbH~?nhSNaP=Z?9#YU9W>DD&cYK@M zSxDkIFm_<{myWclv;Rw{qX+EJ)Ou>3BtHGFvQ$&8uKEk6x{6<1YW{RFZq|@a8Iidr z{>xq1S%00$?+INyU1_j43MnFR(TYy14VN~y=9?dj_7)i59=zE-Tn~rx?0dLu(O+Ov zwkX!kxMa!;O=R4#h+m(&LRMJCw~^3Pu~?iz)3iigz|*0tqy(&Kh~6!J=M+wr-7h{4z#j{SkQ z#qhU(D9-J4A6Gs3QM}E4v7gkbBmeq7=B56ok`A(VlSE@;Z>?=$hO)AH4`Zgw=MwQaNkzxx2UANrd} zCMV3^vg_iJt4ePa2P?}XA7bag>d^TirX1FQ&qyANgfc#h zVwP=Pg#u`ckH9y9U3sHNNQn}rA*EP>uX+RnU=g_ty52{-rQB=lZ#zkt@^xqPS|JC0oB{*v=*h1kMLqpZ991mi z+}gN}JtB$W0iiI3An32iXxL^@w%fS<4UiY6Lm%qi>&XKi!yn7WsS{~W?FAPjJ2|#e zx)>Y~j&*~_KNe#&e{79M*k3<}cj+(R&|lSn^kJ(1HtofOpNRcj_4k%I9iAy)8Mk>I zQqV;st~L^T@voksXE54rl0$lNLusiFUEqxB#oIjvHK`Z>lqB!Px0Bq}i~s%f4qU7#ZD(uD6kWlK| zn@@a(qEmbGU8Ili&Cf!wH>0;|iL4!u@zbBt)NZ=DsfW*15mOeGZ#$AZt4aU$UWlQ~ z1dIUk8lJ0Vc6p96*C+5P&|PXKs@GPX+aGHaZ}Zjn$U*A>IvT|HJcm_l_Tv>^AY(y4 z?)?IHS^j+b3pixYB);|q$~m9Jf1zmD^w|s1x2)N$F1~Ngy!K1*NY}eW2II+pTsPX4 zQ8u(!$$aBWOuoMv2edkW0DncfPY&Q!Ucrg)r}BhXnA2XIzY-Tnr_*@d*D%Q6+gyLu zOWO^nhTT2q6pHTAXrSoaf&7ctFo6E@m*1cDxzek$Rb8aeX1+5&`5HY%&x&7Thk7xDQ^kI$`h8NgZ>hirWM29k1szL;9GPwS|5kHs~j`}N# z3=`Xb`Mg)kNR&-eIfQ$ZmYggw9*U>;F0EPm?Gw?yn(ChFyPfcr=O^DCIiI*P89DJu zF-=@;R^RzhoQmME?T9cj=b|*OyR#4Uv8*cy#8*Z zJCX76M}phPD1)v6>eUOcJ(Pd@7OO+VP<|d|=oiASA9lhA+P>ErpBkQ9{8f$%IuO9`Wu_v zoEI0Z+v!oYBxY|GABnuK`a7Od+te#RCL;znGFpG>89C3bp93R9fS9_PyK3OX2F32=4wF`OSJj?xc{klB&Hc;|nDm6Yco1V-zn&@zsLxbtUnaI*nK!yUxR@ z0d#7{XopS}-rCjurDZejTV66af7rb3^sFM4IiHUyFLf@sSzcQ0SWv#EbXh8>>LaDM z;;X%+Mg@m5r0(Tx)ys`K{&m!Ve+2i;lB)Bf45@~QkCiBVKU1>c#!Shs6daAmSCTw= z)uED&1#KFtI(3v(hGz|x%Ja0Lk^^5lS*pPmuF){bz7%$2zAsFw#+^q<{(MFfibSXa z?>R!U=3kDG?D?!DlxaN@gcvSsn>%_tvph)$2VWL@yPXjuvFPnnTG|=d6HGd Lf}Yc*Z0Y|1;Or}X diff --git a/package-lock.json b/package-lock.json index 87f7c43..7537715 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,9 @@ "blossom-client-sdk": "^0.4.0", "dayjs": "^1.11.10", "id3js": "^2.1.1", + "lodash": "^4.17.21", "nostr-tools": "^2.4.0", + "p-limit": "^5.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-pdf": "^7.7.1", @@ -28,6 +30,7 @@ }, "devDependencies": { "@tanstack/eslint-plugin-query": "^5.28.6", + "@types/lodash": "^4.17.0", "@types/react": "^18.2.74", "@types/react-dom": "^18.2.24", "@typescript-eslint/eslint-plugin": "^7.2.0", @@ -1667,6 +1670,12 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", + "dev": true + }, "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", @@ -3787,6 +3796,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4246,6 +4260,35 @@ } }, "node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", @@ -4260,14 +4303,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/p-locate/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, "engines": { "node": ">=10" }, @@ -5847,12 +5887,11 @@ } }, "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6809,6 +6848,12 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "@types/lodash": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", + "dev": true + }, "@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", @@ -8340,6 +8385,11 @@ "p-locate": "^5.0.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -8649,12 +8699,11 @@ } }, "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", "requires": { - "yocto-queue": "^0.1.0" + "yocto-queue": "^1.0.0" } }, "p-locate": { @@ -8664,6 +8713,23 @@ "dev": true, "requires": { "p-limit": "^3.0.2" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } } }, "parent-module": { @@ -9711,10 +9777,9 @@ "dev": true }, "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==" } } } diff --git a/package.json b/package.json index 608c397..d0588e2 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,9 @@ "blossom-client-sdk": "^0.4.0", "dayjs": "^1.11.10", "id3js": "^2.1.1", + "lodash": "^4.17.21", "nostr-tools": "^2.4.0", + "p-limit": "^5.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-pdf": "^7.7.1", @@ -32,6 +34,7 @@ }, "devDependencies": { "@tanstack/eslint-plugin-query": "^5.28.6", + "@types/lodash": "^4.17.0", "@types/react": "^18.2.74", "@types/react-dom": "^18.2.24", "@typescript-eslint/eslint-plugin": "^7.2.0", diff --git a/src/components/BlobList/BlobList.css b/src/components/BlobList/BlobList.css index 68fb1b4..e6a5604 100644 --- a/src/components/BlobList/BlobList.css +++ b/src/components/BlobList/BlobList.css @@ -3,16 +3,7 @@ } .blob-list { - @apply bg-base-200 p-4 text-neutral-content rounded-lg; -} - -.blob-list .blob { - @apply p-1 hover:bg-base-200 rounded-md grid pr-4; - grid-template-columns: 2em auto /*auto*/ 2em 6em 10em 7em 3em; -} - -.blob-list .blob span { - @apply overflow-ellipsis overflow-hidden text-nowrap; + @apply p-4 text-neutral-content rounded-lg; } .blog-list-header { @@ -23,18 +14,10 @@ @apply flex-grow; } -.blog-list-header button { - @apply btn p-2 ml-2 my-2 text-neutral-content rounded-lg; -} - -.blog-list-header button.selected { - @apply btn-primary text-primary-content; -} - .blog-list-header svg { @apply w-6 opacity-80 hover:opacity-100; } -.blob-list .blob span a.pill { - @apply bg-base-200 p-1 px-2 rounded-2xl text-white; -} \ No newline at end of file +.blob-list .table :where(th, td) { + padding: .25em; +} diff --git a/src/components/BlobList/BlobList.tsx b/src/components/BlobList/BlobList.tsx index 1c775e6..9f67b6e 100644 --- a/src/components/BlobList/BlobList.tsx +++ b/src/components/BlobList/BlobList.tsx @@ -17,6 +17,10 @@ import * as id3 from 'id3js'; import { ID3Tag, ID3TagV2 } from 'id3js/lib/id3Tag'; import { useQueries } from '@tanstack/react-query'; import { useServerInfo } from '../../utils/useServerInfo'; +import useFileMetaEventsByHash, { KIND_BLOSSOM_DRIVE, KIND_FILE_META } from '../../utils/useFileMetaEvents'; +import { nip19 } from 'nostr-tools'; +import { AddressPointer, EventPointer } from 'nostr-tools/nip19'; +import { NDKEvent } from '@nostr-dev-kit/ndk'; type ListMode = 'gallery' | 'list' | 'audio' | 'video' | 'docs'; @@ -31,6 +35,7 @@ type AudioBlob = BlobDescriptor & { id3?: ID3Tag; imageData?: string }; const BlobList = ({ blobs, onDelete, title }: BlobListProps) => { const [mode, setMode] = useState('list'); const { distribution } = useServerInfo(); + const fileMetaEventsByHash = useFileMetaEventsByHash(); const images = useMemo( () => blobs.filter(b => b.type?.startsWith('image/')).sort((a, b) => (a.created > b.created ? -1 : 1)), // descending @@ -121,6 +126,46 @@ const BlobList = ({ blobs, onDelete, title }: BlobListProps) => { ); + + const Badge = ({ ev }: { ev: NDKEvent }) => { + if (ev.kind == KIND_FILE_META) { + const nevent = nip19.neventEncode({ + kind: ev.kind, + id: ev.id, + author: ev.author.pubkey, + relays: ev.onRelays.map(r => r.url), + } as EventPointer); + return ( + +
published
+
+ ); + } + + if (ev.kind == KIND_BLOSSOM_DRIVE) { + const naddr = nip19.naddrEncode({ + kind: ev.kind, + identifier: ev.tagValue('d'), + pubkey: ev.author.pubkey, + relays: ev.onRelays.map(r => r.url), + } as AddressPointer); + return ( + + 🌸 drive + + ); + } + + return <>; + } + + const Badges = ({ blob }: { blob: BlobDescriptor }) => { + const events = fileMetaEventsByHash[blob.sha256]; + if (!events) return; + + return events.map(ev => ) + }; + return ( <>
@@ -293,34 +338,42 @@ const BlobList = ({ blobs, onDelete, title }: BlobListProps) => { {mode == 'list' && (
- {blobs.map((blob: BlobDescriptor) => ( -
- - - - - - {blob.sha256} - - - {/* - - 🌸 drive 📝 post - - */} - - {distribution[blob.sha256].servers.length == 1 ? ( - - ) : ( - '' - )} - - {formatFileSize(blob.size)} - {blob.type && `${blob.type}`} - {formatDate(blob.created)} - -
- ))} + + + + + + + + + + + + + {blobs.map((blob: BlobDescriptor) => ( + + + + + + + + + ))} + +
HashUsesSizeTypeDateActions
+ + + {blob.sha256.slice(0, 15)} + + + + + {distribution[blob.sha256].servers.length == 1 && } + + {formatFileSize(blob.size)}{blob.type && `${blob.type}`}{formatDate(blob.created)} + +
)} diff --git a/src/components/FileEventEditor/FileEventEditor.tsx b/src/components/FileEventEditor/FileEventEditor.tsx index deba828..8c0bdcb 100644 --- a/src/components/FileEventEditor/FileEventEditor.tsx +++ b/src/components/FileEventEditor/FileEventEditor.tsx @@ -2,14 +2,16 @@ import { NDKEvent, NostrEvent } from '@nostr-dev-kit/ndk'; import { useNDK } from '../../ndk'; import dayjs from 'dayjs'; import { useState } from 'react'; +import uniq from 'lodash/uniq'; +import { formatFileSize } from '../../utils'; export type FileEventData = { content: string; - url: string; + url: string[]; dim?: string; x: string; m?: string; - size?: string; + size: number; //summary: string; //alt: string; }; @@ -23,8 +25,8 @@ const FileEventEditor = ({ data }: { data: FileEventData }) => { created_at: dayjs().unix(), content: data.content, tags: [ + ...uniq(data.url).map(du => ['url', du]), ['x', data.x], - ['url', data.url], //['summary', data.summary], //['alt', data.alt], ], @@ -33,7 +35,7 @@ const FileEventEditor = ({ data }: { data: FileEventData }) => { }; if (data.size) { - e.tags.push(['size', data.size]); + e.tags.push(['size', `${data.size}`]); } if (data.dim) { e.tags.push(['dim', data.dim]); @@ -45,21 +47,45 @@ const FileEventEditor = ({ data }: { data: FileEventData }) => { const ev = new NDKEvent(ndk, e); await ev.sign(); console.log(ev.rawEvent()); - await ev.publish(); + // await ev.publish(); }; return ( -
-
{JSON.stringify(fileEventData, null, 2)}
- - {fileEventData.dim ? `(${fileEventData.dim})` : ''} -
+
+ {fileEventData.m?.startsWith('image/') && ( +
+ +
+ )} +
+ Type + {fileEventData.m} + + {fileEventData.dim && ( + <> + Dimensions + {fileEventData.dim} + + )} + + File size + {fileEventData.size ? formatFileSize(fileEventData.size) : 'unknown'} + Content / Description + URL +