From 254022d81df714ae1ffe45b20578bb28d990f3d8 Mon Sep 17 00:00:00 2001 From: 429Enjoyer Date: Wed, 20 May 2026 05:56:16 +0700 Subject: [PATCH] .clean up the code --- .github/FUNDING.yml | 2 - .github/ISSUE_TEMPLATE/bug_report.yml | 77 - .github/ISSUE_TEMPLATE/config.yml | 1 - .github/ISSUE_TEMPLATE/feature_request.yml | 36 - .github/workflows/build.yml | 421 -- .gitignore | 64 - LICENSE | 21 - README.md | 115 - app.go | 2420 --------- backend/amazon.go | 537 -- backend/analysis.go | 214 - backend/artist_format.go | 90 - backend/config.go | 249 - backend/cover.go | 595 --- backend/download_validation.go | 44 - backend/ffmpeg.go | 947 ---- backend/ffmpeg_unix.go | 12 - backend/ffmpeg_windows.go | 15 - backend/file_dialog.go | 53 - backend/fileicon_darwin.go | 45 - backend/fileicon_stub.go | 7 - backend/filemanager.go | 503 -- backend/filename.go | 239 - backend/folder.go | 115 - backend/history.go | 323 -- backend/http_headers.go | 20 - backend/isrc_cache.go | 137 - backend/isrc_finder.go | 464 -- backend/isrc_helper.go | 22 - backend/link_resolver.go | 154 - backend/lyrics.go | 540 -- backend/metadata.go | 1255 ----- backend/musicbrainz.go | 331 -- backend/progress.go | 419 -- backend/provider_endpoints.go | 88 - backend/provider_priority.go | 215 - backend/qobuz.go | 1127 ---- backend/qobuz_api.go | 407 -- backend/qobuz_providers.go | 106 - backend/recent_fetches.go | 91 - backend/resample.go | 223 - backend/songlink.go | 505 -- backend/songstats.go | 128 - backend/soundplate.go | 95 - backend/spotfetch.go | 1753 ------- backend/spotify_metadata.go | 1774 ------- backend/spotify_totp.go | 28 - backend/tidal.go | 956 ---- backend/upc_tags.go | 50 - frontend/.gitignore | 24 - frontend/components.json | 24 - frontend/eslint.config.js | 22 - frontend/index.html | 21 - frontend/package.json | 59 - frontend/package.json.md5 | 1 - frontend/pnpm-lock.yaml | 4519 ----------------- frontend/public/assets/flags/ad.svg | 150 - frontend/public/assets/flags/ae.svg | 6 - frontend/public/assets/flags/af.svg | 81 - frontend/public/assets/flags/ag.svg | 14 - frontend/public/assets/flags/ai.svg | 29 - frontend/public/assets/flags/al.svg | 5 - frontend/public/assets/flags/am.svg | 5 - frontend/public/assets/flags/ao.svg | 13 - frontend/public/assets/flags/aq.svg | 5 - frontend/public/assets/flags/ar.svg | 32 - frontend/public/assets/flags/arab.svg | 109 - frontend/public/assets/flags/as.svg | 72 - frontend/public/assets/flags/asean.svg | 13 - frontend/public/assets/flags/at.svg | 4 - frontend/public/assets/flags/au.svg | 8 - frontend/public/assets/flags/aw.svg | 186 - frontend/public/assets/flags/ax.svg | 18 - frontend/public/assets/flags/az.svg | 8 - frontend/public/assets/flags/ba.svg | 12 - frontend/public/assets/flags/bb.svg | 6 - frontend/public/assets/flags/bd.svg | 4 - frontend/public/assets/flags/be.svg | 7 - frontend/public/assets/flags/bf.svg | 7 - frontend/public/assets/flags/bg.svg | 5 - frontend/public/assets/flags/bh.svg | 4 - frontend/public/assets/flags/bi.svg | 15 - frontend/public/assets/flags/bj.svg | 14 - frontend/public/assets/flags/bl.svg | 5 - frontend/public/assets/flags/bm.svg | 97 - frontend/public/assets/flags/bn.svg | 36 - frontend/public/assets/flags/bo.svg | 673 --- frontend/public/assets/flags/bq.svg | 5 - frontend/public/assets/flags/br.svg | 45 - frontend/public/assets/flags/bs.svg | 13 - frontend/public/assets/flags/bt.svg | 89 - frontend/public/assets/flags/bv.svg | 13 - frontend/public/assets/flags/bw.svg | 7 - frontend/public/assets/flags/by.svg | 18 - frontend/public/assets/flags/bz.svg | 145 - frontend/public/assets/flags/ca.svg | 4 - frontend/public/assets/flags/cc.svg | 19 - frontend/public/assets/flags/cd.svg | 5 - frontend/public/assets/flags/cefta.svg | 13 - frontend/public/assets/flags/cf.svg | 15 - frontend/public/assets/flags/cg.svg | 12 - frontend/public/assets/flags/ch.svg | 9 - frontend/public/assets/flags/ci.svg | 7 - frontend/public/assets/flags/ck.svg | 9 - frontend/public/assets/flags/cl.svg | 13 - frontend/public/assets/flags/cm.svg | 15 - frontend/public/assets/flags/cn.svg | 11 - frontend/public/assets/flags/co.svg | 7 - frontend/public/assets/flags/cp.svg | 7 - frontend/public/assets/flags/cr.svg | 7 - frontend/public/assets/flags/cu.svg | 13 - frontend/public/assets/flags/cv.svg | 13 - frontend/public/assets/flags/cw.svg | 14 - frontend/public/assets/flags/cx.svg | 15 - frontend/public/assets/flags/cy.svg | 6 - frontend/public/assets/flags/cz.svg | 5 - frontend/public/assets/flags/de.svg | 5 - frontend/public/assets/flags/dg.svg | 130 - frontend/public/assets/flags/dj.svg | 13 - frontend/public/assets/flags/dk.svg | 5 - frontend/public/assets/flags/dm.svg | 152 - frontend/public/assets/flags/do.svg | 121 - frontend/public/assets/flags/dz.svg | 5 - frontend/public/assets/flags/eac.svg | 48 - frontend/public/assets/flags/ec.svg | 138 - frontend/public/assets/flags/ee.svg | 5 - frontend/public/assets/flags/eg.svg | 38 - frontend/public/assets/flags/eh.svg | 16 - frontend/public/assets/flags/er.svg | 8 - frontend/public/assets/flags/es-ct.svg | 4 - frontend/public/assets/flags/es-ga.svg | 187 - frontend/public/assets/flags/es-pv.svg | 5 - frontend/public/assets/flags/es.svg | 544 -- frontend/public/assets/flags/et.svg | 14 - frontend/public/assets/flags/eu.svg | 28 - frontend/public/assets/flags/fi.svg | 5 - frontend/public/assets/flags/fj.svg | 120 - frontend/public/assets/flags/fk.svg | 90 - frontend/public/assets/flags/fm.svg | 11 - frontend/public/assets/flags/fo.svg | 12 - frontend/public/assets/flags/fr.svg | 5 - frontend/public/assets/flags/ga.svg | 7 - frontend/public/assets/flags/gb-eng.svg | 5 - frontend/public/assets/flags/gb-nir.svg | 132 - frontend/public/assets/flags/gb-sct.svg | 4 - frontend/public/assets/flags/gb-wls.svg | 9 - frontend/public/assets/flags/gb.svg | 7 - frontend/public/assets/flags/gd.svg | 27 - frontend/public/assets/flags/ge.svg | 6 - frontend/public/assets/flags/gf.svg | 5 - frontend/public/assets/flags/gg.svg | 9 - frontend/public/assets/flags/gh.svg | 6 - frontend/public/assets/flags/gi.svg | 32 - frontend/public/assets/flags/gl.svg | 4 - frontend/public/assets/flags/gm.svg | 14 - frontend/public/assets/flags/gn.svg | 7 - frontend/public/assets/flags/gp.svg | 5 - frontend/public/assets/flags/gq.svg | 23 - frontend/public/assets/flags/gr.svg | 16 - frontend/public/assets/flags/gs.svg | 133 - frontend/public/assets/flags/gt.svg | 204 - frontend/public/assets/flags/gu.svg | 19 - frontend/public/assets/flags/gw.svg | 13 - frontend/public/assets/flags/gy.svg | 9 - frontend/public/assets/flags/hk.svg | 8 - frontend/public/assets/flags/hm.svg | 8 - frontend/public/assets/flags/hn.svg | 18 - frontend/public/assets/flags/hr.svg | 58 - frontend/public/assets/flags/ht.svg | 116 - frontend/public/assets/flags/hu.svg | 7 - frontend/public/assets/flags/ic.svg | 7 - frontend/public/assets/flags/id.svg | 4 - frontend/public/assets/flags/ie.svg | 7 - frontend/public/assets/flags/il.svg | 14 - frontend/public/assets/flags/im.svg | 36 - frontend/public/assets/flags/in.svg | 25 - frontend/public/assets/flags/io.svg | 130 - frontend/public/assets/flags/iq.svg | 10 - frontend/public/assets/flags/ir.svg | 219 - frontend/public/assets/flags/is.svg | 12 - frontend/public/assets/flags/it.svg | 7 - frontend/public/assets/flags/je.svg | 62 - frontend/public/assets/flags/jm.svg | 8 - frontend/public/assets/flags/jo.svg | 16 - frontend/public/assets/flags/jp.svg | 11 - frontend/public/assets/flags/ke.svg | 23 - frontend/public/assets/flags/kg.svg | 4 - frontend/public/assets/flags/kh.svg | 61 - frontend/public/assets/flags/ki.svg | 36 - frontend/public/assets/flags/km.svg | 16 - frontend/public/assets/flags/kn.svg | 14 - frontend/public/assets/flags/kp.svg | 15 - frontend/public/assets/flags/kr.svg | 24 - frontend/public/assets/flags/kw.svg | 13 - frontend/public/assets/flags/ky.svg | 103 - frontend/public/assets/flags/kz.svg | 36 - frontend/public/assets/flags/la.svg | 12 - frontend/public/assets/flags/lb.svg | 15 - frontend/public/assets/flags/lc.svg | 8 - frontend/public/assets/flags/li.svg | 43 - frontend/public/assets/flags/lk.svg | 22 - frontend/public/assets/flags/lr.svg | 14 - frontend/public/assets/flags/ls.svg | 8 - frontend/public/assets/flags/lt.svg | 7 - frontend/public/assets/flags/lu.svg | 5 - frontend/public/assets/flags/lv.svg | 7 - frontend/public/assets/flags/ly.svg | 13 - frontend/public/assets/flags/ma.svg | 4 - frontend/public/assets/flags/mc.svg | 6 - frontend/public/assets/flags/md.svg | 70 - frontend/public/assets/flags/me.svg | 116 - frontend/public/assets/flags/mf.svg | 5 - frontend/public/assets/flags/mg.svg | 7 - frontend/public/assets/flags/mh.svg | 7 - frontend/public/assets/flags/mk.svg | 5 - frontend/public/assets/flags/ml.svg | 7 - frontend/public/assets/flags/mm.svg | 12 - frontend/public/assets/flags/mn.svg | 14 - frontend/public/assets/flags/mo.svg | 9 - frontend/public/assets/flags/mp.svg | 86 - frontend/public/assets/flags/mq.svg | 5 - frontend/public/assets/flags/mr.svg | 6 - frontend/public/assets/flags/ms.svg | 29 - frontend/public/assets/flags/mt.svg | 58 - frontend/public/assets/flags/mu.svg | 8 - frontend/public/assets/flags/mv.svg | 6 - frontend/public/assets/flags/mw.svg | 10 - frontend/public/assets/flags/mx.svg | 382 -- frontend/public/assets/flags/my.svg | 26 - frontend/public/assets/flags/mz.svg | 21 - frontend/public/assets/flags/na.svg | 16 - frontend/public/assets/flags/nc.svg | 13 - frontend/public/assets/flags/ne.svg | 6 - frontend/public/assets/flags/nf.svg | 9 - frontend/public/assets/flags/ng.svg | 6 - frontend/public/assets/flags/ni.svg | 129 - frontend/public/assets/flags/nl.svg | 5 - frontend/public/assets/flags/no.svg | 7 - frontend/public/assets/flags/np.svg | 13 - frontend/public/assets/flags/nr.svg | 12 - frontend/public/assets/flags/nu.svg | 10 - frontend/public/assets/flags/nz.svg | 36 - frontend/public/assets/flags/om.svg | 115 - frontend/public/assets/flags/pa.svg | 7 - frontend/public/assets/flags/pc.svg | 33 - frontend/public/assets/flags/pe.svg | 4 - frontend/public/assets/flags/pf.svg | 19 - frontend/public/assets/flags/pg.svg | 9 - frontend/public/assets/flags/ph.svg | 6 - frontend/public/assets/flags/pk.svg | 15 - frontend/public/assets/flags/pl.svg | 6 - frontend/public/assets/flags/pm.svg | 5 - frontend/public/assets/flags/pn.svg | 53 - frontend/public/assets/flags/pr.svg | 13 - frontend/public/assets/flags/ps.svg | 6 - frontend/public/assets/flags/pt.svg | 57 - frontend/public/assets/flags/pw.svg | 11 - frontend/public/assets/flags/py.svg | 157 - frontend/public/assets/flags/qa.svg | 4 - frontend/public/assets/flags/re.svg | 5 - frontend/public/assets/flags/ro.svg | 7 - frontend/public/assets/flags/rs.svg | 292 -- frontend/public/assets/flags/ru.svg | 5 - frontend/public/assets/flags/rw.svg | 13 - frontend/public/assets/flags/sa.svg | 25 - frontend/public/assets/flags/sb.svg | 13 - frontend/public/assets/flags/sc.svg | 7 - frontend/public/assets/flags/sd.svg | 13 - frontend/public/assets/flags/se.svg | 4 - frontend/public/assets/flags/sg.svg | 13 - frontend/public/assets/flags/sh-ac.svg | 689 --- frontend/public/assets/flags/sh-hl.svg | 164 - frontend/public/assets/flags/sh-ta.svg | 76 - frontend/public/assets/flags/sh.svg | 7 - frontend/public/assets/flags/si.svg | 18 - frontend/public/assets/flags/sj.svg | 7 - frontend/public/assets/flags/sk.svg | 9 - frontend/public/assets/flags/sl.svg | 7 - frontend/public/assets/flags/sm.svg | 75 - frontend/public/assets/flags/sn.svg | 8 - frontend/public/assets/flags/so.svg | 11 - frontend/public/assets/flags/sr.svg | 6 - frontend/public/assets/flags/ss.svg | 8 - frontend/public/assets/flags/st.svg | 16 - frontend/public/assets/flags/sv.svg | 593 --- frontend/public/assets/flags/sx.svg | 56 - frontend/public/assets/flags/sy.svg | 6 - frontend/public/assets/flags/sz.svg | 34 - frontend/public/assets/flags/tc.svg | 50 - frontend/public/assets/flags/td.svg | 7 - frontend/public/assets/flags/tf.svg | 15 - frontend/public/assets/flags/tg.svg | 14 - frontend/public/assets/flags/th.svg | 7 - frontend/public/assets/flags/tj.svg | 22 - frontend/public/assets/flags/tk.svg | 5 - frontend/public/assets/flags/tl.svg | 13 - frontend/public/assets/flags/tm.svg | 204 - frontend/public/assets/flags/tn.svg | 4 - frontend/public/assets/flags/to.svg | 10 - frontend/public/assets/flags/tr.svg | 8 - frontend/public/assets/flags/tt.svg | 5 - frontend/public/assets/flags/tv.svg | 9 - frontend/public/assets/flags/tw.svg | 34 - frontend/public/assets/flags/tz.svg | 13 - frontend/public/assets/flags/ua.svg | 6 - frontend/public/assets/flags/ug.svg | 30 - frontend/public/assets/flags/um.svg | 9 - frontend/public/assets/flags/un.svg | 16 - frontend/public/assets/flags/us.svg | 9 - frontend/public/assets/flags/uy.svg | 28 - frontend/public/assets/flags/uz.svg | 30 - frontend/public/assets/flags/va.svg | 190 - frontend/public/assets/flags/vc.svg | 8 - frontend/public/assets/flags/ve.svg | 26 - frontend/public/assets/flags/vg.svg | 59 - frontend/public/assets/flags/vi.svg | 28 - frontend/public/assets/flags/vn.svg | 11 - frontend/public/assets/flags/vu.svg | 21 - frontend/public/assets/flags/wf.svg | 5 - frontend/public/assets/flags/ws.svg | 7 - frontend/public/assets/flags/xk.svg | 5 - frontend/public/assets/flags/xx.svg | 4 - frontend/public/assets/flags/ye.svg | 7 - frontend/public/assets/flags/yt.svg | 5 - frontend/public/assets/flags/za.svg | 17 - frontend/public/assets/flags/zm.svg | 27 - frontend/public/assets/flags/zw.svg | 21 - frontend/public/icon.svg | 39 - frontend/scripts/generate-icon.js | 24 - frontend/src/App.tsx | 726 --- frontend/src/assets/audiotts-pro.webp | Bin 9172 -> 0 bytes frontend/src/assets/chatgpt-tts.webp | Bin 6922 -> 0 bytes frontend/src/assets/github-lang-colors.ts | 18 - frontend/src/assets/icons/am.png | Bin 9483 -> 0 bytes frontend/src/assets/icons/amzn.png | Bin 56880 -> 0 bytes frontend/src/assets/icons/dzr.png | Bin 23621 -> 0 bytes frontend/src/assets/icons/lrclib.png | Bin 22223 -> 0 bytes frontend/src/assets/icons/musicbrainz_d.png | Bin 28301 -> 0 bytes frontend/src/assets/icons/musicbrainz_l.png | Bin 28243 -> 0 bytes frontend/src/assets/icons/next.svg | 27 - frontend/src/assets/icons/qbz.png | Bin 30704 -> 0 bytes frontend/src/assets/icons/songlink_d.png | Bin 15310 -> 0 bytes frontend/src/assets/icons/songlink_l.png | Bin 15477 -> 0 bytes frontend/src/assets/icons/songstats.png | Bin 40971 -> 0 bytes frontend/src/assets/icons/spotiflac.svg | 39 - frontend/src/assets/icons/spotubedl.svg | 1 - frontend/src/assets/icons/tidal_d.png | Bin 3948 -> 0 bytes frontend/src/assets/icons/tidal_l.png | Bin 3937 -> 0 bytes frontend/src/assets/icons/xbatchdl.svg | 11 - frontend/src/assets/ko-fi.gif | Bin 924277 -> 0 bytes frontend/src/assets/kofi_symbol.svg | 13 - frontend/src/assets/patreon.svg | 6 - frontend/src/assets/patreon_symbol.svg | 11 - frontend/src/assets/usdt.jpg | Bin 35056 -> 0 bytes frontend/src/assets/x.webp | Bin 18318 -> 0 bytes frontend/src/components/AlbumInfo.tsx | 284 -- frontend/src/components/ApiStatusTab.tsx | 85 - frontend/src/components/ArtistInfo.tsx | 643 --- frontend/src/components/AudioAnalysis.tsx | 179 - frontend/src/components/AudioAnalysisPage.tsx | 884 ---- .../src/components/AudioConverterPage.tsx | 460 -- .../src/components/AudioResamplerPage.tsx | 468 -- frontend/src/components/AvailabilityLinks.tsx | 62 - frontend/src/components/DebugLoggerPage.tsx | 113 - frontend/src/components/DownloadProgress.tsx | 32 - .../src/components/DownloadProgressToast.tsx | 31 - frontend/src/components/DownloadQueue.tsx | 274 - frontend/src/components/FetchHistory.tsx | 96 - frontend/src/components/FileManagerPage.tsx | 743 --- frontend/src/components/Header.tsx | 42 - frontend/src/components/HistoryPage.tsx | 706 --- frontend/src/components/OtherProjects.tsx | 322 -- frontend/src/components/PlatformIcons.tsx | 121 - frontend/src/components/PlaylistInfo.tsx | 249 - frontend/src/components/SearchAndSort.tsx | 40 - frontend/src/components/SearchBar.tsx | 817 --- frontend/src/components/SettingsPage.tsx | 1003 ---- frontend/src/components/Sidebar.tsx | 200 - .../src/components/SpectrumVisualization.tsx | 602 --- frontend/src/components/SupportPage.tsx | 97 - frontend/src/components/TitleBar.tsx | 197 - frontend/src/components/TrackInfo.tsx | 190 - frontend/src/components/TrackList.tsx | 384 -- frontend/src/components/ui/activity.tsx | 63 - frontend/src/components/ui/audio-lines.tsx | 87 - frontend/src/components/ui/badge.tsx | 24 - frontend/src/components/ui/blocks-icon.tsx | 53 - .../src/components/ui/bug-report-icon.tsx | 132 - frontend/src/components/ui/button.tsx | 35 - frontend/src/components/ui/card.tsx | 24 - frontend/src/components/ui/checkbox.tsx | 13 - frontend/src/components/ui/coffee.tsx | 67 - frontend/src/components/ui/context-menu.tsx | 77 - frontend/src/components/ui/dialog.tsx | 47 - frontend/src/components/ui/dropdown-menu.tsx | 76 - frontend/src/components/ui/file-music.tsx | 64 - frontend/src/components/ui/file-pen.tsx | 63 - frontend/src/components/ui/history-icon.tsx | 97 - frontend/src/components/ui/home.tsx | 62 - .../src/components/ui/input-with-context.tsx | 156 - frontend/src/components/ui/input.tsx | 6 - frontend/src/components/ui/label.tsx | 8 - frontend/src/components/ui/menubar.tsx | 60 - frontend/src/components/ui/pagination.tsx | 41 - frontend/src/components/ui/progress.tsx | 10 - frontend/src/components/ui/scroll-area.tsx | 18 - frontend/src/components/ui/select.tsx | 73 - frontend/src/components/ui/settings.tsx | 54 - frontend/src/components/ui/slider.tsx | 17 - frontend/src/components/ui/sonner.tsx | 27 - frontend/src/components/ui/spinner.tsx | 6 - frontend/src/components/ui/switch.tsx | 10 - frontend/src/components/ui/tabs.tsx | 16 - frontend/src/components/ui/terminal.tsx | 60 - frontend/src/components/ui/textarea.tsx | 6 - frontend/src/components/ui/toggle-group.tsx | 32 - frontend/src/components/ui/toggle.tsx | 25 - frontend/src/components/ui/tool-case.tsx | 89 - frontend/src/components/ui/tooltip.tsx | 24 - frontend/src/hooks/useApiStatus.ts | 17 - frontend/src/hooks/useAudioAnalysis.ts | 550 -- frontend/src/hooks/useAvailability.ts | 58 - frontend/src/hooks/useCover.ts | 224 - frontend/src/hooks/useDownload.ts | 1111 ---- frontend/src/hooks/useDownloadProgress.ts | 34 - frontend/src/hooks/useDownloadQueueData.ts | 31 - frontend/src/hooks/useDownloadQueueDialog.ts | 13 - frontend/src/hooks/useLyrics.ts | 257 - frontend/src/hooks/useMetadata.ts | 350 -- frontend/src/hooks/usePreview.ts | 90 - frontend/src/hooks/useTypingEffect.ts | 35 - frontend/src/index.css | 275 - frontend/src/lib/api-status.ts | 404 -- frontend/src/lib/api.ts | 50 - frontend/src/lib/artist-links.ts | 42 - frontend/src/lib/async-timeout.ts | 17 - .../src/lib/audio-analysis-preferences.ts | 63 - frontend/src/lib/audio.ts | 72 - frontend/src/lib/flac-analysis.ts | 747 --- frontend/src/lib/logger.ts | 53 - frontend/src/lib/playlist.ts | 14 - frontend/src/lib/preview-player.ts | 37 - frontend/src/lib/preview.ts | 10 - frontend/src/lib/relative-time.ts | 57 - frontend/src/lib/settings.ts | 822 --- frontend/src/lib/spectrum-cache.ts | 15 - frontend/src/lib/themes.ts | 275 - frontend/src/lib/toast-with-sound.ts | 53 - frontend/src/lib/utils.ts | 55 - frontend/src/main.tsx | 9 - frontend/src/types/api.ts | 294 -- frontend/src/vite-env.d.ts | 2 - frontend/tsconfig.app.json | 36 - frontend/tsconfig.json | 13 - frontend/tsconfig.node.json | 26 - frontend/vite.config.ts | 19 - go.mod | 47 - go.sum | 133 - main.go | 69 - wails.json | 21 - 460 files changed, 51905 deletions(-) delete mode 100644 .github/FUNDING.yml delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml delete mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml delete mode 100644 .github/workflows/build.yml delete mode 100644 .gitignore delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 app.go delete mode 100644 backend/amazon.go delete mode 100644 backend/analysis.go delete mode 100644 backend/artist_format.go delete mode 100644 backend/config.go delete mode 100644 backend/cover.go delete mode 100644 backend/download_validation.go delete mode 100644 backend/ffmpeg.go delete mode 100644 backend/ffmpeg_unix.go delete mode 100644 backend/ffmpeg_windows.go delete mode 100644 backend/file_dialog.go delete mode 100644 backend/fileicon_darwin.go delete mode 100644 backend/fileicon_stub.go delete mode 100644 backend/filemanager.go delete mode 100644 backend/filename.go delete mode 100644 backend/folder.go delete mode 100644 backend/history.go delete mode 100644 backend/http_headers.go delete mode 100644 backend/isrc_cache.go delete mode 100644 backend/isrc_finder.go delete mode 100644 backend/isrc_helper.go delete mode 100644 backend/link_resolver.go delete mode 100644 backend/lyrics.go delete mode 100644 backend/metadata.go delete mode 100644 backend/musicbrainz.go delete mode 100644 backend/progress.go delete mode 100644 backend/provider_endpoints.go delete mode 100644 backend/provider_priority.go delete mode 100644 backend/qobuz.go delete mode 100644 backend/qobuz_api.go delete mode 100644 backend/qobuz_providers.go delete mode 100644 backend/recent_fetches.go delete mode 100644 backend/resample.go delete mode 100644 backend/songlink.go delete mode 100644 backend/songstats.go delete mode 100644 backend/soundplate.go delete mode 100644 backend/spotfetch.go delete mode 100644 backend/spotify_metadata.go delete mode 100644 backend/spotify_totp.go delete mode 100644 backend/tidal.go delete mode 100644 backend/upc_tags.go delete mode 100644 frontend/.gitignore delete mode 100644 frontend/components.json delete mode 100644 frontend/eslint.config.js delete mode 100644 frontend/index.html delete mode 100644 frontend/package.json delete mode 100644 frontend/package.json.md5 delete mode 100644 frontend/pnpm-lock.yaml delete mode 100644 frontend/public/assets/flags/ad.svg delete mode 100644 frontend/public/assets/flags/ae.svg delete mode 100644 frontend/public/assets/flags/af.svg delete mode 100644 frontend/public/assets/flags/ag.svg delete mode 100644 frontend/public/assets/flags/ai.svg delete mode 100644 frontend/public/assets/flags/al.svg delete mode 100644 frontend/public/assets/flags/am.svg delete mode 100644 frontend/public/assets/flags/ao.svg delete mode 100644 frontend/public/assets/flags/aq.svg delete mode 100644 frontend/public/assets/flags/ar.svg delete mode 100644 frontend/public/assets/flags/arab.svg delete mode 100644 frontend/public/assets/flags/as.svg delete mode 100644 frontend/public/assets/flags/asean.svg delete mode 100644 frontend/public/assets/flags/at.svg delete mode 100644 frontend/public/assets/flags/au.svg delete mode 100644 frontend/public/assets/flags/aw.svg delete mode 100644 frontend/public/assets/flags/ax.svg delete mode 100644 frontend/public/assets/flags/az.svg delete mode 100644 frontend/public/assets/flags/ba.svg delete mode 100644 frontend/public/assets/flags/bb.svg delete mode 100644 frontend/public/assets/flags/bd.svg delete mode 100644 frontend/public/assets/flags/be.svg delete mode 100644 frontend/public/assets/flags/bf.svg delete mode 100644 frontend/public/assets/flags/bg.svg delete mode 100644 frontend/public/assets/flags/bh.svg delete mode 100644 frontend/public/assets/flags/bi.svg delete mode 100644 frontend/public/assets/flags/bj.svg delete mode 100644 frontend/public/assets/flags/bl.svg delete mode 100644 frontend/public/assets/flags/bm.svg delete mode 100644 frontend/public/assets/flags/bn.svg delete mode 100644 frontend/public/assets/flags/bo.svg delete mode 100644 frontend/public/assets/flags/bq.svg delete mode 100644 frontend/public/assets/flags/br.svg delete mode 100644 frontend/public/assets/flags/bs.svg delete mode 100644 frontend/public/assets/flags/bt.svg delete mode 100644 frontend/public/assets/flags/bv.svg delete mode 100644 frontend/public/assets/flags/bw.svg delete mode 100644 frontend/public/assets/flags/by.svg delete mode 100644 frontend/public/assets/flags/bz.svg delete mode 100644 frontend/public/assets/flags/ca.svg delete mode 100644 frontend/public/assets/flags/cc.svg delete mode 100644 frontend/public/assets/flags/cd.svg delete mode 100644 frontend/public/assets/flags/cefta.svg delete mode 100644 frontend/public/assets/flags/cf.svg delete mode 100644 frontend/public/assets/flags/cg.svg delete mode 100644 frontend/public/assets/flags/ch.svg delete mode 100644 frontend/public/assets/flags/ci.svg delete mode 100644 frontend/public/assets/flags/ck.svg delete mode 100644 frontend/public/assets/flags/cl.svg delete mode 100644 frontend/public/assets/flags/cm.svg delete mode 100644 frontend/public/assets/flags/cn.svg delete mode 100644 frontend/public/assets/flags/co.svg delete mode 100644 frontend/public/assets/flags/cp.svg delete mode 100644 frontend/public/assets/flags/cr.svg delete mode 100644 frontend/public/assets/flags/cu.svg delete mode 100644 frontend/public/assets/flags/cv.svg delete mode 100644 frontend/public/assets/flags/cw.svg delete mode 100644 frontend/public/assets/flags/cx.svg delete mode 100644 frontend/public/assets/flags/cy.svg delete mode 100644 frontend/public/assets/flags/cz.svg delete mode 100644 frontend/public/assets/flags/de.svg delete mode 100644 frontend/public/assets/flags/dg.svg delete mode 100644 frontend/public/assets/flags/dj.svg delete mode 100644 frontend/public/assets/flags/dk.svg delete mode 100644 frontend/public/assets/flags/dm.svg delete mode 100644 frontend/public/assets/flags/do.svg delete mode 100644 frontend/public/assets/flags/dz.svg delete mode 100644 frontend/public/assets/flags/eac.svg delete mode 100644 frontend/public/assets/flags/ec.svg delete mode 100644 frontend/public/assets/flags/ee.svg delete mode 100644 frontend/public/assets/flags/eg.svg delete mode 100644 frontend/public/assets/flags/eh.svg delete mode 100644 frontend/public/assets/flags/er.svg delete mode 100644 frontend/public/assets/flags/es-ct.svg delete mode 100644 frontend/public/assets/flags/es-ga.svg delete mode 100644 frontend/public/assets/flags/es-pv.svg delete mode 100644 frontend/public/assets/flags/es.svg delete mode 100644 frontend/public/assets/flags/et.svg delete mode 100644 frontend/public/assets/flags/eu.svg delete mode 100644 frontend/public/assets/flags/fi.svg delete mode 100644 frontend/public/assets/flags/fj.svg delete mode 100644 frontend/public/assets/flags/fk.svg delete mode 100644 frontend/public/assets/flags/fm.svg delete mode 100644 frontend/public/assets/flags/fo.svg delete mode 100644 frontend/public/assets/flags/fr.svg delete mode 100644 frontend/public/assets/flags/ga.svg delete mode 100644 frontend/public/assets/flags/gb-eng.svg delete mode 100644 frontend/public/assets/flags/gb-nir.svg delete mode 100644 frontend/public/assets/flags/gb-sct.svg delete mode 100644 frontend/public/assets/flags/gb-wls.svg delete mode 100644 frontend/public/assets/flags/gb.svg delete mode 100644 frontend/public/assets/flags/gd.svg delete mode 100644 frontend/public/assets/flags/ge.svg delete mode 100644 frontend/public/assets/flags/gf.svg delete mode 100644 frontend/public/assets/flags/gg.svg delete mode 100644 frontend/public/assets/flags/gh.svg delete mode 100644 frontend/public/assets/flags/gi.svg delete mode 100644 frontend/public/assets/flags/gl.svg delete mode 100644 frontend/public/assets/flags/gm.svg delete mode 100644 frontend/public/assets/flags/gn.svg delete mode 100644 frontend/public/assets/flags/gp.svg delete mode 100644 frontend/public/assets/flags/gq.svg delete mode 100644 frontend/public/assets/flags/gr.svg delete mode 100644 frontend/public/assets/flags/gs.svg delete mode 100644 frontend/public/assets/flags/gt.svg delete mode 100644 frontend/public/assets/flags/gu.svg delete mode 100644 frontend/public/assets/flags/gw.svg delete mode 100644 frontend/public/assets/flags/gy.svg delete mode 100644 frontend/public/assets/flags/hk.svg delete mode 100644 frontend/public/assets/flags/hm.svg delete mode 100644 frontend/public/assets/flags/hn.svg delete mode 100644 frontend/public/assets/flags/hr.svg delete mode 100644 frontend/public/assets/flags/ht.svg delete mode 100644 frontend/public/assets/flags/hu.svg delete mode 100644 frontend/public/assets/flags/ic.svg delete mode 100644 frontend/public/assets/flags/id.svg delete mode 100644 frontend/public/assets/flags/ie.svg delete mode 100644 frontend/public/assets/flags/il.svg delete mode 100644 frontend/public/assets/flags/im.svg delete mode 100644 frontend/public/assets/flags/in.svg delete mode 100644 frontend/public/assets/flags/io.svg delete mode 100644 frontend/public/assets/flags/iq.svg delete mode 100644 frontend/public/assets/flags/ir.svg delete mode 100644 frontend/public/assets/flags/is.svg delete mode 100644 frontend/public/assets/flags/it.svg delete mode 100644 frontend/public/assets/flags/je.svg delete mode 100644 frontend/public/assets/flags/jm.svg delete mode 100644 frontend/public/assets/flags/jo.svg delete mode 100644 frontend/public/assets/flags/jp.svg delete mode 100644 frontend/public/assets/flags/ke.svg delete mode 100644 frontend/public/assets/flags/kg.svg delete mode 100644 frontend/public/assets/flags/kh.svg delete mode 100644 frontend/public/assets/flags/ki.svg delete mode 100644 frontend/public/assets/flags/km.svg delete mode 100644 frontend/public/assets/flags/kn.svg delete mode 100644 frontend/public/assets/flags/kp.svg delete mode 100644 frontend/public/assets/flags/kr.svg delete mode 100644 frontend/public/assets/flags/kw.svg delete mode 100644 frontend/public/assets/flags/ky.svg delete mode 100644 frontend/public/assets/flags/kz.svg delete mode 100644 frontend/public/assets/flags/la.svg delete mode 100644 frontend/public/assets/flags/lb.svg delete mode 100644 frontend/public/assets/flags/lc.svg delete mode 100644 frontend/public/assets/flags/li.svg delete mode 100644 frontend/public/assets/flags/lk.svg delete mode 100644 frontend/public/assets/flags/lr.svg delete mode 100644 frontend/public/assets/flags/ls.svg delete mode 100644 frontend/public/assets/flags/lt.svg delete mode 100644 frontend/public/assets/flags/lu.svg delete mode 100644 frontend/public/assets/flags/lv.svg delete mode 100644 frontend/public/assets/flags/ly.svg delete mode 100644 frontend/public/assets/flags/ma.svg delete mode 100644 frontend/public/assets/flags/mc.svg delete mode 100644 frontend/public/assets/flags/md.svg delete mode 100644 frontend/public/assets/flags/me.svg delete mode 100644 frontend/public/assets/flags/mf.svg delete mode 100644 frontend/public/assets/flags/mg.svg delete mode 100644 frontend/public/assets/flags/mh.svg delete mode 100644 frontend/public/assets/flags/mk.svg delete mode 100644 frontend/public/assets/flags/ml.svg delete mode 100644 frontend/public/assets/flags/mm.svg delete mode 100644 frontend/public/assets/flags/mn.svg delete mode 100644 frontend/public/assets/flags/mo.svg delete mode 100644 frontend/public/assets/flags/mp.svg delete mode 100644 frontend/public/assets/flags/mq.svg delete mode 100644 frontend/public/assets/flags/mr.svg delete mode 100644 frontend/public/assets/flags/ms.svg delete mode 100644 frontend/public/assets/flags/mt.svg delete mode 100644 frontend/public/assets/flags/mu.svg delete mode 100644 frontend/public/assets/flags/mv.svg delete mode 100644 frontend/public/assets/flags/mw.svg delete mode 100644 frontend/public/assets/flags/mx.svg delete mode 100644 frontend/public/assets/flags/my.svg delete mode 100644 frontend/public/assets/flags/mz.svg delete mode 100644 frontend/public/assets/flags/na.svg delete mode 100644 frontend/public/assets/flags/nc.svg delete mode 100644 frontend/public/assets/flags/ne.svg delete mode 100644 frontend/public/assets/flags/nf.svg delete mode 100644 frontend/public/assets/flags/ng.svg delete mode 100644 frontend/public/assets/flags/ni.svg delete mode 100644 frontend/public/assets/flags/nl.svg delete mode 100644 frontend/public/assets/flags/no.svg delete mode 100644 frontend/public/assets/flags/np.svg delete mode 100644 frontend/public/assets/flags/nr.svg delete mode 100644 frontend/public/assets/flags/nu.svg delete mode 100644 frontend/public/assets/flags/nz.svg delete mode 100644 frontend/public/assets/flags/om.svg delete mode 100644 frontend/public/assets/flags/pa.svg delete mode 100644 frontend/public/assets/flags/pc.svg delete mode 100644 frontend/public/assets/flags/pe.svg delete mode 100644 frontend/public/assets/flags/pf.svg delete mode 100644 frontend/public/assets/flags/pg.svg delete mode 100644 frontend/public/assets/flags/ph.svg delete mode 100644 frontend/public/assets/flags/pk.svg delete mode 100644 frontend/public/assets/flags/pl.svg delete mode 100644 frontend/public/assets/flags/pm.svg delete mode 100644 frontend/public/assets/flags/pn.svg delete mode 100644 frontend/public/assets/flags/pr.svg delete mode 100644 frontend/public/assets/flags/ps.svg delete mode 100644 frontend/public/assets/flags/pt.svg delete mode 100644 frontend/public/assets/flags/pw.svg delete mode 100644 frontend/public/assets/flags/py.svg delete mode 100644 frontend/public/assets/flags/qa.svg delete mode 100644 frontend/public/assets/flags/re.svg delete mode 100644 frontend/public/assets/flags/ro.svg delete mode 100644 frontend/public/assets/flags/rs.svg delete mode 100644 frontend/public/assets/flags/ru.svg delete mode 100644 frontend/public/assets/flags/rw.svg delete mode 100644 frontend/public/assets/flags/sa.svg delete mode 100644 frontend/public/assets/flags/sb.svg delete mode 100644 frontend/public/assets/flags/sc.svg delete mode 100644 frontend/public/assets/flags/sd.svg delete mode 100644 frontend/public/assets/flags/se.svg delete mode 100644 frontend/public/assets/flags/sg.svg delete mode 100644 frontend/public/assets/flags/sh-ac.svg delete mode 100644 frontend/public/assets/flags/sh-hl.svg delete mode 100644 frontend/public/assets/flags/sh-ta.svg delete mode 100644 frontend/public/assets/flags/sh.svg delete mode 100644 frontend/public/assets/flags/si.svg delete mode 100644 frontend/public/assets/flags/sj.svg delete mode 100644 frontend/public/assets/flags/sk.svg delete mode 100644 frontend/public/assets/flags/sl.svg delete mode 100644 frontend/public/assets/flags/sm.svg delete mode 100644 frontend/public/assets/flags/sn.svg delete mode 100644 frontend/public/assets/flags/so.svg delete mode 100644 frontend/public/assets/flags/sr.svg delete mode 100644 frontend/public/assets/flags/ss.svg delete mode 100644 frontend/public/assets/flags/st.svg delete mode 100644 frontend/public/assets/flags/sv.svg delete mode 100644 frontend/public/assets/flags/sx.svg delete mode 100644 frontend/public/assets/flags/sy.svg delete mode 100644 frontend/public/assets/flags/sz.svg delete mode 100644 frontend/public/assets/flags/tc.svg delete mode 100644 frontend/public/assets/flags/td.svg delete mode 100644 frontend/public/assets/flags/tf.svg delete mode 100644 frontend/public/assets/flags/tg.svg delete mode 100644 frontend/public/assets/flags/th.svg delete mode 100644 frontend/public/assets/flags/tj.svg delete mode 100644 frontend/public/assets/flags/tk.svg delete mode 100644 frontend/public/assets/flags/tl.svg delete mode 100644 frontend/public/assets/flags/tm.svg delete mode 100644 frontend/public/assets/flags/tn.svg delete mode 100644 frontend/public/assets/flags/to.svg delete mode 100644 frontend/public/assets/flags/tr.svg delete mode 100644 frontend/public/assets/flags/tt.svg delete mode 100644 frontend/public/assets/flags/tv.svg delete mode 100644 frontend/public/assets/flags/tw.svg delete mode 100644 frontend/public/assets/flags/tz.svg delete mode 100644 frontend/public/assets/flags/ua.svg delete mode 100644 frontend/public/assets/flags/ug.svg delete mode 100644 frontend/public/assets/flags/um.svg delete mode 100644 frontend/public/assets/flags/un.svg delete mode 100644 frontend/public/assets/flags/us.svg delete mode 100644 frontend/public/assets/flags/uy.svg delete mode 100644 frontend/public/assets/flags/uz.svg delete mode 100644 frontend/public/assets/flags/va.svg delete mode 100644 frontend/public/assets/flags/vc.svg delete mode 100644 frontend/public/assets/flags/ve.svg delete mode 100644 frontend/public/assets/flags/vg.svg delete mode 100644 frontend/public/assets/flags/vi.svg delete mode 100644 frontend/public/assets/flags/vn.svg delete mode 100644 frontend/public/assets/flags/vu.svg delete mode 100644 frontend/public/assets/flags/wf.svg delete mode 100644 frontend/public/assets/flags/ws.svg delete mode 100644 frontend/public/assets/flags/xk.svg delete mode 100644 frontend/public/assets/flags/xx.svg delete mode 100644 frontend/public/assets/flags/ye.svg delete mode 100644 frontend/public/assets/flags/yt.svg delete mode 100644 frontend/public/assets/flags/za.svg delete mode 100644 frontend/public/assets/flags/zm.svg delete mode 100644 frontend/public/assets/flags/zw.svg delete mode 100644 frontend/public/icon.svg delete mode 100644 frontend/scripts/generate-icon.js delete mode 100644 frontend/src/App.tsx delete mode 100644 frontend/src/assets/audiotts-pro.webp delete mode 100644 frontend/src/assets/chatgpt-tts.webp delete mode 100644 frontend/src/assets/github-lang-colors.ts delete mode 100644 frontend/src/assets/icons/am.png delete mode 100644 frontend/src/assets/icons/amzn.png delete mode 100644 frontend/src/assets/icons/dzr.png delete mode 100644 frontend/src/assets/icons/lrclib.png delete mode 100644 frontend/src/assets/icons/musicbrainz_d.png delete mode 100644 frontend/src/assets/icons/musicbrainz_l.png delete mode 100644 frontend/src/assets/icons/next.svg delete mode 100644 frontend/src/assets/icons/qbz.png delete mode 100644 frontend/src/assets/icons/songlink_d.png delete mode 100644 frontend/src/assets/icons/songlink_l.png delete mode 100644 frontend/src/assets/icons/songstats.png delete mode 100644 frontend/src/assets/icons/spotiflac.svg delete mode 100644 frontend/src/assets/icons/spotubedl.svg delete mode 100644 frontend/src/assets/icons/tidal_d.png delete mode 100644 frontend/src/assets/icons/tidal_l.png delete mode 100644 frontend/src/assets/icons/xbatchdl.svg delete mode 100644 frontend/src/assets/ko-fi.gif delete mode 100644 frontend/src/assets/kofi_symbol.svg delete mode 100644 frontend/src/assets/patreon.svg delete mode 100644 frontend/src/assets/patreon_symbol.svg delete mode 100644 frontend/src/assets/usdt.jpg delete mode 100644 frontend/src/assets/x.webp delete mode 100644 frontend/src/components/AlbumInfo.tsx delete mode 100644 frontend/src/components/ApiStatusTab.tsx delete mode 100644 frontend/src/components/ArtistInfo.tsx delete mode 100644 frontend/src/components/AudioAnalysis.tsx delete mode 100644 frontend/src/components/AudioAnalysisPage.tsx delete mode 100644 frontend/src/components/AudioConverterPage.tsx delete mode 100644 frontend/src/components/AudioResamplerPage.tsx delete mode 100644 frontend/src/components/AvailabilityLinks.tsx delete mode 100644 frontend/src/components/DebugLoggerPage.tsx delete mode 100644 frontend/src/components/DownloadProgress.tsx delete mode 100644 frontend/src/components/DownloadProgressToast.tsx delete mode 100644 frontend/src/components/DownloadQueue.tsx delete mode 100644 frontend/src/components/FetchHistory.tsx delete mode 100644 frontend/src/components/FileManagerPage.tsx delete mode 100644 frontend/src/components/Header.tsx delete mode 100644 frontend/src/components/HistoryPage.tsx delete mode 100644 frontend/src/components/OtherProjects.tsx delete mode 100644 frontend/src/components/PlatformIcons.tsx delete mode 100644 frontend/src/components/PlaylistInfo.tsx delete mode 100644 frontend/src/components/SearchAndSort.tsx delete mode 100644 frontend/src/components/SearchBar.tsx delete mode 100644 frontend/src/components/SettingsPage.tsx delete mode 100644 frontend/src/components/Sidebar.tsx delete mode 100644 frontend/src/components/SpectrumVisualization.tsx delete mode 100644 frontend/src/components/SupportPage.tsx delete mode 100644 frontend/src/components/TitleBar.tsx delete mode 100644 frontend/src/components/TrackInfo.tsx delete mode 100644 frontend/src/components/TrackList.tsx delete mode 100644 frontend/src/components/ui/activity.tsx delete mode 100644 frontend/src/components/ui/audio-lines.tsx delete mode 100644 frontend/src/components/ui/badge.tsx delete mode 100644 frontend/src/components/ui/blocks-icon.tsx delete mode 100644 frontend/src/components/ui/bug-report-icon.tsx delete mode 100644 frontend/src/components/ui/button.tsx delete mode 100644 frontend/src/components/ui/card.tsx delete mode 100644 frontend/src/components/ui/checkbox.tsx delete mode 100644 frontend/src/components/ui/coffee.tsx delete mode 100644 frontend/src/components/ui/context-menu.tsx delete mode 100644 frontend/src/components/ui/dialog.tsx delete mode 100644 frontend/src/components/ui/dropdown-menu.tsx delete mode 100644 frontend/src/components/ui/file-music.tsx delete mode 100644 frontend/src/components/ui/file-pen.tsx delete mode 100644 frontend/src/components/ui/history-icon.tsx delete mode 100644 frontend/src/components/ui/home.tsx delete mode 100644 frontend/src/components/ui/input-with-context.tsx delete mode 100644 frontend/src/components/ui/input.tsx delete mode 100644 frontend/src/components/ui/label.tsx delete mode 100644 frontend/src/components/ui/menubar.tsx delete mode 100644 frontend/src/components/ui/pagination.tsx delete mode 100644 frontend/src/components/ui/progress.tsx delete mode 100644 frontend/src/components/ui/scroll-area.tsx delete mode 100644 frontend/src/components/ui/select.tsx delete mode 100644 frontend/src/components/ui/settings.tsx delete mode 100644 frontend/src/components/ui/slider.tsx delete mode 100644 frontend/src/components/ui/sonner.tsx delete mode 100644 frontend/src/components/ui/spinner.tsx delete mode 100644 frontend/src/components/ui/switch.tsx delete mode 100644 frontend/src/components/ui/tabs.tsx delete mode 100644 frontend/src/components/ui/terminal.tsx delete mode 100644 frontend/src/components/ui/textarea.tsx delete mode 100644 frontend/src/components/ui/toggle-group.tsx delete mode 100644 frontend/src/components/ui/toggle.tsx delete mode 100644 frontend/src/components/ui/tool-case.tsx delete mode 100644 frontend/src/components/ui/tooltip.tsx delete mode 100644 frontend/src/hooks/useApiStatus.ts delete mode 100644 frontend/src/hooks/useAudioAnalysis.ts delete mode 100644 frontend/src/hooks/useAvailability.ts delete mode 100644 frontend/src/hooks/useCover.ts delete mode 100644 frontend/src/hooks/useDownload.ts delete mode 100644 frontend/src/hooks/useDownloadProgress.ts delete mode 100644 frontend/src/hooks/useDownloadQueueData.ts delete mode 100644 frontend/src/hooks/useDownloadQueueDialog.ts delete mode 100644 frontend/src/hooks/useLyrics.ts delete mode 100644 frontend/src/hooks/useMetadata.ts delete mode 100644 frontend/src/hooks/usePreview.ts delete mode 100644 frontend/src/hooks/useTypingEffect.ts delete mode 100644 frontend/src/index.css delete mode 100644 frontend/src/lib/api-status.ts delete mode 100644 frontend/src/lib/api.ts delete mode 100644 frontend/src/lib/artist-links.ts delete mode 100644 frontend/src/lib/async-timeout.ts delete mode 100644 frontend/src/lib/audio-analysis-preferences.ts delete mode 100644 frontend/src/lib/audio.ts delete mode 100644 frontend/src/lib/flac-analysis.ts delete mode 100644 frontend/src/lib/logger.ts delete mode 100644 frontend/src/lib/playlist.ts delete mode 100644 frontend/src/lib/preview-player.ts delete mode 100644 frontend/src/lib/preview.ts delete mode 100644 frontend/src/lib/relative-time.ts delete mode 100644 frontend/src/lib/settings.ts delete mode 100644 frontend/src/lib/spectrum-cache.ts delete mode 100644 frontend/src/lib/themes.ts delete mode 100644 frontend/src/lib/toast-with-sound.ts delete mode 100644 frontend/src/lib/utils.ts delete mode 100644 frontend/src/main.tsx delete mode 100644 frontend/src/types/api.ts delete mode 100644 frontend/src/vite-env.d.ts delete mode 100644 frontend/tsconfig.app.json delete mode 100644 frontend/tsconfig.json delete mode 100644 frontend/tsconfig.node.json delete mode 100644 frontend/vite.config.ts delete mode 100644 go.mod delete mode 100644 go.sum delete mode 100644 main.go delete mode 100644 wails.json diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 1ee451b..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -ko_fi: afkarxyz -patreon: afkarxyz \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml deleted file mode 100644 index ecaf71a..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: Bug Report -description: Bug Report -title: "[Bug Report] " -labels: ["bug"] - -body: - - type: markdown - attributes: - value: | - > **WARNING: Issues that do not follow this template will be deleted without review.** - > - > **Please keep `[Bug Report]` in the issue title and only continue after it.** - - - type: textarea - id: problem - attributes: - label: Problem - placeholder: e.g. Downloading a playlist stops after the first track with no error message. - validations: - required: true - - - type: dropdown - id: type - attributes: - label: Type - description: Select the Spotify item type related to this bug. - options: - - Track - - Album - - Playlist - - Artist - validations: - required: true - - - type: input - id: spotify-url - attributes: - label: Spotify URL - placeholder: e.g. https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT - validations: - required: true - - - type: textarea - id: additional-context - attributes: - label: Additional Context - placeholder: e.g. Happens every time on this link. Screenshot or recording attached. - validations: - required: true - - - type: markdown - attributes: - value: "### Environment" - - - type: input - id: version - attributes: - label: SpotiFLAC Version - placeholder: e.g. v7.1.0 - validations: - required: true - - - type: input - id: os - attributes: - label: OS - placeholder: e.g. Windows 11 23H2 - validations: - required: true - - - type: input - id: location - attributes: - label: Location - placeholder: e.g. Indonesia - validations: - required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index ec4bb38..0000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1 +0,0 @@ -blank_issues_enabled: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml deleted file mode 100644 index f91add4..0000000 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Feature Request -description: Feature Request -title: "[Feature Request] " -labels: ["enhancement"] - -body: - - type: markdown - attributes: - value: | - > **WARNING: Issues that do not follow this template will be deleted without review.** - > - > **Please keep `[Feature Request]` in the issue title and only continue after it.** - - - type: textarea - id: description - attributes: - label: Description - placeholder: e.g. Add an option to choose the output naming format for downloaded tracks. - validations: - required: true - - - type: textarea - id: use-case - attributes: - label: Use Case - placeholder: e.g. I want downloaded files to follow a custom format like Artist - Title for easier library management. - validations: - required: true - - - type: textarea - id: additional-context - attributes: - label: Additional Context - placeholder: e.g. Similar tools allow custom naming templates. Screenshot or mockup attached if needed. - validations: - required: true diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 46bee43..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,421 +0,0 @@ -name: Build Multi-Platform - -on: - push: - tags: - - 'v*' - workflow_dispatch: - -env: - GO_VERSION: '1.26' - NODE_VERSION: '24' - -jobs: - build-windows: - name: Build Windows - runs-on: windows-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Get version from tag - id: version - shell: bash - run: | - if [[ "${{ github.ref }}" == refs/tags/* ]]; then - VERSION=${GITHUB_REF#refs/tags/} - else - VERSION="dev" - fi - echo "version=$VERSION" >> $GITHUB_OUTPUT - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: ${{ env.GO_VERSION }} - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: Install pnpm - uses: pnpm/action-setup@v4 - with: - version: 9 - - - name: Get pnpm store directory - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - - - name: Setup pnpm cache - continue-on-error: true - uses: actions/cache@v4 - with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('frontend/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install Wails CLI - run: go install github.com/wailsapp/wails/v2/cmd/wails@latest - - - name: Install frontend dependencies - working-directory: frontend - run: | - pnpm install - pnpm run generate-icon - - - name: Install UPX - run: | - choco install upx -y - - - name: Build application - run: wails build -platform windows/amd64 - - - name: Compress with UPX - run: | - upx --best --lzma "build\bin\SpotiFLAC.exe" - - - name: Prepare artifacts - run: | - mkdir -p dist - Copy-Item -Path "build\bin\SpotiFLAC.exe" -Destination "dist\SpotiFLAC.exe" - - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: windows-portable - path: dist/SpotiFLAC.exe - retention-days: 7 - - build-macos: - name: Build macOS - runs-on: macos-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Get version from tag - id: version - run: | - if [[ "${{ github.ref }}" == refs/tags/* ]]; then - VERSION=${GITHUB_REF#refs/tags/} - else - VERSION="dev" - fi - echo "version=$VERSION" >> $GITHUB_OUTPUT - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: ${{ env.GO_VERSION }} - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: Install pnpm - uses: pnpm/action-setup@v4 - with: - version: 9 - - - name: Get pnpm store directory - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - - - name: Setup pnpm cache - continue-on-error: true - uses: actions/cache@v4 - with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('frontend/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install Wails CLI - run: go install github.com/wailsapp/wails/v2/cmd/wails@latest - - - name: Install frontend dependencies - working-directory: frontend - run: | - pnpm install - pnpm run generate-icon - - - name: Build application - run: wails build -platform darwin/universal - - - name: Create DMG - run: | - mkdir -p dist - # Install create-dmg if not available - brew install create-dmg || true - - # Create DMG - create-dmg \ - --volname "SpotiFLAC" \ - --window-pos 200 120 \ - --window-size 600 400 \ - --icon-size 100 \ - --icon "SpotiFLAC.app" 175 120 \ - --hide-extension "SpotiFLAC.app" \ - --app-drop-link 425 120 \ - "dist/SpotiFLAC.dmg" \ - "build/bin/SpotiFLAC.app" || \ - # Fallback to hdiutil if create-dmg fails - hdiutil create -volname SpotiFLAC -srcfolder build/bin/SpotiFLAC.app -ov -format UDZO dist/SpotiFLAC.dmg - - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: macos-portable - path: dist/SpotiFLAC.dmg - retention-days: 7 - - build-linux: - name: Build Linux (${{ matrix.display_name }}) - runs-on: ${{ matrix.runner }} - strategy: - fail-fast: false - matrix: - include: - - display_name: amd64 - runner: ubuntu-24.04 - wails_platform: linux/amd64 - artifact_name: linux-portable - output_name: SpotiFLAC.AppImage - appimage_arch: x86_64 - appimagetool_arch: x86_64 - pkgconfig_dir: /usr/lib/x86_64-linux-gnu/pkgconfig - - display_name: arm64 - runner: ubuntu-24.04-arm - wails_platform: linux/arm64 - artifact_name: linux-portable-arm - output_name: SpotiFLAC-ARM.AppImage - appimage_arch: aarch64 - appimagetool_arch: aarch64 - pkgconfig_dir: /usr/lib/aarch64-linux-gnu/pkgconfig - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Get version from tag - id: version - run: | - if [[ "${{ github.ref }}" == refs/tags/* ]]; then - VERSION=${GITHUB_REF#refs/tags/} - else - VERSION="dev" - fi - echo "version=$VERSION" >> $GITHUB_OUTPUT - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: ${{ env.GO_VERSION }} - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: Install pnpm - uses: pnpm/action-setup@v4 - with: - version: 9 - - - name: Get pnpm store directory - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - - - name: Setup pnpm cache - continue-on-error: true - uses: actions/cache@v4 - with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('frontend/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libfuse2 imagemagick upx-ucl - - # Create symlink for webkit2gtk-4.0 -> webkit2gtk-4.1 (Ubuntu 24.04 compatibility) - sudo ln -sf "${{ matrix.pkgconfig_dir }}/webkit2gtk-4.1.pc" "${{ matrix.pkgconfig_dir }}/webkit2gtk-4.0.pc" - - - name: Install Wails CLI - run: go install github.com/wailsapp/wails/v2/cmd/wails@latest - - - name: Install frontend dependencies - working-directory: frontend - run: | - pnpm install - pnpm run generate-icon - - - name: Build application - run: wails build -platform ${{ matrix.wails_platform }} - - - name: Compress with UPX - run: | - upx --best --lzma build/bin/SpotiFLAC - - - name: Cache appimagetool - id: cache-appimagetool - uses: actions/cache@v4 - with: - path: appimagetool - key: appimagetool-${{ matrix.appimagetool_arch }}-v2 - - - name: Download appimagetool - if: steps.cache-appimagetool.outputs.cache-hit != 'true' - run: | - wget --timeout=30 --tries=5 --retry-connrefused --waitretry=5 -O appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${{ matrix.appimagetool_arch }}.AppImage" || \ - wget --timeout=30 --tries=5 --retry-connrefused --waitretry=5 -O appimagetool "https://github.com/AppImage/appimagetool/releases/download/1.9.1/appimagetool-${{ matrix.appimagetool_arch }}.AppImage" - - - name: Make appimagetool executable - run: chmod +x appimagetool - - - name: Create AppImage - run: | - mkdir -p AppDir/usr/bin - mkdir -p AppDir/usr/share/applications - mkdir -p AppDir/usr/share/icons/hicolor/256x256/apps - - # Copy binary - cp build/bin/SpotiFLAC AppDir/usr/bin/ - - # Create desktop file - cat > AppDir/spotiflac.desktop << 'EOF' - [Desktop Entry] - Name=SpotiFLAC - Exec=SpotiFLAC - Icon=spotiflac - Type=Application - Categories=Audio;AudioVideo; - Comment=Get Spotify tracks in true FLAC from Tidal/Deezer - EOF - - cp AppDir/spotiflac.desktop AppDir/usr/share/applications/ - - # Create icon - if [ -f "build/appicon.png" ]; then - convert build/appicon.png -resize 256x256 AppDir/spotiflac.png - elif [ -f "frontend/public/icon.svg" ]; then - convert -background none -size 256x256 frontend/public/icon.svg AppDir/spotiflac.png - else - echo "Warning: No icon found, building without icon" - fi - - # Copy icon if exists - if [ -f "AppDir/spotiflac.png" ]; then - cp AppDir/spotiflac.png AppDir/usr/share/icons/hicolor/256x256/apps/ - cp AppDir/spotiflac.png AppDir/.DirIcon - fi - - # Create AppRun - cat > AppDir/AppRun << 'EOF' - #!/bin/sh - SELF=$(readlink -f "$0") - HERE=${SELF%/*} - export PATH="${HERE}/usr/bin/:${PATH}" - export LD_LIBRARY_PATH="${HERE}/usr/lib/:${LD_LIBRARY_PATH}" - exec "${HERE}/usr/bin/SpotiFLAC" "$@" - EOF - chmod +x AppDir/AppRun - - # Create AppImage - mkdir -p dist - ARCH=${{ matrix.appimage_arch }} ./appimagetool --no-appstream AppDir "dist/${{ matrix.output_name }}" - - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.artifact_name }} - path: dist/${{ matrix.output_name }} - retention-days: 7 - - create-release: - name: Create Release - needs: [build-windows, build-macos, build-linux] - runs-on: ubuntu-latest - if: startsWith(github.ref, 'refs/tags/v') - permissions: - contents: write - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Get version from tag - id: version - run: | - VERSION=${GITHUB_REF#refs/tags/} - echo "version=$VERSION" >> $GITHUB_OUTPUT - - - name: Download all artifacts - uses: actions/download-artifact@v4 - with: - path: artifacts - - - name: Display structure of downloaded files - run: ls -R artifacts - - - name: Create Release - uses: softprops/action-gh-release@v2 - with: - draft: true - prerelease: false - generate_release_notes: false - body: | - ## Changelog - - ## Downloads - - - `SpotiFLAC.exe` - Windows - - `SpotiFLAC.dmg` - macOS - - `SpotiFLAC.AppImage` - Linux AMD64 - - `SpotiFLAC-ARM.AppImage` - Linux ARM64 - -
- Linux Requirements - - The AppImage requires `webkit2gtk-4.1` to be installed on your system: - - **Ubuntu/Debian:** - ```bash - sudo apt install libwebkit2gtk-4.1-0 - ``` - - **Arch Linux:** - ```bash - sudo pacman -S webkit2gtk-4.1 - ``` - - **Fedora:** - ```bash - sudo dnf install webkit2gtk4.1 - ``` - - After installing the dependency, make the AppImage executable: - ```bash - chmod +x SpotiFLAC.AppImage - ./SpotiFLAC.AppImage - ``` - - For ARM64: - ```bash - chmod +x SpotiFLAC-ARM.AppImage - ./SpotiFLAC-ARM.AppImage - ``` - -
- files: | - artifacts/windows-portable/SpotiFLAC.exe - artifacts/macos-portable/SpotiFLAC.dmg - artifacts/linux-portable/SpotiFLAC.AppImage - artifacts/linux-portable-arm/SpotiFLAC-ARM.AppImage - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 0fd4e72..0000000 --- a/.gitignore +++ /dev/null @@ -1,64 +0,0 @@ -# Wails Build -build/ -*.exe -*.dll -*.dylib -*.so - -# Wails Generated Files -frontend/wailsjs/ - -# Go -*.test -*.out -go.work -go.work.sum - -# Node / Frontend -node_modules/ -frontend/node_modules/ -frontend/dist/ -frontend/.vite/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -.pnpm-store/ -.npm -.yarn -*.tsbuildinfo - -# IDE / Editors -.vscode/ -.idea/ -*.swp -*.swo -*~ -.DS_Store - -# OS -Thumbs.db -desktop.ini - -# Environment -.env -.env.local -.env.*.local - -# Logs -*.log -logs/ - -# Temporary files -tmp/ -temp/ -*.tmp -*.bak -*.old - -# Test files -test - -# Build notes (optional - uncomment if you don't want to commit) -# BUILD_NOTES.md -push.bat \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 705657f..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2026 afkarxyz - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 7137312..0000000 --- a/README.md +++ /dev/null @@ -1,115 +0,0 @@ -# SpotiFLAC - -afkarxyz%2FSpotiFLAC | Trendshift - -Get Spotify tracks in true FLAC from Tidal, Qobuz & Amazon Music — no account required. - -![Windows](https://img.shields.io/badge/Windows-10%2B-0078D6?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxwYXRoIGZpbGw9IiNmZmZmZmYiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTIwIDEwLjg3M1YyMEw4LjQ3OSAxOC41MzdsLjAwMS03LjY2NEgyMFptLTEzLjEyIDBsLS4wMDEgNy40NjFMMCAxNy40NjF2LTYuNTg4aDYuODhaTTIwIDkuMjczSDguNDhsLS4wMDEtNy44MUwyMCAwdjkuMjczWk02Ljg3OSAxLjY2NmwuMDAxIDcuNjA3SDBWMi41MzlsNi44NzktLjg3M1oiLz48L3N2Zz4=) -![macOS](https://img.shields.io/badge/macOS-10.13%2B-000000?style=for-the-badge&logo=apple&logoColor=white) -![Linux](https://img.shields.io/badge/Linux-Any-FCC624?style=for-the-badge&logo=linux&logoColor=white) -[![Announcements](https://img.shields.io/badge/ANNOUNCEMENTS-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/spotiflac) -[![Chat](https://img.shields.io/badge/CHAT-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/spotiflac_chat) - -### [Download](https://github.com/spotbye/SpotiFLAC/releases) - -![Image](https://github.com/user-attachments/assets/c2624ca5-8569-49f0-950e-4410b523cea1) - -## Other projects - -### [SpotiFLAC Next](https://github.com/spotbye/SpotiFLAC-Next) - -Get Spotify tracks in true Lossless from Tidal, Qobuz, Amazon Music, Deezer & Apple Music — no account required. - -### [SpotubeDL.com](https://spotubedl.com) - -Download Spotify Tracks, Albums, Playlists & Discography as MP3/OGG/Opus. - -## Related projects - -### [SpotiFLAC (Mobile)](https://github.com/zarzet/SpotiFLAC-Mobile) - -SpotiFLAC for Android & iOS — maintained by [@zarzet](https://github.com/zarzet) - -### [SpotiFLAC (Python Module)](https://github.com/ShuShuzinhuu/SpotiFLAC-Module-Version) - -SpotiFLAC Python library for SpotiFLAC integration — maintained by [@ShuShuzinhuu](https://github.com/ShuShuzinhuu) - -## FAQ - -
-Is this software free? - -_Yes. This software is completely free. -You do not need an account, login, or subscription. -All you need is an internet connection._ - -
- -
-Can using this software get my Spotify account suspended or banned? - -_No. -This software has no connection to your Spotify account. -Spotify data is obtained through reverse engineering of the Spotify Web Player, not through user authentication._ - -
- -
-Where does the audio come from? - -_The audio is fetched using third-party APIs._ - -
- -
-Why does metadata fetching sometimes fail? - -_This usually happens because your IP address has been rate-limited. -You can wait and try again later, or use a VPN to bypass the rate limit._ - -
- -
-Why does Windows Defender or antivirus flag or delete the file? - -_This is a false positive. -It likely happens because the executable is compressed using UPX._ - -_If you are concerned, you can fork the repository and build the software yourself from source._ - -
- -
-Want to support the project? - -_If this software is useful and brings you value, -consider supporting the project by buying me a coffee. -Your support helps keep development going._ - -
- -[![Ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/afkarxyz) - -## Disclaimer - -This project is for **educational and private use only**. The developer does not condone or encourage copyright infringement. - -**SpotiFLAC** is a third-party tool and is not affiliated with, endorsed by, or connected to Spotify, Tidal, Qobuz, Amazon Music or any other streaming service. - -You are solely responsible for: - -1. Ensuring your use of this software complies with your local laws. -2. Reading and adhering to the Terms of Service of the respective platforms. -3. Any legal consequences resulting from the misuse of this tool. - -The software is provided "as is", without warranty of any kind. The author assumes no liability for any bans, damages, or legal issues arising from its use. - -## API Credits - -[MusicBrainz](https://musicbrainz.org) · [LRCLIB](https://lrclib.net) · [Songlink/Odesli](https://song.link) · [hifi-api](https://github.com/binimum/hifi-api) · [WJHE](https://music.wjhe.top) · [GDStudio](https://music.gdstudio.xyz) · [MusicDL](https://musicdl.me) - -> [!TIP] -> -> **Star Us**, You will receive all release notifications from GitHub without any delay ~ - -[![RepoStars](https://repostars.dev/api/embed?repo=afkarxyz%2FSpotiFLAC&theme=forest)](https://repostars.dev/?repos=afkarxyz%2FSpotiFLAC&theme=forest) diff --git a/app.go b/app.go deleted file mode 100644 index 82a8e32..0000000 --- a/app.go +++ /dev/null @@ -1,2420 +0,0 @@ -package main - -import ( - "context" - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "io" - "net/url" - "os" - - "path/filepath" - - "net/http" - "strings" - "sync" - "time" - - "github.com/afkarxyz/SpotiFLAC/backend" - - "github.com/wailsapp/wails/v2/pkg/runtime" -) - -type App struct { - ctx context.Context -} - -type CurrentIPInfo struct { - IP string `json:"ip"` - Country string `json:"country"` - CountryCode string `json:"country_code,omitempty"` - Source string `json:"source,omitempty"` -} - -type APIStatusTargetResult struct { - Target string `json:"target"` - Label string `json:"label"` - Online bool `json:"online"` - Message string `json:"message,omitempty"` -} - -type APIStatusReport struct { - Type string `json:"type"` - Online bool `json:"online"` - RequireAll bool `json:"require_all"` - Details []APIStatusTargetResult `json:"details"` -} - -const checkOperationTimeout = 10 * time.Second - -func NewApp() *App { - return &App{} -} - -func (a *App) LogStatusConsole(level string, message string) { - normalizedLevel := strings.ToLower(strings.TrimSpace(level)) - if normalizedLevel == "" { - normalizedLevel = "info" - } - - line := fmt.Sprintf("[%s] [%s] %s\n", time.Now().Format("15:04:05"), normalizedLevel, strings.TrimSpace(message)) - switch normalizedLevel { - case "error": - _, _ = fmt.Fprint(os.Stderr, line) - default: - fmt.Print(line) - } -} - -type timedResult[T any] struct { - value T - err error -} - -func runWithTimeout[T any](timeout time.Duration, fn func() (T, error)) (T, error) { - resultCh := make(chan timedResult[T], 1) - - go func() { - value, err := fn() - resultCh <- timedResult[T]{value: value, err: err} - }() - - select { - case result := <-resultCh: - return result.value, result.err - case <-time.After(timeout): - var zero T - return zero, fmt.Errorf("operation timed out after %s", timeout) - } -} - -func containsStreamingURL(body []byte) bool { - trimmedBody := strings.TrimSpace(string(body)) - if trimmedBody == "" { - return false - } - - var directResp struct { - URL string `json:"url"` - } - if err := json.Unmarshal(body, &directResp); err == nil && isStreamingURL(directResp.URL) { - return true - } - - var nestedResp struct { - Data struct { - URL string `json:"url"` - } `json:"data"` - } - if err := json.Unmarshal(body, &nestedResp); err == nil && isStreamingURL(nestedResp.Data.URL) { - return true - } - - return isStreamingURL(trimmedBody) -} - -func containsLRCLIBResults(body []byte) bool { - trimmedBody := strings.TrimSpace(string(body)) - if trimmedBody == "" { - return false - } - - var searchResults []map[string]interface{} - if err := json.Unmarshal(body, &searchResults); err == nil { - return len(searchResults) > 0 - } - - var exactResult map[string]interface{} - if err := json.Unmarshal(body, &exactResult); err == nil { - return len(exactResult) > 0 - } - - return false -} - -func containsMusicBrainzResults(body []byte) bool { - trimmedBody := strings.TrimSpace(string(body)) - if trimmedBody == "" { - return false - } - - var payload struct { - Count int `json:"count"` - Recordings []json.RawMessage `json:"recordings"` - } - if err := json.Unmarshal(body, &payload); err != nil { - return false - } - - return payload.Count > 0 || len(payload.Recordings) > 0 -} - -func isStreamingURL(raw string) bool { - candidate := strings.TrimSpace(raw) - if candidate == "" { - return false - } - - parsed, err := url.Parse(candidate) - if err != nil { - return false - } - - return (parsed.Scheme == "http" || parsed.Scheme == "https") && parsed.Host != "" -} - -func previewResponseBody(body []byte, maxLen int) string { - preview := strings.TrimSpace(string(body)) - if maxLen > 0 && len(preview) > maxLen { - return preview[:maxLen] + "..." - } - return preview -} - -func fetchCurrentIPInfo() (CurrentIPInfo, error) { - type ipwhoisResponse struct { - Success bool `json:"success"` - IP string `json:"ip"` - Country string `json:"country"` - CountryCode string `json:"country_code"` - Message string `json:"message"` - } - type ipapiResponse struct { - IP string `json:"ip"` - Country string `json:"country_name"` - CountryCode string `json:"country_code"` - Error bool `json:"error"` - Reason string `json:"reason"` - } - - client := &http.Client{Timeout: 8 * time.Second} - tryFetch := func(source, reqURL string, parse func(body []byte) (CurrentIPInfo, error)) (CurrentIPInfo, error) { - req, err := http.NewRequest(http.MethodGet, reqURL, nil) - if err != nil { - return CurrentIPInfo{}, err - } - req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36") - req.Header.Set("Accept", "application/json") - - resp, err := client.Do(req) - if err != nil { - return CurrentIPInfo{}, err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return CurrentIPInfo{}, err - } - if resp.StatusCode != http.StatusOK { - return CurrentIPInfo{}, fmt.Errorf("%s returned status %d: %s", source, resp.StatusCode, previewResponseBody(body, 200)) - } - - info, err := parse(body) - if err != nil { - return CurrentIPInfo{}, err - } - info.Source = source - return info, nil - } - - info, err := tryFetch("ipwho.is", "https://ipwho.is/", func(body []byte) (CurrentIPInfo, error) { - var payload ipwhoisResponse - if err := json.Unmarshal(body, &payload); err != nil { - return CurrentIPInfo{}, err - } - if !payload.Success { - return CurrentIPInfo{}, fmt.Errorf("ipwho.is lookup failed: %s", strings.TrimSpace(payload.Message)) - } - if strings.TrimSpace(payload.IP) == "" || strings.TrimSpace(payload.Country) == "" { - return CurrentIPInfo{}, fmt.Errorf("ipwho.is returned incomplete IP data") - } - return CurrentIPInfo{ - IP: strings.TrimSpace(payload.IP), - Country: strings.TrimSpace(payload.Country), - CountryCode: strings.TrimSpace(payload.CountryCode), - }, nil - }) - if err == nil { - return info, nil - } - firstErr := err - - info, err = tryFetch("ipapi.co", "https://ipapi.co/json/", func(body []byte) (CurrentIPInfo, error) { - var payload ipapiResponse - if err := json.Unmarshal(body, &payload); err != nil { - return CurrentIPInfo{}, err - } - if payload.Error { - return CurrentIPInfo{}, fmt.Errorf("ipapi.co lookup failed: %s", strings.TrimSpace(payload.Reason)) - } - if strings.TrimSpace(payload.IP) == "" || strings.TrimSpace(payload.Country) == "" { - return CurrentIPInfo{}, fmt.Errorf("ipapi.co returned incomplete IP data") - } - return CurrentIPInfo{ - IP: strings.TrimSpace(payload.IP), - Country: strings.TrimSpace(payload.Country), - CountryCode: strings.TrimSpace(payload.CountryCode), - }, nil - }) - if err == nil { - return info, nil - } - - return CurrentIPInfo{}, fmt.Errorf("failed to detect public IP: %v; fallback failed: %v", firstErr, err) -} - -func (a *App) GetCurrentIPInfo() (string, error) { - info, err := fetchCurrentIPInfo() - if err != nil { - return "", err - } - - payload, err := json.Marshal(info) - if err != nil { - return "", err - } - - return string(payload), nil -} - -func (a *App) getFirstArtist(artistString string) string { - if artistString == "" { - return "" - } - delimiters := []string{", ", " & ", " feat. ", " ft. ", " featuring "} - for _, d := range delimiters { - if idx := strings.Index(strings.ToLower(artistString), d); idx != -1 { - return strings.TrimSpace(artistString[:idx]) - } - } - return artistString -} - -func (a *App) startup(ctx context.Context) { - a.ctx = ctx - - if err := backend.InitHistoryDB("SpotiFLAC"); err != nil { - fmt.Printf("Failed to init history DB: %v\n", err) - } - if err := backend.InitISRCCacheDB(); err != nil { - fmt.Printf("Failed to init ISRC cache DB: %v\n", err) - } - if err := backend.InitProviderPriorityDB(); err != nil { - fmt.Printf("Failed to init provider priority DB: %v\n", err) - } - if err := backend.CleanupLegacyTidalPublicAPIState(); err != nil { - fmt.Printf("Failed to clean legacy Tidal API cache: %v\n", err) - } - if err := backend.SanitizePersistedConfigSettings(); err != nil { - fmt.Printf("Failed to sanitize persisted config settings: %v\n", err) - } -} - -func (a *App) shutdown(ctx context.Context) { - backend.CloseHistoryDB() - backend.CloseISRCCacheDB() - backend.CloseProviderPriorityDB() -} - -type SpotifyMetadataRequest struct { - URL string `json:"url"` - Batch bool `json:"batch"` - Delay float64 `json:"delay"` - Timeout float64 `json:"timeout"` - Separator string `json:"separator,omitempty"` -} - -type DownloadRequest struct { - Service string `json:"service"` - Query string `json:"query,omitempty"` - TrackName string `json:"track_name,omitempty"` - ArtistName string `json:"artist_name,omitempty"` - AlbumName string `json:"album_name,omitempty"` - AlbumArtist string `json:"album_artist,omitempty"` - ReleaseDate string `json:"release_date,omitempty"` - CoverURL string `json:"cover_url,omitempty"` - TidalAPIURL string `json:"tidal_api_url,omitempty"` - OutputDir string `json:"output_dir,omitempty"` - AudioFormat string `json:"audio_format,omitempty"` - FilenameFormat string `json:"filename_format,omitempty"` - TrackNumber bool `json:"track_number,omitempty"` - Position int `json:"position,omitempty"` - UseAlbumTrackNumber bool `json:"use_album_track_number,omitempty"` - SpotifyID string `json:"spotify_id,omitempty"` - EmbedLyrics bool `json:"embed_lyrics,omitempty"` - EmbedMaxQualityCover bool `json:"embed_max_quality_cover,omitempty"` - ServiceURL string `json:"service_url,omitempty"` - Duration int `json:"duration,omitempty"` - ItemID string `json:"item_id,omitempty"` - SpotifyTrackNumber int `json:"spotify_track_number,omitempty"` - SpotifyDiscNumber int `json:"spotify_disc_number,omitempty"` - SpotifyTotalTracks int `json:"spotify_total_tracks,omitempty"` - SpotifyTotalDiscs int `json:"spotify_total_discs,omitempty"` - ISRC string `json:"isrc,omitempty"` - Copyright string `json:"copyright,omitempty"` - Publisher string `json:"publisher,omitempty"` - Composer string `json:"composer,omitempty"` - PlaylistName string `json:"playlist_name,omitempty"` - PlaylistOwner string `json:"playlist_owner,omitempty"` - AllowFallback bool `json:"allow_fallback"` - UseFirstArtistOnly bool `json:"use_first_artist_only,omitempty"` - UseSingleGenre bool `json:"use_single_genre,omitempty"` - EmbedGenre bool `json:"embed_genre,omitempty"` - Separator string `json:"separator,omitempty"` -} - -type DownloadResponse struct { - Success bool `json:"success"` - Message string `json:"message"` - File string `json:"file,omitempty"` - Error string `json:"error,omitempty"` - AlreadyExists bool `json:"already_exists,omitempty"` - ItemID string `json:"item_id,omitempty"` -} - -func cleanupInvalidDownloadArtifacts(paths ...string) { - seen := make(map[string]struct{}, len(paths)) - for _, path := range paths { - if path == "" { - continue - } - if _, ok := seen[path]; ok { - continue - } - seen[path] = struct{}{} - if err := os.Remove(path); err == nil { - fmt.Printf("Removed invalid download artifact: %s\n", path) - } - } -} - -func (a *App) GetStreamingURLs(spotifyTrackID string, region string) (string, error) { - if spotifyTrackID == "" { - return "", fmt.Errorf("spotify track ID is required") - } - - fmt.Printf("[GetStreamingURLs] Called for track ID: %s, Region: %s\n", spotifyTrackID, region) - client := backend.NewSongLinkClient() - urls, err := client.GetAllURLsFromSpotify(spotifyTrackID, region) - if err != nil { - return "", err - } - - jsonData, err := json.Marshal(urls) - if err != nil { - return "", fmt.Errorf("failed to encode response: %v", err) - } - - return string(jsonData), nil -} - -func (a *App) GetSpotifyMetadata(req SpotifyMetadataRequest) (string, error) { - if req.URL == "" { - return "", fmt.Errorf("URL parameter is required") - } - - if req.Delay == 0 { - req.Delay = 1.0 - } - if req.Timeout == 0 { - req.Timeout = 300.0 - } - - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(req.Timeout*float64(time.Second))) - defer cancel() - - settings, err := a.LoadSettings() - separator := req.Separator - if separator == "" { - separator = ", " - if err == nil && settings != nil { - if sep, ok := settings["separator"].(string); ok { - if sep == "semicolon" { - separator = "; " - } else if sep == "comma" { - separator = ", " - } - } - } - } - - data, err := backend.GetFilteredSpotifyData(ctx, req.URL, req.Batch, time.Duration(req.Delay*float64(time.Second)), separator, func(tracks interface{}) { - runtime.EventsEmit(a.ctx, "metadata-stream", tracks) - }) - if err != nil { - return "", fmt.Errorf("failed to fetch metadata: %v", err) - } - - jsonData, err := json.MarshalIndent(data, "", " ") - if err != nil { - return "", fmt.Errorf("failed to encode response: %v", err) - } - - return string(jsonData), nil -} - -type SpotifySearchRequest struct { - Query string `json:"query"` - Limit int `json:"limit"` -} - -func (a *App) SearchSpotify(req SpotifySearchRequest) (*backend.SearchResponse, error) { - if req.Query == "" { - return nil, fmt.Errorf("search query is required") - } - - if req.Limit <= 0 { - req.Limit = 10 - } - - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - return backend.SearchSpotify(ctx, req.Query, req.Limit) -} - -type SpotifySearchByTypeRequest struct { - Query string `json:"query"` - SearchType string `json:"search_type"` - Limit int `json:"limit"` - Offset int `json:"offset"` -} - -func (a *App) SearchSpotifyByType(req SpotifySearchByTypeRequest) ([]backend.SearchResult, error) { - if req.Query == "" { - return nil, fmt.Errorf("search query is required") - } - - if req.SearchType == "" { - return nil, fmt.Errorf("search type is required") - } - - if req.Limit <= 0 { - req.Limit = 50 - } - - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - return backend.SearchSpotifyByType(ctx, req.Query, req.SearchType, req.Limit, req.Offset) -} - -func (a *App) DownloadTrack(req DownloadRequest) (DownloadResponse, error) { - - if req.Service == "qobuz" && req.SpotifyID == "" { - return DownloadResponse{ - Success: false, - Error: "Spotify ID is required for Qobuz", - }, fmt.Errorf("spotify ID is required for Qobuz") - } - - if req.Service == "" { - req.Service = "tidal" - } - - if req.OutputDir == "" { - req.OutputDir = "." - } else { - - if req.PlaylistName != "" { - sanitizedPlaylist := backend.SanitizeFilename(req.PlaylistName) - req.OutputDir = filepath.Join(req.OutputDir, sanitizedPlaylist) - } - - req.OutputDir = backend.SanitizeFolderPath(req.OutputDir) - } - - if req.AudioFormat == "" { - req.AudioFormat = "LOSSLESS" - } - - var err error - var filename string - - if req.FilenameFormat == "" { - req.FilenameFormat = "title-artist" - } - shouldResolveISRC := strings.Contains(req.FilenameFormat, "{isrc}") || backend.GetExistingFileCheckModeSetting() == "isrc" - if req.ISRC == "" && shouldResolveISRC && req.SpotifyID != "" { - req.ISRC = backend.ResolveTrackISRC(req.SpotifyID) - } - - itemID := req.ItemID - if itemID == "" { - - if req.SpotifyID != "" { - itemID = fmt.Sprintf("%s-%d", req.SpotifyID, time.Now().UnixNano()) - } else { - itemID = fmt.Sprintf("%s-%s-%d", req.TrackName, req.ArtistName, time.Now().UnixNano()) - } - - backend.AddToQueue(itemID, req.TrackName, req.ArtistName, req.AlbumName, req.SpotifyID) - } - - backend.SetDownloading(true) - backend.StartDownloadItem(itemID) - defer backend.SetDownloading(false) - - spotifyURL := "" - if req.SpotifyID != "" { - spotifyURL = fmt.Sprintf("https://open.spotify.com/track/%s", req.SpotifyID) - } - - metadataSeparator := req.Separator - if metadataSeparator == "" { - metadataSeparator = ", " - metadataSettings, _ := a.LoadSettings() - if metadataSettings != nil { - if sep, ok := metadataSettings["separator"].(string); ok { - if sep == "semicolon" { - metadataSeparator = "; " - } else if sep == "comma" { - metadataSeparator = ", " - } - } - } - } - - if req.SpotifyID != "" && (req.Copyright == "" || req.Publisher == "" || req.Composer == "" || req.SpotifyTotalDiscs == 0 || req.ReleaseDate == "" || req.SpotifyTotalTracks == 0 || req.SpotifyTrackNumber == 0) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - trackURL := fmt.Sprintf("https://open.spotify.com/track/%s", req.SpotifyID) - trackData, err := backend.GetFilteredSpotifyData(ctx, trackURL, false, 0, metadataSeparator, nil) - if err == nil { - - var trackResp struct { - Track struct { - Copyright string `json:"copyright"` - Publisher string `json:"publisher"` - Composer string `json:"composer"` - TotalDiscs int `json:"total_discs"` - TotalTracks int `json:"total_tracks"` - TrackNumber int `json:"track_number"` - ReleaseDate string `json:"release_date"` - } `json:"track"` - } - if jsonData, jsonErr := json.Marshal(trackData); jsonErr == nil { - if json.Unmarshal(jsonData, &trackResp) == nil { - - if req.Copyright == "" && trackResp.Track.Copyright != "" { - req.Copyright = trackResp.Track.Copyright - } - if req.Publisher == "" && trackResp.Track.Publisher != "" { - req.Publisher = trackResp.Track.Publisher - } - if req.Composer == "" && trackResp.Track.Composer != "" { - req.Composer = trackResp.Track.Composer - } - if req.SpotifyTotalDiscs == 0 && trackResp.Track.TotalDiscs > 0 { - req.SpotifyTotalDiscs = trackResp.Track.TotalDiscs - } - if req.SpotifyTotalTracks == 0 && trackResp.Track.TotalTracks > 0 { - req.SpotifyTotalTracks = trackResp.Track.TotalTracks - } - if req.SpotifyTrackNumber == 0 && trackResp.Track.TrackNumber > 0 { - req.SpotifyTrackNumber = trackResp.Track.TrackNumber - } - if req.ReleaseDate == "" && trackResp.Track.ReleaseDate != "" { - req.ReleaseDate = trackResp.Track.ReleaseDate - } - } - } - } - } - - if req.TrackName != "" && req.ArtistName != "" { - expectedFilename := backend.BuildExpectedFilename(req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, req.FilenameFormat, req.PlaylistName, req.PlaylistOwner, req.TrackNumber, req.Position, req.SpotifyDiscNumber, req.UseAlbumTrackNumber, req.ISRC) - expectedPath := filepath.Join(req.OutputDir, expectedFilename) - - if !backend.GetRedownloadWithSuffixSetting() { - if fileInfo, err := os.Stat(expectedPath); err == nil && fileInfo.Size() > 100*1024 { - - backend.SkipDownloadItem(itemID, expectedPath) - return DownloadResponse{ - Success: true, - Message: "File already exists", - File: expectedPath, - AlreadyExists: true, - ItemID: itemID, - }, nil - } - } - } - - lyricsChan := make(chan string, 1) - isrcChan := make(chan string, 1) - - if req.SpotifyID != "" { - if req.EmbedLyrics { - go func() { - client := backend.NewLyricsClient() - resp, _, err := client.FetchLyricsAllSources(req.SpotifyID, req.TrackName, req.ArtistName, req.AlbumName, req.Duration) - if err == nil && resp != nil && len(resp.Lines) > 0 { - lrc := client.ConvertToLRC(resp, req.TrackName, req.ArtistName) - lyricsChan <- lrc - } else { - lyricsChan <- "" - } - }() - } else { - close(lyricsChan) - } - - if req.Service == "qobuz" { - go func() { - client := backend.NewSongLinkClient() - isrc, err := client.GetISRCDirect(req.SpotifyID) - if err != nil { - fmt.Printf("Warning: failed to resolve ISRC for Qobuz: %v\n", err) - } - isrcChan <- isrc - }() - } else { - close(isrcChan) - } - } else { - close(lyricsChan) - close(isrcChan) - } - - switch req.Service { - case "amazon": - - downloader := backend.NewAmazonDownloader() - if req.ServiceURL != "" { - filename, err = downloader.DownloadByURL(req.ServiceURL, req.OutputDir, req.AudioFormat, req.FilenameFormat, req.PlaylistName, req.PlaylistOwner, req.TrackNumber, req.Position, req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, req.CoverURL, req.SpotifyTrackNumber, req.SpotifyDiscNumber, req.SpotifyTotalTracks, req.EmbedMaxQualityCover, req.SpotifyTotalDiscs, req.Copyright, req.Publisher, req.Composer, metadataSeparator, req.ISRC, spotifyURL, req.UseFirstArtistOnly, req.UseSingleGenre, req.EmbedGenre) - } else { - filename, err = downloader.DownloadBySpotifyID(req.SpotifyID, req.OutputDir, req.AudioFormat, req.FilenameFormat, req.PlaylistName, req.PlaylistOwner, req.TrackNumber, req.Position, req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, req.CoverURL, req.SpotifyTrackNumber, req.SpotifyDiscNumber, req.SpotifyTotalTracks, req.EmbedMaxQualityCover, req.SpotifyTotalDiscs, req.Copyright, req.Publisher, req.Composer, metadataSeparator, req.ISRC, spotifyURL, req.UseFirstArtistOnly, req.UseSingleGenre, req.EmbedGenre) - } - - case "tidal": - if !strings.HasPrefix(strings.TrimRight(strings.TrimSpace(req.TidalAPIURL), "/"), "https://") { - err = fmt.Errorf("a configured HTTPS Tidal instance is required") - break - } - downloader := backend.NewTidalDownloader(req.TidalAPIURL) - if req.ServiceURL != "" { - filename, err = downloader.DownloadByURL(req.ServiceURL, req.OutputDir, req.AudioFormat, req.FilenameFormat, req.TrackNumber, req.Position, req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, req.UseAlbumTrackNumber, req.CoverURL, req.EmbedMaxQualityCover, req.SpotifyTrackNumber, req.SpotifyDiscNumber, req.SpotifyTotalTracks, req.SpotifyTotalDiscs, req.Copyright, req.Publisher, req.Composer, metadataSeparator, req.ISRC, spotifyURL, req.AllowFallback, req.UseFirstArtistOnly, req.UseSingleGenre, req.EmbedGenre) - } else { - filename, err = downloader.Download(req.SpotifyID, req.OutputDir, req.AudioFormat, req.FilenameFormat, req.TrackNumber, req.Position, req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, req.UseAlbumTrackNumber, req.CoverURL, req.EmbedMaxQualityCover, req.SpotifyTrackNumber, req.SpotifyDiscNumber, req.SpotifyTotalTracks, req.SpotifyTotalDiscs, req.Copyright, req.Publisher, req.Composer, metadataSeparator, req.ISRC, spotifyURL, req.AllowFallback, req.UseFirstArtistOnly, req.UseSingleGenre, req.EmbedGenre) - } - - case "qobuz": - - isrc := strings.TrimSpace(req.ISRC) - if isrc == "" { - fmt.Println("Waiting for ISRC (Qobuz dependency)...") - isrc = <-isrcChan - } - downloader := backend.NewQobuzDownloader() - quality := req.AudioFormat - if quality == "" { - quality = "6" - } - filename, err = downloader.DownloadTrackWithISRC(isrc, req.OutputDir, quality, req.FilenameFormat, req.TrackNumber, req.Position, req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, req.UseAlbumTrackNumber, req.CoverURL, req.EmbedMaxQualityCover, req.SpotifyTrackNumber, req.SpotifyDiscNumber, req.SpotifyTotalTracks, req.SpotifyTotalDiscs, req.Copyright, req.Publisher, req.Composer, metadataSeparator, spotifyURL, req.AllowFallback, req.UseFirstArtistOnly, req.UseSingleGenre, req.EmbedGenre) - - default: - return DownloadResponse{ - Success: false, - Error: fmt.Sprintf("Unknown service: %s", req.Service), - }, fmt.Errorf("unknown service: %s", req.Service) - } - - if err != nil { - backend.FailDownloadItem(itemID, fmt.Sprintf("Download failed: %v", err)) - - if filename != "" && !strings.HasPrefix(filename, "EXISTS:") { - - if _, statErr := os.Stat(filename); statErr == nil { - fmt.Printf("Removing corrupted/partial file after failed download: %s\n", filename) - if removeErr := os.Remove(filename); removeErr != nil { - fmt.Printf("Warning: Failed to remove corrupted file %s: %v\n", filename, removeErr) - } - } - } - - return DownloadResponse{ - Success: false, - Error: fmt.Sprintf("Download failed: %v", err), - ItemID: itemID, - }, err - } - - alreadyExists := false - if strings.HasPrefix(filename, "EXISTS:") { - alreadyExists = true - filename = strings.TrimPrefix(filename, "EXISTS:") - } - - if !alreadyExists { - validated, validationErr := backend.ValidateDownloadedTrackDuration(filename, req.Duration) - if validationErr != nil { - cleanupInvalidDownloadArtifacts(filename) - errorMessage := validationErr.Error() - backend.FailDownloadItem(itemID, errorMessage) - return DownloadResponse{ - Success: false, - Error: errorMessage, - ItemID: itemID, - }, errors.New(errorMessage) - } - if !validated { - fmt.Printf("[DownloadValidation] Skipped duration validation for %s (expected=%ds)\n", filename, req.Duration) - } - } - - if !alreadyExists && req.SpotifyID != "" && req.EmbedLyrics && (strings.HasSuffix(filename, ".flac") || strings.HasSuffix(filename, ".mp3") || strings.HasSuffix(filename, ".m4a")) { - fmt.Printf("\nWaiting for lyrics fetch to complete...\n") - lyrics := <-lyricsChan - if lyrics != "" { - fmt.Printf("\n--- Full LRC Content ---\n") - fmt.Println(lyrics) - fmt.Printf("--- End LRC Content ---\n\n") - - fmt.Printf("Embedding into: %s\n", filename) - - if err := backend.EmbedLyricsOnlyUniversal(filename, lyrics); err != nil { - fmt.Printf("Failed to embed lyrics: %v\n", err) - } else { - fmt.Printf("Lyrics embedded successfully!\n") - } - } else { - fmt.Println("No lyrics found to embed.") - } - } else { - - select { - case <-lyricsChan: - default: - } - } - - message := "Download completed successfully" - if alreadyExists { - message = "File already exists" - backend.SkipDownloadItem(itemID, filename) - } else { - if strings.EqualFold(filepath.Ext(filename), ".flac") && req.CoverURL != "" { - coverClient := backend.NewCoverClient() - if iconErr := coverClient.ApplyMacOSFLACFileIcon(filename, req.CoverURL, 256, req.EmbedMaxQualityCover); iconErr != nil { - fmt.Printf("Warning: failed to set macOS FLAC file icon: %v\n", iconErr) - } else { - fmt.Printf("macOS FLAC file icon set: %s\n", filename) - } - } - - if fileInfo, statErr := os.Stat(filename); statErr == nil { - finalSize := float64(fileInfo.Size()) / (1024 * 1024) - backend.CompleteDownloadItem(itemID, filename, finalSize) - } else { - - backend.CompleteDownloadItem(itemID, filename, 0) - } - - historySource := req.Service - - go func(fPath, track, artist, album, sID, cover, format, source string) { - time.Sleep(2 * time.Second) - - quality := "Unknown" - durationStr := "0:00" - - meta, err := backend.GetTrackMetadata(fPath) - if err == nil { - if meta.Bitrate > 0 { - quality = fmt.Sprintf("%dkbps/%.1fkHz", meta.Bitrate/1000, float64(meta.SampleRate)/1000.0) - } else if meta.SampleRate > 0 { - quality = fmt.Sprintf("%.1fkHz", float64(meta.SampleRate)/1000.0) - } - d := int(meta.Duration) - durationStr = fmt.Sprintf("%d:%02d", d/60, d%60) - } else { - fmt.Printf("[History] Failed to get metadata for %s: %v\n", fPath, err) - } - - item := backend.HistoryItem{ - SpotifyID: sID, - Title: track, - Artists: artist, - Album: album, - DurationStr: durationStr, - CoverURL: cover, - Quality: quality, - Path: fPath, - Source: source, - } - - item.Format = strings.ToUpper(strings.TrimSpace(format)) - - if ext := filepath.Ext(fPath); len(ext) > 1 { - item.Format = strings.ToUpper(ext[1:]) - } - - switch item.Format { - case "6", "7", "27", "LOSSLESS", "HI_RES", "HI_RES_LOSSLESS": - item.Format = "FLAC" - case "ALAC", "APPLE", "ATMOS", "M4A-AAC", "M4A-ALAC": - item.Format = "M4A" - } - - backend.AddHistoryItem(item, "SpotiFLAC") - }(filename, req.TrackName, req.ArtistName, req.AlbumName, req.SpotifyID, req.CoverURL, req.AudioFormat, historySource) - } - - return DownloadResponse{ - Success: true, - Message: message, - File: filename, - AlreadyExists: alreadyExists, - ItemID: itemID, - }, nil -} - -func (a *App) OpenFolder(path string) error { - if path == "" { - return fmt.Errorf("path is required") - } - - err := backend.OpenFolderInExplorer(path) - if err != nil { - return fmt.Errorf("failed to open folder: %v", err) - } - - return nil -} - -func (a *App) OpenConfigFolder() error { - configDir, err := backend.EnsureAppDir() - if err != nil { - return fmt.Errorf("failed to create config directory: %v", err) - } - return backend.OpenFolderInExplorer(configDir) -} - -func (a *App) SelectFolder(defaultPath string) (string, error) { - return backend.SelectFolderDialog(a.ctx, defaultPath) -} - -func (a *App) SelectFile() (string, error) { - return backend.SelectFileDialog(a.ctx) -} - -func (a *App) GetDefaults() map[string]string { - return map[string]string{ - "downloadPath": backend.GetDefaultMusicPath(), - } -} - -func (a *App) GetDownloadProgress() backend.ProgressInfo { - return backend.GetDownloadProgress() -} - -func (a *App) GetDownloadQueue() backend.DownloadQueueInfo { - return backend.GetDownloadQueue() -} - -func (a *App) ClearCompletedDownloads() { - backend.ClearDownloadQueue() -} - -func (a *App) ClearAllDownloads() { - backend.ClearAllDownloads() -} - -func (a *App) AddToDownloadQueue(spotifyID, trackName, artistName, albumName string) string { - itemID := fmt.Sprintf("%s-%d", spotifyID, time.Now().UnixNano()) - backend.AddToQueue(itemID, trackName, artistName, albumName, "") - return itemID -} - -func (a *App) MarkDownloadItemFailed(itemID, errorMsg string) { - backend.FailDownloadItem(itemID, errorMsg) -} - -func (a *App) CancelAllQueuedItems() { - backend.CancelAllQueuedItems() -} - -func (a *App) ExportFailedDownloads() (string, error) { - queueInfo := backend.GetDownloadQueue() - var failedItems []string - - hasFailed := false - for _, item := range queueInfo.Queue { - if item.Status == backend.StatusFailed { - hasFailed = true - break - } - } - - if !hasFailed { - return "No failed downloads to export.", nil - } - - failedItems = append(failedItems, fmt.Sprintf("Failed Downloads Report - %s", time.Now().Format("2006-01-02 15:04:05"))) - failedItems = append(failedItems, strings.Repeat("-", 50)) - failedItems = append(failedItems, "") - - count := 0 - for _, item := range queueInfo.Queue { - if item.Status == backend.StatusFailed { - count++ - line := fmt.Sprintf("%d. %s - %s", count, item.TrackName, item.ArtistName) - if item.AlbumName != "" { - line += fmt.Sprintf(" (%s)", item.AlbumName) - } - failedItems = append(failedItems, line) - failedItems = append(failedItems, fmt.Sprintf(" Error: %s", item.ErrorMessage)) - - if item.SpotifyID != "" { - failedItems = append(failedItems, fmt.Sprintf(" ID: %s", item.SpotifyID)) - failedItems = append(failedItems, fmt.Sprintf(" URL: https://open.spotify.com/track/%s", item.SpotifyID)) - } - failedItems = append(failedItems, "") - } - } - - content := strings.Join(failedItems, "\n") - defaultFilename := fmt.Sprintf("SpotiFLAC_%s_Failed.txt", time.Now().Format("20060102_150405")) - - path, err := runtime.SaveFileDialog(a.ctx, runtime.SaveDialogOptions{ - DefaultFilename: defaultFilename, - Title: "Export Failed Downloads", - Filters: []runtime.FileFilter{ - { - DisplayName: "Text Files (*.txt)", - Pattern: "*.txt", - }, - }, - }) - - if err != nil { - return "", fmt.Errorf("failed to open save dialog: %v", err) - } - - if path == "" { - return "Export cancelled", nil - } - - if err := os.WriteFile(path, []byte(content), 0644); err != nil { - return "", fmt.Errorf("failed to write file: %v", err) - } - - return fmt.Sprintf("Successfully exported %d failed downloads to %s", count, path), nil -} - -func (a *App) CheckAPIStatus(apiType string, apiURL string) bool { - isOnline, err := runWithTimeout(checkOperationTimeout, func() (bool, error) { - switch apiType { - case "tidal": - return checkGroupedAPIStatus("tidal", buildTidalStatusCheckURLs(apiURL)), nil - case "qobuz", "qbz": - return checkGroupedAPIStatus("qobuz", buildQobuzStatusCheckURLs(apiURL)), nil - case "amazon": - return checkGroupedAPIStatus("amazon", buildAmazonStatusCheckURLs(apiURL)), nil - case "lrclib": - return checkGroupedAPIStatus("lrclib", buildLRCLIBStatusCheckURLs(apiURL)), nil - case "musicbrainz": - return checkGroupedAPIStatus("musicbrainz", buildMusicBrainzStatusCheckURLs(apiURL)), nil - default: - return checkGroupedAPIStatus(apiType, []string{strings.TrimSpace(apiURL)}), nil - } - }) - if err != nil { - if apiType == "musicbrainz" { - backend.SetMusicBrainzStatusCheckResult(false) - } - fmt.Printf("CheckAPIStatus timeout/error for %s (%s): %v\n", apiType, apiURL, err) - return false - } - - if apiType == "musicbrainz" { - backend.SetMusicBrainzStatusCheckResult(isOnline) - } - - return isOnline -} - -func (a *App) CheckAPIStatusReport(apiType string, apiURL string) APIStatusReport { - report, err := runWithTimeout(checkOperationTimeout, func() (APIStatusReport, error) { - switch apiType { - case "tidal": - return buildGroupedAPIStatusReport("tidal", buildTidalStatusCheckURLs(apiURL), false), nil - case "qobuz", "qbz": - return buildGroupedAPIStatusReport("qobuz", buildQobuzStatusCheckURLs(apiURL), false), nil - case "amazon": - return buildGroupedAPIStatusReport("amazon", buildAmazonStatusCheckURLs(apiURL), false), nil - case "lrclib": - return buildGroupedAPIStatusReport("lrclib", buildLRCLIBStatusCheckURLs(apiURL), false), nil - case "musicbrainz": - return buildGroupedAPIStatusReport("musicbrainz", buildMusicBrainzStatusCheckURLs(apiURL), false), nil - default: - return buildGroupedAPIStatusReport(apiType, []string{strings.TrimSpace(apiURL)}, false), nil - } - }) - if err != nil { - return APIStatusReport{ - Type: apiType, - Online: false, - RequireAll: apiType == "qobuz" || apiType == "qbz", - Details: []APIStatusTargetResult{{ - Target: strings.TrimSpace(apiURL), - Label: describeAPIStatusTarget(apiType, apiURL), - Online: false, - Message: err.Error(), - }}, - } - } - return report -} - -func (a *App) CheckCustomTidalAPI(apiURL string) bool { - type tidalProbeResponse struct { - Version string `json:"version"` - Data struct { - TrackID int64 `json:"trackId"` - AssetPresentation string `json:"assetPresentation"` - ManifestMimeType string `json:"manifestMimeType"` - Manifest string `json:"manifest"` - } `json:"data"` - } - type tidalLegacyResponse struct { - OriginalTrackURL string `json:"OriginalTrackUrl"` - } - - apiURL = strings.TrimRight(strings.TrimSpace(apiURL), "/") - if apiURL == "" { - return false - } - - const probeTrackID int64 = 441821360 - probeURL := fmt.Sprintf("%s/track/?id=%d&quality=LOSSLESS", apiURL, probeTrackID) - - req, err := http.NewRequest(http.MethodGet, probeURL, nil) - if err != nil { - fmt.Printf("[CheckCustomTidalAPI] Failed to create request for %s: %v\n", apiURL, err) - return false - } - req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36") - req.Header.Set("Accept", "application/json") - - client := &http.Client{Timeout: 12 * time.Second} - resp, err := client.Do(req) - if err != nil { - fmt.Printf("[CheckCustomTidalAPI] Probe request failed for %s: %v\n", apiURL, err) - return false - } - defer resp.Body.Close() - - body, err := io.ReadAll(io.LimitReader(resp.Body, 64*1024)) - if err != nil { - fmt.Printf("[CheckCustomTidalAPI] Failed to read probe response for %s: %v\n", apiURL, err) - return false - } - if resp.StatusCode != http.StatusOK { - fmt.Printf("[CheckCustomTidalAPI] Probe returned status %d for %s: %s\n", resp.StatusCode, apiURL, previewResponseBody(body, 200)) - return false - } - - var probe tidalProbeResponse - if err := json.Unmarshal(body, &probe); err == nil { - assetPresentation := strings.ToUpper(strings.TrimSpace(probe.Data.AssetPresentation)) - switch assetPresentation { - case "FULL": - if strings.TrimSpace(probe.Data.Manifest) != "" { - fmt.Printf("[CheckCustomTidalAPI] Tidal API is ONLINE for %s (assetPresentation=%s)\n", apiURL, assetPresentation) - return true - } - fmt.Printf("[CheckCustomTidalAPI] Probe returned FULL without manifest for %s\n", apiURL) - return false - case "PREVIEW": - fmt.Printf("[CheckCustomTidalAPI] Probe returned PREVIEW for %s\n", apiURL) - return false - case "": - - default: - fmt.Printf("[CheckCustomTidalAPI] Probe returned unsupported assetPresentation=%s for %s\n", assetPresentation, apiURL) - return false - } - } - - var legacy []tidalLegacyResponse - if err := json.Unmarshal(body, &legacy); err == nil { - for _, item := range legacy { - if strings.TrimSpace(item.OriginalTrackURL) != "" { - fmt.Printf("[CheckCustomTidalAPI] Tidal API is ONLINE for %s (legacy response)\n", apiURL) - return true - } - } - } - - fmt.Printf("[CheckCustomTidalAPI] Probe response was unusable for %s: %s\n", apiURL, previewResponseBody(body, 200)) - return false -} - -func buildTidalStatusCheckURLs(apiURL string) []string { - apiURL = strings.TrimRight(strings.TrimSpace(apiURL), "/") - if apiURL == "" { - return nil - } - return []string{fmt.Sprintf("%s/track/?id=441821360&quality=HI_RES_LOSSLESS", apiURL)} -} - -func buildQobuzStatusCheckURLs(apiURL string) []string { - if trimmed := strings.TrimSpace(apiURL); trimmed != "" { - return []string{trimmed} - } - - return backend.GetQobuzDownloadProviderURLs() -} - -func buildAmazonStatusCheckURLs(apiURL string) []string { - baseURL := strings.TrimRight(strings.TrimSpace(apiURL), "/") - if baseURL == "" { - baseURL = backend.GetAmazonMusicAPIBaseURL() - } - return []string{fmt.Sprintf("%s/status", baseURL)} -} - -func buildLRCLIBStatusCheckURLs(apiURL string) []string { - baseURL := strings.TrimRight(strings.TrimSpace(apiURL), "/") - if baseURL == "" { - baseURL = "https://lrclib.net" - } - return []string{fmt.Sprintf("%s/api/search?artist_name=Adele&track_name=Hello", baseURL)} -} - -func buildMusicBrainzStatusCheckURLs(apiURL string) []string { - baseURL := strings.TrimRight(strings.TrimSpace(apiURL), "/") - if baseURL == "" { - baseURL = "https://musicbrainz.org" - } - return []string{fmt.Sprintf("%s/ws/2/recording?query=%s&fmt=json&limit=1", baseURL, url.QueryEscape(`recording:"Hello" AND artist:"Adele"`))} -} - -func checkGroupedAPIStatus(apiType string, checkURLs []string) bool { - filtered := make([]string, 0, len(checkURLs)) - for _, rawURL := range checkURLs { - url := strings.TrimSpace(rawURL) - if url == "" { - continue - } - filtered = append(filtered, url) - } - - if len(filtered) == 0 { - return false - } - - results := make(chan bool, len(filtered)) - var wg sync.WaitGroup - - for _, checkURL := range filtered { - wg.Add(1) - go func(target string) { - defer wg.Done() - results <- checkSingleAPIStatus(apiType, target) - }(checkURL) - } - - go func() { - wg.Wait() - close(results) - }() - - for online := range results { - if online { - return true - } - } - - return false -} - -func buildGroupedAPIStatusReport(apiType string, checkURLs []string, requireAll bool) APIStatusReport { - filtered := make([]string, 0, len(checkURLs)) - for _, rawURL := range checkURLs { - target := strings.TrimSpace(rawURL) - if target == "" { - continue - } - filtered = append(filtered, target) - } - - report := APIStatusReport{ - Type: apiType, - Online: !requireAll, - RequireAll: requireAll, - Details: make([]APIStatusTargetResult, len(filtered)), - } - - if len(filtered) == 0 { - report.Online = false - return report - } - - var wg sync.WaitGroup - for index, target := range filtered { - wg.Add(1) - go func(idx int, rawTarget string) { - defer wg.Done() - report.Details[idx] = checkSingleAPIStatusDetailed(apiType, rawTarget) - }(index, target) - } - wg.Wait() - - if requireAll { - report.Online = true - for _, detail := range report.Details { - if !detail.Online { - report.Online = false - break - } - } - } else { - report.Online = false - for _, detail := range report.Details { - if detail.Online { - report.Online = true - break - } - } - } - - return report -} - -func checkAllGroupedAPIStatus(apiType string, checkURLs []string) bool { - filtered := make([]string, 0, len(checkURLs)) - for _, rawURL := range checkURLs { - url := strings.TrimSpace(rawURL) - if url == "" { - continue - } - filtered = append(filtered, url) - } - - if len(filtered) == 0 { - return false - } - - results := make(chan bool, len(filtered)) - var wg sync.WaitGroup - - for _, checkURL := range filtered { - wg.Add(1) - go func(target string) { - defer wg.Done() - results <- checkSingleAPIStatus(apiType, target) - }(checkURL) - } - - go func() { - wg.Wait() - close(results) - }() - - for online := range results { - if !online { - return false - } - } - - return true -} - -func describeAPIStatusTarget(apiType string, checkURL string) string { - trimmedType := strings.TrimSpace(strings.ToLower(apiType)) - trimmedURL := strings.TrimSpace(checkURL) - - if trimmedType == "qobuz" || trimmedType == "qbz" { - switch { - case backend.IsQobuzWJHEProviderURL(trimmedURL): - return "WJHE" - case backend.IsQobuzMusicDLProviderURL(trimmedURL): - return "MusicDL" - case backend.IsQobuzGDStudioProviderURL(trimmedURL): - parsed, err := url.Parse(trimmedURL) - if err == nil { - host := strings.ToLower(strings.TrimSpace(parsed.Host)) - switch { - case strings.Contains(host, "xyz"): - return "GDStudio XYZ" - case strings.Contains(host, "org"): - return "GDStudio ORG" - } - } - return "GDStudio" - } - } - - if trimmedURL != "" { - if parsed, err := url.Parse(trimmedURL); err == nil && strings.TrimSpace(parsed.Host) != "" { - return strings.TrimSpace(parsed.Host) - } - } - - if trimmedType == "" { - return "Unknown" - } - - return strings.ToUpper(trimmedType) -} - -func checkSingleAPIStatusDetailed(apiType string, checkURL string) APIStatusTargetResult { - result := APIStatusTargetResult{ - Target: strings.TrimSpace(checkURL), - Label: describeAPIStatusTarget(apiType, checkURL), - } - - client := &http.Client{Timeout: 4 * time.Second} - trimmedType := strings.TrimSpace(strings.ToLower(apiType)) - - if trimmedType == "qobuz" || trimmedType == "qbz" { - var err error - switch { - case backend.IsQobuzWJHEProviderURL(checkURL): - err = backend.CheckQobuzWJHEStatusDetailed(client) - case backend.IsQobuzMusicDLProviderURL(checkURL): - err = backend.CheckQobuzMusicDLStatusDetailed(client) - case backend.IsQobuzGDStudioProviderURL(checkURL): - err = backend.CheckQobuzGDStudioAPIStatusDetailed(client, checkURL) - default: - err = fmt.Errorf("unknown qobuz provider url: %s", strings.TrimSpace(checkURL)) - } - - if err != nil { - result.Message = err.Error() - return result - } - - result.Online = true - result.Message = "stream URL resolved" - return result - } - - req, err := backend.NewRequestWithDefaultHeaders(http.MethodGet, checkURL, nil) - if err != nil { - result.Message = fmt.Sprintf("failed to create request: %v", err) - return result - } - - resp, err := client.Do(req) - if err != nil { - result.Message = fmt.Sprintf("request failed: %v", err) - return result - } - defer resp.Body.Close() - - body, err := io.ReadAll(io.LimitReader(resp.Body, 2048)) - if err != nil { - result.Message = fmt.Sprintf("failed to read response: %v", err) - return result - } - - switch trimmedType { - case "amazon": - if resp.StatusCode == http.StatusOK && strings.Contains(string(body), `"amazonMusic":"up"`) { - result.Online = true - result.Message = `amazonMusic="up"` - return result - } - if resp.StatusCode != http.StatusOK { - result.Message = fmt.Sprintf("HTTP %d: %s", resp.StatusCode, previewResponseBody(body, 160)) - return result - } - result.Message = `amazonMusic was not reported as "up"` - return result - default: - if resp.StatusCode == http.StatusOK { - result.Online = true - result.Message = fmt.Sprintf("HTTP %d", resp.StatusCode) - return result - } - result.Message = fmt.Sprintf("HTTP %d: %s", resp.StatusCode, previewResponseBody(body, 160)) - return result - } -} - -func checkSingleAPIStatus(apiType string, checkURL string) bool { - client := &http.Client{Timeout: 4 * time.Second} - if apiType == "qobuz" || apiType == "qbz" { - switch { - case backend.IsQobuzWJHEProviderURL(checkURL): - return backend.CheckQobuzWJHEStatus(client) - case backend.IsQobuzMusicDLProviderURL(checkURL): - return backend.CheckQobuzMusicDLStatus(client) - case backend.IsQobuzGDStudioProviderURL(checkURL): - return backend.CheckQobuzGDStudioAPIStatus(client, checkURL) - } - } - - req, err := backend.NewRequestWithDefaultHeaders(http.MethodGet, checkURL, nil) - if err != nil { - return false - } - - resp, err := client.Do(req) - if err != nil { - return false - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return false - } - - statusCode := resp.StatusCode - switch apiType { - case "amazon": - return statusCode == http.StatusOK && strings.Contains(string(body), `"amazonMusic":"up"`) - case "qobuz", "qbz": - return statusCode == http.StatusOK && containsStreamingURL(body) - case "lrclib": - return statusCode == http.StatusOK && containsLRCLIBResults(body) - case "musicbrainz": - return statusCode == http.StatusOK && containsMusicBrainzResults(body) - default: - return statusCode == http.StatusOK - } -} - -func (a *App) Quit() { - - panic("quit") -} - -func (a *App) GetDownloadHistory() ([]backend.HistoryItem, error) { - return backend.GetHistoryItems("SpotiFLAC") -} - -func (a *App) ClearDownloadHistory() error { - return backend.ClearHistory("SpotiFLAC") -} - -func (a *App) DeleteDownloadHistoryItem(id string) error { - return backend.DeleteHistoryItem(id, "SpotiFLAC") -} - -func (a *App) GetFetchHistory() ([]backend.FetchHistoryItem, error) { - return backend.GetFetchHistoryItems("SpotiFLAC") -} - -func (a *App) AddFetchHistory(item backend.FetchHistoryItem) error { - return backend.AddFetchHistoryItem(item, "SpotiFLAC") -} - -func (a *App) ClearFetchHistory() error { - return backend.ClearFetchHistory("SpotiFLAC") -} - -func (a *App) DeleteFetchHistoryItem(id string) error { - return backend.DeleteFetchHistoryItem(id, "SpotiFLAC") -} - -func (a *App) ClearFetchHistoryByType(itemType string) error { - return backend.ClearFetchHistoryByType(itemType, "SpotiFLAC") -} - -func (a *App) GetRecentFetches() (string, error) { - items, err := backend.LoadRecentFetches() - if err != nil { - return "", err - } - - data, err := json.Marshal(items) - if err != nil { - return "", err - } - - return string(data), nil -} - -func (a *App) SaveRecentFetches(payload string) error { - payload = strings.TrimSpace(payload) - if payload == "" { - payload = "[]" - } - - var items []backend.RecentFetchItem - if err := json.Unmarshal([]byte(payload), &items); err != nil { - return err - } - - return backend.SaveRecentFetches(items) -} - -func (a *App) SaveSpectrumImage(audioFilePath string, base64Data string) (string, error) { - if audioFilePath == "" || base64Data == "" { - return "", fmt.Errorf("file path and image data are required") - } - - base64Data = strings.TrimPrefix(base64Data, "data:image/png;base64,") - - data, err := base64.StdEncoding.DecodeString(base64Data) - if err != nil { - return "", fmt.Errorf("failed to decode base64 image: %v", err) - } - - ext := filepath.Ext(audioFilePath) - baseName := strings.TrimSuffix(filepath.Base(audioFilePath), ext) - outPath := filepath.Join(filepath.Dir(audioFilePath), baseName+".png") - - err = os.WriteFile(outPath, data, 0644) - if err != nil { - return "", fmt.Errorf("failed to save image to disk: %v", err) - } - - return outPath, nil -} - -type LyricsDownloadRequest struct { - SpotifyID string `json:"spotify_id"` - TrackName string `json:"track_name"` - ArtistName string `json:"artist_name"` - AlbumName string `json:"album_name"` - AlbumArtist string `json:"album_artist"` - ReleaseDate string `json:"release_date"` - ISRC string `json:"isrc,omitempty"` - OutputDir string `json:"output_dir"` - FilenameFormat string `json:"filename_format"` - TrackNumber bool `json:"track_number"` - Position int `json:"position"` - UseAlbumTrackNumber bool `json:"use_album_track_number"` - DiscNumber int `json:"disc_number"` -} - -func (a *App) DownloadLyrics(req LyricsDownloadRequest) (backend.LyricsDownloadResponse, error) { - if req.SpotifyID == "" { - return backend.LyricsDownloadResponse{ - Success: false, - Error: "Spotify ID is required", - }, fmt.Errorf("spotify ID is required") - } - - client := backend.NewLyricsClient() - backendReq := backend.LyricsDownloadRequest{ - SpotifyID: req.SpotifyID, - TrackName: req.TrackName, - ArtistName: req.ArtistName, - AlbumName: req.AlbumName, - AlbumArtist: req.AlbumArtist, - ReleaseDate: req.ReleaseDate, - ISRC: req.ISRC, - OutputDir: req.OutputDir, - FilenameFormat: req.FilenameFormat, - TrackNumber: req.TrackNumber, - Position: req.Position, - UseAlbumTrackNumber: req.UseAlbumTrackNumber, - DiscNumber: req.DiscNumber, - } - - resp, err := client.DownloadLyrics(backendReq) - if err != nil { - return backend.LyricsDownloadResponse{ - Success: false, - Error: err.Error(), - }, err - } - - return *resp, nil -} - -type CoverDownloadRequest struct { - CoverURL string `json:"cover_url"` - TrackName string `json:"track_name"` - ArtistName string `json:"artist_name"` - AlbumName string `json:"album_name"` - AlbumArtist string `json:"album_artist"` - ReleaseDate string `json:"release_date"` - OutputDir string `json:"output_dir"` - FilenameFormat string `json:"filename_format"` - TrackNumber bool `json:"track_number"` - Position int `json:"position"` - DiscNumber int `json:"disc_number"` -} - -func (a *App) DownloadCover(req CoverDownloadRequest) (backend.CoverDownloadResponse, error) { - if req.CoverURL == "" { - return backend.CoverDownloadResponse{ - Success: false, - Error: "Cover URL is required", - }, fmt.Errorf("cover URL is required") - } - - client := backend.NewCoverClient() - backendReq := backend.CoverDownloadRequest{ - CoverURL: req.CoverURL, - TrackName: req.TrackName, - ArtistName: req.ArtistName, - AlbumName: req.AlbumName, - AlbumArtist: req.AlbumArtist, - ReleaseDate: req.ReleaseDate, - OutputDir: req.OutputDir, - FilenameFormat: req.FilenameFormat, - TrackNumber: req.TrackNumber, - Position: req.Position, - DiscNumber: req.DiscNumber, - } - - resp, err := client.DownloadCover(backendReq) - if err != nil { - return backend.CoverDownloadResponse{ - Success: false, - Error: err.Error(), - }, err - } - - return *resp, nil -} - -type HeaderDownloadRequest struct { - HeaderURL string `json:"header_url"` - ArtistName string `json:"artist_name"` - OutputDir string `json:"output_dir"` -} - -func (a *App) DownloadHeader(req HeaderDownloadRequest) (backend.HeaderDownloadResponse, error) { - if req.HeaderURL == "" { - return backend.HeaderDownloadResponse{ - Success: false, - Error: "Header URL is required", - }, fmt.Errorf("header URL is required") - } - - if req.ArtistName == "" { - return backend.HeaderDownloadResponse{ - Success: false, - Error: "Artist name is required", - }, fmt.Errorf("artist name is required") - } - - client := backend.NewCoverClient() - backendReq := backend.HeaderDownloadRequest{ - HeaderURL: req.HeaderURL, - ArtistName: req.ArtistName, - OutputDir: req.OutputDir, - } - - resp, err := client.DownloadHeader(backendReq) - if err != nil { - return backend.HeaderDownloadResponse{ - Success: false, - Error: err.Error(), - }, err - } - - return *resp, nil -} - -type GalleryImageDownloadRequest struct { - ImageURL string `json:"image_url"` - ArtistName string `json:"artist_name"` - ImageIndex int `json:"image_index"` - OutputDir string `json:"output_dir"` -} - -func (a *App) DownloadGalleryImage(req GalleryImageDownloadRequest) (backend.GalleryImageDownloadResponse, error) { - if req.ImageURL == "" { - return backend.GalleryImageDownloadResponse{ - Success: false, - Error: "Image URL is required", - }, fmt.Errorf("image URL is required") - } - - if req.ArtistName == "" { - return backend.GalleryImageDownloadResponse{ - Success: false, - Error: "Artist name is required", - }, fmt.Errorf("artist name is required") - } - - client := backend.NewCoverClient() - backendReq := backend.GalleryImageDownloadRequest{ - ImageURL: req.ImageURL, - ArtistName: req.ArtistName, - ImageIndex: req.ImageIndex, - OutputDir: req.OutputDir, - } - - resp, err := client.DownloadGalleryImage(backendReq) - if err != nil { - return backend.GalleryImageDownloadResponse{ - Success: false, - Error: err.Error(), - }, err - } - - return *resp, nil -} - -type AvatarDownloadRequest struct { - AvatarURL string `json:"avatar_url"` - ArtistName string `json:"artist_name"` - OutputDir string `json:"output_dir"` -} - -func (a *App) DownloadAvatar(req AvatarDownloadRequest) (backend.AvatarDownloadResponse, error) { - if req.AvatarURL == "" { - return backend.AvatarDownloadResponse{ - Success: false, - Error: "Avatar URL is required", - }, fmt.Errorf("avatar URL is required") - } - - if req.ArtistName == "" { - return backend.AvatarDownloadResponse{ - Success: false, - Error: "Artist name is required", - }, fmt.Errorf("artist name is required") - } - - client := backend.NewCoverClient() - backendReq := backend.AvatarDownloadRequest{ - AvatarURL: req.AvatarURL, - ArtistName: req.ArtistName, - OutputDir: req.OutputDir, - } - - resp, err := client.DownloadAvatar(backendReq) - if err != nil { - return backend.AvatarDownloadResponse{ - Success: false, - Error: err.Error(), - }, err - } - - return *resp, nil -} - -func (a *App) CheckTrackAvailability(spotifyTrackID string) (string, error) { - if spotifyTrackID == "" { - return "", fmt.Errorf("spotify track ID is required") - } - - return runWithTimeout(checkOperationTimeout, func() (string, error) { - client := backend.NewSongLinkClient() - availability, err := client.CheckTrackAvailability(spotifyTrackID) - if err != nil { - return "", err - } - - jsonData, err := json.Marshal(availability) - if err != nil { - return "", fmt.Errorf("failed to encode response: %v", err) - } - - return string(jsonData), nil - }) -} - -func (a *App) IsFFmpegInstalled() (bool, error) { - return backend.IsFFmpegInstalled() -} - -func (a *App) IsFFprobeInstalled() (bool, error) { - return backend.IsFFprobeInstalled() -} - -type DownloadFFmpegRequest struct{} - -type DownloadFFmpegResponse struct { - Success bool `json:"success"` - Message string `json:"message"` - Error string `json:"error,omitempty"` -} - -func (a *App) DownloadFFmpeg() DownloadFFmpegResponse { - runtime.EventsEmit(a.ctx, "ffmpeg:status", "starting") - err := backend.DownloadFFmpeg(func(progress int) { - runtime.EventsEmit(a.ctx, "ffmpeg:progress", progress) - }) - if err != nil { - runtime.EventsEmit(a.ctx, "ffmpeg:status", "failed") - return DownloadFFmpegResponse{ - Success: false, - Error: err.Error(), - } - } - - runtime.EventsEmit(a.ctx, "ffmpeg:status", "completed") - return DownloadFFmpegResponse{ - Success: true, - Message: "FFmpeg installed successfully", - } -} - -func (a *App) GetBrewPath() string { - return backend.GetBrewPath() -} - -func (a *App) IsBrewFFmpegInstalled() (bool, error) { - return backend.IsBrewFFmpegInstalled() -} - -type InstallFFmpegWithBrewResponse struct { - Success bool `json:"success"` - Message string `json:"message"` - Error string `json:"error,omitempty"` -} - -func (a *App) InstallFFmpegWithBrew() InstallFFmpegWithBrewResponse { - runtime.EventsEmit(a.ctx, "ffmpeg:status", "Installing FFmpeg via Homebrew...") - err := backend.InstallFFmpegWithBrew(func(progress int, status string) { - runtime.EventsEmit(a.ctx, "ffmpeg:progress", progress) - runtime.EventsEmit(a.ctx, "ffmpeg:status", status) - }) - if err != nil { - runtime.EventsEmit(a.ctx, "ffmpeg:status", "failed") - return InstallFFmpegWithBrewResponse{ - Success: false, - Error: err.Error(), - } - } - - runtime.EventsEmit(a.ctx, "ffmpeg:status", "completed") - return InstallFFmpegWithBrewResponse{ - Success: true, - Message: "FFmpeg installed successfully via Homebrew", - } -} - -type ConvertAudioRequest struct { - InputFiles []string `json:"input_files"` - OutputFormat string `json:"output_format"` - Bitrate string `json:"bitrate"` - Codec string `json:"codec"` -} - -func (a *App) ConvertAudio(req ConvertAudioRequest) ([]backend.ConvertAudioResult, error) { - backendReq := backend.ConvertAudioRequest{ - InputFiles: req.InputFiles, - OutputFormat: req.OutputFormat, - Bitrate: req.Bitrate, - Codec: req.Codec, - } - return backend.ConvertAudio(backendReq) -} - -type ResampleAudioRequest struct { - InputFiles []string `json:"input_files"` - SampleRate string `json:"sample_rate"` - BitDepth string `json:"bit_depth"` -} - -func (a *App) ResampleAudio(req ResampleAudioRequest) ([]backend.ResampleResult, error) { - backendReq := backend.ResampleRequest{ - InputFiles: req.InputFiles, - SampleRate: req.SampleRate, - BitDepth: req.BitDepth, - } - return backend.ResampleAudio(backendReq) -} - -func (a *App) SelectAudioFiles() ([]string, error) { - files, err := backend.SelectMultipleFiles(a.ctx) - if err != nil { - return nil, err - } - return files, nil -} - -func (a *App) GetFlacInfoBatch(paths []string) []backend.FlacInfo { - return backend.GetFlacInfoBatch(paths) -} - -func (a *App) GetFileSizes(files []string) map[string]int64 { - return backend.GetFileSizes(files) -} - -func (a *App) ListDirectoryFiles(dirPath string) ([]backend.FileInfo, error) { - if dirPath == "" { - return nil, fmt.Errorf("directory path is required") - } - return backend.ListDirectory(dirPath) -} - -func (a *App) ListAudioFilesInDir(dirPath string) ([]backend.FileInfo, error) { - if dirPath == "" { - return nil, fmt.Errorf("directory path is required") - } - return backend.ListAudioFiles(dirPath) -} - -func (a *App) ReadFileMetadata(filePath string) (*backend.AudioMetadata, error) { - if filePath == "" { - return nil, fmt.Errorf("file path is required") - } - return backend.ReadAudioMetadata(filePath) -} - -func (a *App) PreviewRenameFiles(files []string, format string) []backend.RenamePreview { - return backend.PreviewRename(files, format) -} - -func (a *App) RenameFilesByMetadata(files []string, format string) []backend.RenameResult { - return backend.RenameFiles(files, format) -} - -func (a *App) ReadTextFile(filePath string) (string, error) { - content, err := os.ReadFile(filePath) - if err != nil { - return "", err - } - return string(content), nil -} - -func (a *App) ReadFileAsBase64(filePath string) (string, error) { - content, err := os.ReadFile(filePath) - if err != nil { - return "", err - } - - return base64.StdEncoding.EncodeToString(content), nil -} - -func (a *App) DecodeAudioForAnalysis(filePath string) (*backend.AnalysisDecodeResponse, error) { - if filePath == "" { - return nil, fmt.Errorf("file path is required") - } - - return backend.DecodeAudioForAnalysis(filePath) -} - -func (a *App) RenameFileTo(oldPath, newName string) error { - dir := filepath.Dir(oldPath) - ext := filepath.Ext(oldPath) - newPath := filepath.Join(dir, newName+ext) - return os.Rename(oldPath, newPath) -} - -func (a *App) SelectImageVideo() ([]string, error) { - return backend.SelectImageVideoDialog(a.ctx) -} - -func (a *App) ReadImageAsBase64(filePath string) (string, error) { - content, err := os.ReadFile(filePath) - if err != nil { - return "", err - } - - ext := strings.ToLower(filepath.Ext(filePath)) - var mimeType string - switch ext { - case ".jpg", ".jpeg": - mimeType = "image/jpeg" - case ".png": - mimeType = "image/png" - case ".gif": - mimeType = "image/gif" - case ".webp": - mimeType = "image/webp" - default: - mimeType = "image/jpeg" - } - - encoded := base64.StdEncoding.EncodeToString(content) - return fmt.Sprintf("data:%s;base64,%s", mimeType, encoded), nil -} - -type CheckFileExistenceRequest struct { - SpotifyID string `json:"spotify_id"` - TrackName string `json:"track_name"` - ArtistName string `json:"artist_name"` - AlbumName string `json:"album_name,omitempty"` - AlbumArtist string `json:"album_artist,omitempty"` - ReleaseDate string `json:"release_date,omitempty"` - ISRC string `json:"isrc,omitempty"` - TrackNumber int `json:"track_number,omitempty"` - DiscNumber int `json:"disc_number,omitempty"` - Position int `json:"position,omitempty"` - UseAlbumTrackNumber bool `json:"use_album_track_number,omitempty"` - FilenameFormat string `json:"filename_format,omitempty"` - IncludeTrackNumber bool `json:"include_track_number,omitempty"` - AudioFormat string `json:"audio_format,omitempty"` - RelativePath string `json:"relative_path,omitempty"` -} - -type CheckFileExistenceResult struct { - SpotifyID string `json:"spotify_id"` - Exists bool `json:"exists"` - FilePath string `json:"file_path,omitempty"` - TrackName string `json:"track_name,omitempty"` - ArtistName string `json:"artist_name,omitempty"` -} - -type existingFileLookupIndex struct { - byFilename map[string]string - byISRC map[string]string -} - -func isAudioFileForExistenceCheck(path string) bool { - switch strings.ToLower(filepath.Ext(path)) { - case ".flac", ".mp3", ".m4a": - return true - default: - return false - } -} - -func normalizeExistingFileIdentifier(value string) string { - return strings.ToUpper(strings.TrimSpace(value)) -} - -func buildExistingFileLookupIndex(scanRoot string, mode string) existingFileLookupIndex { - index := existingFileLookupIndex{ - byFilename: make(map[string]string), - byISRC: make(map[string]string), - } - - scanRoot = backend.NormalizePath(scanRoot) - if scanRoot == "" { - return index - } - - _ = filepath.Walk(scanRoot, func(path string, info os.FileInfo, err error) error { - if err != nil || info == nil || info.IsDir() || !isAudioFileForExistenceCheck(path) { - return nil - } - if info.Size() <= 100*1024 { - return nil - } - - if _, exists := index.byFilename[info.Name()]; !exists { - index.byFilename[info.Name()] = path - } - - if mode == "filename" { - return nil - } - - metadata, metadataErr := backend.ExtractFullMetadataFromFile(path) - if metadataErr != nil { - return nil - } - - if normalizedISRC := normalizeExistingFileIdentifier(metadata.ISRC); normalizedISRC != "" { - if _, exists := index.byISRC[normalizedISRC]; !exists { - index.byISRC[normalizedISRC] = path - } - } - - return nil - }) - - return index -} - -func (a *App) CheckFilesExistence(outputDir string, rootDir string, tracks []CheckFileExistenceRequest) []CheckFileExistenceResult { - if len(tracks) == 0 { - return []CheckFileExistenceResult{} - } - - outputDir = backend.NormalizePath(outputDir) - if rootDir != "" { - rootDir = backend.NormalizePath(rootDir) - } - - defaultFilenameFormat := "title-artist" - redownloadWithSuffix := backend.GetRedownloadWithSuffixSetting() - existingFileCheckMode := backend.GetExistingFileCheckModeSetting() - scanRoot := outputDir - if rootDir != "" { - scanRoot = rootDir - } - - type result struct { - index int - result CheckFileExistenceResult - } - - resultsChan := make(chan result, len(tracks)) - var lookupIndex existingFileLookupIndex - var lookupIndexOnce sync.Once - getLookupIndex := func() existingFileLookupIndex { - lookupIndexOnce.Do(func() { - lookupIndex = buildExistingFileLookupIndex(scanRoot, existingFileCheckMode) - }) - return lookupIndex - } - - for i, track := range tracks { - go func(idx int, t CheckFileExistenceRequest) { - res := CheckFileExistenceResult{ - SpotifyID: t.SpotifyID, - TrackName: t.TrackName, - ArtistName: t.ArtistName, - Exists: false, - } - - if t.TrackName == "" || t.ArtistName == "" { - resultsChan <- result{index: idx, result: res} - return - } - - filenameFormat := t.FilenameFormat - if filenameFormat == "" { - filenameFormat = defaultFilenameFormat - } - isrc := strings.TrimSpace(t.ISRC) - shouldResolveISRC := existingFileCheckMode == "isrc" || strings.Contains(filenameFormat, "{isrc}") - if isrc == "" && shouldResolveISRC && t.SpotifyID != "" { - isrc = backend.ResolveTrackISRC(t.SpotifyID) - } - - trackNumber := t.Position - if t.UseAlbumTrackNumber && t.TrackNumber > 0 { - trackNumber = t.TrackNumber - } - - fileExt := ".flac" - switch strings.ToLower(strings.TrimSpace(t.AudioFormat)) { - case "mp3": - fileExt = ".mp3" - case "m4a", "m4a-aac", "m4a-alac", "alac", "atmos", "apple": - fileExt = ".m4a" - } - - expectedFilenameBase := backend.BuildExpectedFilename( - t.TrackName, - t.ArtistName, - t.AlbumName, - t.AlbumArtist, - t.ReleaseDate, - filenameFormat, - "", - "", - t.IncludeTrackNumber, - trackNumber, - t.DiscNumber, - t.UseAlbumTrackNumber, - isrc, - ) - - expectedFilename := strings.TrimSuffix(expectedFilenameBase, ".flac") + fileExt - - targetDir := outputDir - if t.RelativePath != "" { - targetDir = filepath.Join(outputDir, t.RelativePath) - } - - expectedPath := filepath.Join(targetDir, expectedFilename) - if redownloadWithSuffix { - expectedPath, _ = backend.ResolveOutputPathForDownload(expectedPath, true) - resultsChan <- result{index: idx, result: res} - return - } - - normalizedISRC := normalizeExistingFileIdentifier(isrc) - effectiveMode := existingFileCheckMode - if effectiveMode == "isrc" && normalizedISRC == "" { - effectiveMode = "filename" - } - - switch effectiveMode { - case "isrc": - if path, ok := getLookupIndex().byISRC[normalizedISRC]; ok { - res.Exists = true - res.FilePath = path - } - default: - if fileInfo, err := os.Stat(expectedPath); err == nil && fileInfo.Size() > 100*1024 { - res.Exists = true - res.FilePath = expectedPath - } else if path, ok := getLookupIndex().byFilename[filepath.Base(expectedPath)]; ok { - res.Exists = true - res.FilePath = path - } - } - - resultsChan <- result{index: idx, result: res} - }(i, track) - } - - results := make([]CheckFileExistenceResult, len(tracks)) - - for i := 0; i < len(tracks); i++ { - r := <-resultsChan - results[r.index] = r.result - } - - return results -} - -func (a *App) SkipDownloadItem(itemID, filePath string) { - backend.SkipDownloadItem(itemID, filePath) -} - -func (a *App) GetTrackISRC(spotifyTrackID string) string { - return backend.ResolveTrackISRC(spotifyTrackID) -} - -func (a *App) GetPreviewURL(trackID string) (string, error) { - return backend.GetPreviewURL(trackID) -} - -func (a *App) GetConfigPath() (string, error) { - dir, err := backend.GetFFmpegDir() - if err != nil { - return "", err - } - return filepath.Join(dir, "config.json"), nil -} - -func (a *App) GetFontsPath() (string, error) { - dir, err := backend.GetFFmpegDir() - if err != nil { - return "", err - } - return filepath.Join(dir, "fonts.json"), nil -} - -func (a *App) SaveSettings(settings map[string]interface{}) error { - configPath, err := a.GetConfigPath() - if err != nil { - return err - } - settings = backend.SanitizeSettingsMap(settings) - - dir := filepath.Dir(configPath) - if _, err := os.Stat(dir); os.IsNotExist(err) { - if err := os.MkdirAll(dir, 0755); err != nil { - return err - } - } - - data, err := json.MarshalIndent(settings, "", " ") - if err != nil { - return err - } - - return os.WriteFile(configPath, data, 0644) -} - -func (a *App) SaveFonts(fonts []map[string]interface{}) error { - fontsPath, err := a.GetFontsPath() - if err != nil { - return err - } - - dir := filepath.Dir(fontsPath) - if _, err := os.Stat(dir); os.IsNotExist(err) { - if err := os.MkdirAll(dir, 0755); err != nil { - return err - } - } - - data, err := json.MarshalIndent(fonts, "", " ") - if err != nil { - return err - } - - return os.WriteFile(fontsPath, data, 0644) -} - -func (a *App) LoadSettings() (map[string]interface{}, error) { - configPath, err := a.GetConfigPath() - if err != nil { - return nil, err - } - - if _, err := os.Stat(configPath); os.IsNotExist(err) { - return nil, nil - } - - data, err := os.ReadFile(configPath) - if err != nil { - return nil, err - } - - var settings map[string]interface{} - if err := json.Unmarshal(data, &settings); err != nil { - return nil, err - } - - return backend.SanitizeSettingsMap(settings), nil -} - -func (a *App) LoadFonts() ([]map[string]interface{}, error) { - fontsPath, err := a.GetFontsPath() - if err != nil { - return nil, err - } - - if _, err := os.Stat(fontsPath); os.IsNotExist(err) { - return nil, nil - } - - data, err := os.ReadFile(fontsPath) - if err != nil { - return nil, err - } - - var fonts []map[string]interface{} - if err := json.Unmarshal(data, &fonts); err != nil { - return nil, err - } - if fonts == nil { - return []map[string]interface{}{}, nil - } - - return fonts, nil -} - -func (a *App) CheckFFmpegInstalled() (bool, error) { - return backend.IsFFmpegInstalled() -} - -func (a *App) CreateM3U8File(m3u8Name string, outputDir string, filePaths []string) error { - if len(filePaths) == 0 { - return nil - } - - if err := os.MkdirAll(outputDir, 0755); err != nil { - return err - } - - fnName := m3u8Name - - safeName := backend.SanitizeFilename(fnName) - if safeName == "" { - safeName = "playlist" - } - - m3u8Path := filepath.Join(outputDir, safeName+".m3u8") - - f, err := os.Create(m3u8Path) - if err != nil { - return err - } - defer f.Close() - - if _, err := f.WriteString("#EXTM3U\n"); err != nil { - return err - } - - for _, path := range filePaths { - if path == "" { - continue - } - - relPath, err := filepath.Rel(outputDir, path) - if err != nil { - - relPath = path - } - - relPath = filepath.ToSlash(relPath) - - if _, err := f.WriteString(relPath + "\n"); err != nil { - return err - } - } - - return nil -} diff --git a/backend/amazon.go b/backend/amazon.go deleted file mode 100644 index 207bd41..0000000 --- a/backend/amazon.go +++ /dev/null @@ -1,537 +0,0 @@ -package backend - -import ( - "crypto/aes" - "crypto/cipher" - "crypto/sha256" - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "os/exec" - "path/filepath" - "regexp" - "strings" - "sync" - "time" -) - -type AmazonDownloader struct { - client *http.Client - regions []string -} - -type AmazonStreamResponse struct { - StreamURL string `json:"streamUrl"` - DecryptionKey string `json:"decryptionKey"` -} - -var ( - amazonMusicDebugKeyOnce sync.Once - amazonMusicDebugKey string - amazonMusicDebugKeyErr error -) - -var amazonMusicDebugKeySeedParts = [][]byte{ - []byte("spotif"), - []byte("lac:am"), - []byte("azon:spotbye:api:v1"), -} - -var amazonMusicDebugKeyAAD = []byte{ - 0x61, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x7c, 0x73, 0x70, 0x6f, 0x74, 0x62, - 0x79, 0x65, 0x7c, 0x64, 0x65, 0x62, 0x75, 0x67, 0x7c, 0x76, 0x31, -} - -var amazonMusicDebugKeyNonce = []byte{ - 0x52, 0x1f, 0xa4, 0x9c, 0x13, 0x77, 0x5b, 0xe2, 0x81, 0x44, 0x90, 0x6d, -} - -var amazonMusicDebugKeyCiphertext = []byte{ - 0x5b, 0xf9, 0xc1, 0x2e, 0x58, 0xf8, 0x5b, 0xc0, 0x04, 0x68, 0x7e, 0xff, - 0x3d, 0xd6, 0x8b, 0xe3, 0x86, 0x49, 0x6c, 0xfd, 0xc1, 0x49, 0x0b, 0xfb, -} - -var amazonMusicDebugKeyTag = []byte{ - 0x6c, 0x21, 0x98, 0x51, 0xf2, 0x38, 0x4b, 0x4a, 0x23, 0xe1, 0xc6, 0xd7, - 0x65, 0x7f, 0xfb, 0xa1, -} - -func getAmazonMusicDebugKey() (string, error) { - amazonMusicDebugKeyOnce.Do(func() { - hasher := sha256.New() - for _, part := range amazonMusicDebugKeySeedParts { - hasher.Write(part) - } - - block, err := aes.NewCipher(hasher.Sum(nil)) - if err != nil { - amazonMusicDebugKeyErr = err - return - } - - gcm, err := cipher.NewGCM(block) - if err != nil { - amazonMusicDebugKeyErr = err - return - } - - sealed := make([]byte, 0, len(amazonMusicDebugKeyCiphertext)+len(amazonMusicDebugKeyTag)) - sealed = append(sealed, amazonMusicDebugKeyCiphertext...) - sealed = append(sealed, amazonMusicDebugKeyTag...) - - plaintext, err := gcm.Open(nil, amazonMusicDebugKeyNonce, sealed, amazonMusicDebugKeyAAD) - if err != nil { - amazonMusicDebugKeyErr = err - return - } - - amazonMusicDebugKey = string(plaintext) - }) - - if amazonMusicDebugKeyErr != nil { - return "", amazonMusicDebugKeyErr - } - - return amazonMusicDebugKey, nil -} - -func NewAmazonDownloader() *AmazonDownloader { - return &AmazonDownloader{ - client: &http.Client{ - Timeout: 120 * time.Second, - }, - regions: []string{"us", "eu"}, - } -} - -func (a *AmazonDownloader) GetAmazonURLFromSpotify(spotifyTrackID string) (string, error) { - fmt.Println("Getting Amazon URL...") - client := NewSongLinkClient() - urls, err := client.GetAllURLsFromSpotify(spotifyTrackID, "") - if err != nil { - return "", fmt.Errorf("failed to get Amazon URL: %w", err) - } - - amazonURL := normalizeAmazonMusicURL(urls.AmazonURL) - if amazonURL == "" { - return "", fmt.Errorf("amazon Music link not found") - } - fmt.Printf("Found Amazon URL: %s\n", amazonURL) - return amazonURL, nil -} - -func (a *AmazonDownloader) DownloadFromAfkarXYZ(amazonURL, outputDir, quality string) (string, error) { - - asinRegex := regexp.MustCompile(`(B[0-9A-Z]{9})`) - asin := asinRegex.FindString(amazonURL) - if asin == "" { - return "", fmt.Errorf("failed to extract ASIN from URL: %s", amazonURL) - } - - apiURL := fmt.Sprintf("%s/api/track/%s", amazonMusicAPIBaseURL, asin) - req, err := NewRequestWithDefaultHeaders(http.MethodGet, apiURL, nil) - if err != nil { - return "", err - } - - debugKey, err := getAmazonMusicDebugKey() - if err != nil { - return "", fmt.Errorf("failed to decrypt Amazon debug key: %w", err) - } - req.Header.Set("X-Debug-Key", debugKey) - - fmt.Printf("Fetching from Amazon API (ASIN: %s)...\n", asin) - resp, err := a.client.Do(req) - if err != nil { - return "", err - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return "", fmt.Errorf("Amazon API returned status %d", resp.StatusCode) - } - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return "", err - } - - var apiResp AmazonStreamResponse - if err := json.Unmarshal(bodyBytes, &apiResp); err != nil { - return "", fmt.Errorf("failed to decode response: %w", err) - } - - if apiResp.StreamURL == "" { - return "", fmt.Errorf("no stream URL found in response") - } - - downloadURL := apiResp.StreamURL - fileName := fmt.Sprintf("%s.m4a", asin) - filePath := filepath.Join(outputDir, fileName) - - out, err := os.Create(filePath) - if err != nil { - return "", err - } - defer out.Close() - - dlReq, err := NewRequestWithDefaultHeaders(http.MethodGet, downloadURL, nil) - if err != nil { - return "", err - } - - dlResp, err := a.client.Do(dlReq) - if err != nil { - return "", err - } - defer dlResp.Body.Close() - - fmt.Printf("Downloading track: %s\n", fileName) - pw := NewProgressWriter(out) - _, err = io.Copy(pw, dlResp.Body) - if err != nil { - out.Close() - os.Remove(filePath) - return "", err - } - - fmt.Printf("\rDownloaded: %.2f MB (Complete)\n", float64(pw.GetTotal())/(1024*1024)) - - if apiResp.DecryptionKey != "" { - fmt.Printf("Decrypting file...\n") - - ffprobePath, err := GetFFprobePath() - var codec string - if err == nil { - cmdProbe := exec.Command(ffprobePath, - "-v", "quiet", - "-select_streams", "a:0", - "-show_entries", "stream=codec_name", - "-of", "default=noprint_wrappers=1:nokey=1", - filePath, - ) - setHideWindow(cmdProbe) - codecOutput, _ := cmdProbe.Output() - codec = strings.TrimSpace(string(codecOutput)) - fmt.Printf("Detected codec: %s\n", codec) - } - - targetExt := ".m4a" - if codec == "flac" { - targetExt = ".flac" - } - - decryptedFilename := "dec_" + fileName + targetExt - - if targetExt == ".flac" && strings.HasSuffix(fileName, ".m4a") { - decryptedFilename = "dec_" + strings.TrimSuffix(fileName, ".m4a") + ".flac" - } - - decryptedPath := filepath.Join(outputDir, decryptedFilename) - - ffmpegPath, err := GetFFmpegPath() - if err != nil { - return "", fmt.Errorf("ffmpeg not found for decryption: %w", err) - } - - if err := ValidateExecutable(ffmpegPath); err != nil { - return "", fmt.Errorf("invalid ffmpeg executable: %w", err) - } - - key := strings.TrimSpace(apiResp.DecryptionKey) - - cmd := exec.Command(ffmpegPath, - "-decryption_key", key, - "-i", filePath, - "-c", "copy", - "-y", - decryptedPath, - ) - - setHideWindow(cmd) - output, err := cmd.CombinedOutput() - if err != nil { - - outStr := string(output) - if len(outStr) > 500 { - outStr = outStr[len(outStr)-500:] - } - return "", fmt.Errorf("ffmpeg decryption failed: %v\nTail Output: %s", err, outStr) - } - - if info, err := os.Stat(decryptedPath); err != nil || info.Size() == 0 { - return "", fmt.Errorf("decrypted file missing or empty") - } - - if err := os.Remove(filePath); err != nil { - fmt.Printf("Warning: Failed to remove encrypted file: %v\n", err) - } - - finalPath := filepath.Join(outputDir, strings.TrimPrefix(decryptedFilename, "dec_")) - if err := os.Rename(decryptedPath, finalPath); err != nil { - return "", fmt.Errorf("failed to rename decrypted file: %w", err) - } - filePath = finalPath - - fmt.Println("Decryption successful") - } - - return filePath, nil -} - -func (a *AmazonDownloader) DownloadFromService(amazonURL, outputDir, quality string) (string, error) { - return a.DownloadFromAfkarXYZ(amazonURL, outputDir, quality) -} - -func (a *AmazonDownloader) DownloadByURL(amazonURL, outputDir, quality, filenameFormat, playlistName, playlistOwner string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, spotifyCoverURL string, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, embedMaxQualityCover bool, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL string, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) { - - if outputDir != "." { - if err := os.MkdirAll(outputDir, 0755); err != nil { - return "", fmt.Errorf("failed to create output directory: %w", err) - } - } - - if spotifyTrackName != "" && spotifyArtistName != "" { - filenameArtist := spotifyArtistName - filenameAlbumArtist := spotifyAlbumArtist - if useFirstArtistOnly { - filenameArtist = GetFirstArtist(spotifyArtistName) - filenameAlbumArtist = GetFirstArtist(spotifyAlbumArtist) - } - expectedFilename := BuildExpectedFilename(spotifyTrackName, filenameArtist, spotifyAlbumName, filenameAlbumArtist, spotifyReleaseDate, filenameFormat, playlistName, playlistOwner, includeTrackNumber, position, spotifyDiscNumber, false, isrcOverride) - expectedPath := filepath.Join(outputDir, expectedFilename) - - if !GetRedownloadWithSuffixSetting() { - if fileInfo, err := os.Stat(expectedPath); err == nil && fileInfo.Size() > 0 { - fmt.Printf("File already exists: %s (%.2f MB)\n", expectedPath, float64(fileInfo.Size())/(1024*1024)) - return "EXISTS:" + expectedPath, nil - } - } - } - - type mbResult struct { - ISRC string - Metadata Metadata - } - - metaChan := make(chan mbResult, 1) - if embedGenre && spotifyURL != "" { - go func() { - res := mbResult{} - var isrc string - parts := strings.Split(spotifyURL, "/") - if len(parts) > 0 { - sID := strings.Split(parts[len(parts)-1], "?")[0] - if sID != "" { - client := NewSongLinkClient() - if val, err := client.GetISRC(sID); err == nil { - isrc = val - } - } - } - res.ISRC = isrc - if isrc != "" { - if ShouldSkipMusicBrainzMetadataFetch() { - fmt.Println("Skipping MusicBrainz metadata fetch because status check is offline.") - } else { - fmt.Println("Fetching MusicBrainz metadata...") - if fetchedMeta, err := FetchMusicBrainzMetadata(isrc, spotifyTrackName, spotifyArtistName, spotifyAlbumName, useSingleGenre, embedGenre); err == nil { - res.Metadata = fetchedMeta - fmt.Println("✓ MusicBrainz metadata fetched") - } else { - fmt.Printf("Warning: Failed to fetch MusicBrainz metadata: %v\n", err) - } - } - } - metaChan <- res - }() - } else { - close(metaChan) - } - - fmt.Printf("Using Amazon URL: %s\n", amazonURL) - - filePath, err := a.DownloadFromService(amazonURL, outputDir, quality) - if err != nil { - return "", err - } - - isrc := strings.TrimSpace(isrcOverride) - var mbMeta Metadata - if spotifyURL != "" { - result := <-metaChan - if isrc == "" { - isrc = result.ISRC - } - mbMeta = result.Metadata - } - - upc := "" - if spotifyURL != "" { - if identifiers, err := GetSpotifyTrackIdentifiersDirect(spotifyURL); err == nil || identifiers.ISRC != "" || identifiers.UPC != "" { - if strings.TrimSpace(isrc) == "" && strings.TrimSpace(identifiers.ISRC) != "" { - isrc = strings.TrimSpace(identifiers.ISRC) - } - upc = strings.TrimSpace(identifiers.UPC) - } - } - - originalFileDir := filepath.Dir(filePath) - originalFileBase := strings.TrimSuffix(filepath.Base(filePath), filepath.Ext(filePath)) - - if spotifyTrackName != "" && spotifyArtistName != "" { - safeArtist := sanitizeFilename(spotifyArtistName) - safeAlbumArtist := sanitizeFilename(spotifyAlbumArtist) - - if useFirstArtistOnly { - safeArtist = sanitizeFilename(GetFirstArtist(spotifyArtistName)) - safeAlbumArtist = sanitizeFilename(GetFirstArtist(spotifyAlbumArtist)) - } - - safeTitle := sanitizeFilename(spotifyTrackName) - safeAlbum := sanitizeFilename(spotifyAlbumName) - - year := "" - if len(spotifyReleaseDate) >= 4 { - year = spotifyReleaseDate[:4] - } - - var newFilename string - - if strings.Contains(filenameFormat, "{") { - newFilename = filenameFormat - newFilename = strings.ReplaceAll(newFilename, "{title}", safeTitle) - newFilename = strings.ReplaceAll(newFilename, "{artist}", safeArtist) - newFilename = strings.ReplaceAll(newFilename, "{album}", safeAlbum) - newFilename = strings.ReplaceAll(newFilename, "{album_artist}", safeAlbumArtist) - newFilename = strings.ReplaceAll(newFilename, "{year}", year) - newFilename = strings.ReplaceAll(newFilename, "{date}", SanitizeFilename(spotifyReleaseDate)) - newFilename = strings.ReplaceAll(newFilename, "{isrc}", SanitizeOptionalFilename(isrc)) - - if spotifyDiscNumber > 0 { - newFilename = strings.ReplaceAll(newFilename, "{disc}", fmt.Sprintf("%d", spotifyDiscNumber)) - } else { - newFilename = strings.ReplaceAll(newFilename, "{disc}", "") - } - - if position > 0 { - newFilename = strings.ReplaceAll(newFilename, "{track}", fmt.Sprintf("%02d", position)) - } else { - - newFilename = regexp.MustCompile(`\{track\}\.\s*`).ReplaceAllString(newFilename, "") - newFilename = regexp.MustCompile(`\{track\}\s*-\s*`).ReplaceAllString(newFilename, "") - newFilename = regexp.MustCompile(`\{track\}\s*`).ReplaceAllString(newFilename, "") - } - } else { - - switch filenameFormat { - case "artist-title": - newFilename = fmt.Sprintf("%s - %s", safeArtist, safeTitle) - case "title": - newFilename = safeTitle - default: - newFilename = fmt.Sprintf("%s - %s", safeTitle, safeArtist) - } - - if includeTrackNumber && position > 0 { - newFilename = fmt.Sprintf("%02d. %s", position, newFilename) - } - } - - ext := filepath.Ext(filePath) - if ext == "" { - ext = ".flac" - } - newFilename = newFilename + ext - newFilePath := filepath.Join(outputDir, newFilename) - if GetRedownloadWithSuffixSetting() { - newFilePath, _ = ResolveOutputPathForDownload(newFilePath, true) - } - - if err := os.Rename(filePath, newFilePath); err != nil { - fmt.Printf("Warning: Failed to rename file: %v\n", err) - } else { - filePath = newFilePath - fmt.Printf("Renamed to: %s\n", newFilename) - } - } - - fmt.Println("Embedding Spotify metadata...") - - coverPath := "" - - if spotifyCoverURL != "" { - coverPath = filePath + ".cover.jpg" - coverClient := NewCoverClient() - if err := coverClient.DownloadCoverToPath(spotifyCoverURL, coverPath, embedMaxQualityCover); err != nil { - fmt.Printf("Warning: Failed to download Spotify cover: %v\n", err) - coverPath = "" - } else { - defer os.Remove(coverPath) - fmt.Println("Spotify cover downloaded") - } - } - - trackNumberToEmbed := spotifyTrackNumber - if trackNumberToEmbed == 0 { - trackNumberToEmbed = 1 - } - - metadata := Metadata{ - Title: spotifyTrackName, - Artist: spotifyArtistName, - Album: spotifyAlbumName, - AlbumArtist: spotifyAlbumArtist, - Date: spotifyReleaseDate, - TrackNumber: trackNumberToEmbed, - TotalTracks: spotifyTotalTracks, - DiscNumber: spotifyDiscNumber, - TotalDiscs: spotifyTotalDiscs, - URL: spotifyURL, - Comment: spotifyURL, - Copyright: spotifyCopyright, - Publisher: spotifyPublisher, - Composer: spotifyComposer, - Separator: metadataSeparator, - Description: "https://github.com/spotbye/SpotiFLAC", - ISRC: isrc, - UPC: upc, - Genre: mbMeta.Genre, - } - - if err := EmbedMetadataToConvertedFile(filePath, metadata, coverPath); err != nil { - fmt.Printf("Warning: Failed to embed metadata: %v\n", err) - } else { - fmt.Println("Metadata embedded successfully") - } - - if strings.HasSuffix(strings.ToLower(filePath), ".flac") { - - originalM4aPath := filepath.Join(originalFileDir, originalFileBase+".m4a") - if _, err := os.Stat(originalM4aPath); err == nil { - if err := os.Remove(originalM4aPath); err != nil { - fmt.Printf("Warning: Failed to remove M4A file: %v\n", err) - } else { - fmt.Printf("Cleaned up original M4A file: %s\n", filepath.Base(originalM4aPath)) - } - } - } - - fmt.Println("Done") - fmt.Println("✓ Downloaded successfully from Amazon Music") - return filePath, nil -} - -func (a *AmazonDownloader) DownloadBySpotifyID(spotifyTrackID, outputDir, quality, filenameFormat, playlistName, playlistOwner string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, spotifyCoverURL string, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, embedMaxQualityCover bool, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL string, - useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool, -) (string, error) { - - amazonURL, err := a.GetAmazonURLFromSpotify(spotifyTrackID) - if err != nil { - return "", err - } - - return a.DownloadByURL(amazonURL, outputDir, quality, filenameFormat, playlistName, playlistOwner, includeTrackNumber, position, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, spotifyCoverURL, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks, embedMaxQualityCover, spotifyTotalDiscs, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL, useFirstArtistOnly, useSingleGenre, embedGenre) -} diff --git a/backend/analysis.go b/backend/analysis.go deleted file mode 100644 index 2753899..0000000 --- a/backend/analysis.go +++ /dev/null @@ -1,214 +0,0 @@ -package backend - -import ( - "bytes" - "encoding/base64" - "fmt" - "os" - "os/exec" - "strconv" - "strings" - "time" -) - -type AnalysisResult struct { - FilePath string `json:"file_path"` - FileSize int64 `json:"file_size"` - SampleRate uint32 `json:"sample_rate"` - Channels uint8 `json:"channels"` - BitsPerSample uint8 `json:"bits_per_sample"` - TotalSamples uint64 `json:"total_samples"` - Duration float64 `json:"duration"` - Bitrate int `json:"bit_rate"` - BitDepth string `json:"bit_depth"` - DynamicRange float64 `json:"dynamic_range"` - PeakAmplitude float64 `json:"peak_amplitude"` - RMSLevel float64 `json:"rms_level"` -} - -type AnalysisDecodeResponse struct { - PCMBase64 string `json:"pcm_base64"` - SampleRate uint32 `json:"sample_rate"` - Channels uint8 `json:"channels"` - BitsPerSample uint8 `json:"bits_per_sample"` - Duration float64 `json:"duration"` - BitrateKbps int `json:"bitrate_kbps,omitempty"` - BitDepth string `json:"bit_depth,omitempty"` -} - -func GetTrackMetadata(filepath string) (*AnalysisResult, error) { - if !fileExists(filepath) { - return nil, fmt.Errorf("file does not exist: %s", filepath) - } - - return GetMetadataWithFFprobe(filepath) -} - -func GetMetadataWithFFprobe(filePath string) (*AnalysisResult, error) { - ffprobePath, err := GetFFprobePath() - if err != nil { - return nil, err - } - - for i := 0; i < 5; i++ { - if f, err := os.Open(filePath); err == nil { - f.Close() - break - } - time.Sleep(200 * time.Millisecond) - } - - args := []string{ - "-v", "error", - "-select_streams", "a:0", - "-show_entries", "stream=sample_rate,channels,bits_per_raw_sample,bits_per_sample,duration,bit_rate", - "-of", "default=noprint_wrappers=0", - filePath, - } - cmd := exec.Command(ffprobePath, args...) - setHideWindow(cmd) - output, err := cmd.CombinedOutput() - if err != nil { - return nil, fmt.Errorf("ffprobe failed: %v - %s", err, string(output)) - } - - infoMap := make(map[string]string) - lines := strings.Split(string(output), "\n") - for _, line := range lines { - if strings.Contains(line, "=") { - parts := strings.SplitN(line, "=", 2) - infoMap[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) - } - } - - res := &AnalysisResult{ - FilePath: filePath, - } - - if info, err := os.Stat(filePath); err == nil { - res.FileSize = info.Size() - } - - if val, ok := infoMap["sample_rate"]; ok { - s, _ := strconv.Atoi(val) - res.SampleRate = uint32(s) - } - if val, ok := infoMap["channels"]; ok { - c, _ := strconv.Atoi(val) - res.Channels = uint8(c) - } - if val, ok := infoMap["duration"]; ok { - d, _ := strconv.ParseFloat(val, 64) - res.Duration = d - } - if val, ok := infoMap["bit_rate"]; ok && val != "N/A" { - br, _ := strconv.Atoi(val) - res.Bitrate = br - } - - bits := 0 - if val, ok := infoMap["bits_per_raw_sample"]; ok && val != "N/A" { - bits, _ = strconv.Atoi(val) - } - if bits == 0 { - if val, ok := infoMap["bits_per_sample"]; ok && val != "N/A" { - bits, _ = strconv.Atoi(val) - } - } - - res.BitsPerSample = uint8(bits) - if bits > 0 { - res.BitDepth = fmt.Sprintf("%d-bit", bits) - } else { - res.BitDepth = "Unknown" - } - - return res, nil -} - -func DecodeAudioForAnalysis(filePath string) (*AnalysisDecodeResponse, error) { - metadata, err := GetTrackMetadata(filePath) - if err != nil { - return nil, err - } - - pcmBase64, err := extractAnalysisPCMBase64(filePath) - if err != nil { - return nil, err - } - - resp := &AnalysisDecodeResponse{ - PCMBase64: pcmBase64, - SampleRate: metadata.SampleRate, - Channels: metadata.Channels, - BitsPerSample: metadata.BitsPerSample, - Duration: metadata.Duration, - BitDepth: metadata.BitDepth, - } - - if metadata.Bitrate > 0 { - resp.BitrateKbps = metadata.Bitrate / 1000 - } - - return resp, nil -} - -func extractAnalysisPCMBase64(filePath string) (string, error) { - ffmpegPath, err := GetFFmpegPath() - if err != nil { - return "", err - } - - argSets := [][]string{ - { - "-v", "error", - "-i", filePath, - "-vn", - "-map", "0:a:0", - "-af", "pan=mono|c0=c0", - "-f", "s16le", - "-acodec", "pcm_s16le", - "pipe:1", - }, - { - "-v", "error", - "-i", filePath, - "-vn", - "-map", "0:a:0", - "-ac", "1", - "-f", "s16le", - "-acodec", "pcm_s16le", - "pipe:1", - }, - } - - var lastErr error - - for _, args := range argSets { - var stdout bytes.Buffer - var stderr bytes.Buffer - - cmd := exec.Command(ffmpegPath, args...) - setHideWindow(cmd) - cmd.Stdout = &stdout - cmd.Stderr = &stderr - - if err := cmd.Run(); err != nil { - lastErr = fmt.Errorf("ffmpeg analysis decode failed: %w - %s", err, strings.TrimSpace(stderr.String())) - continue - } - - if stdout.Len() == 0 { - lastErr = fmt.Errorf("ffmpeg analysis decode returned empty PCM output") - continue - } - - return base64.StdEncoding.EncodeToString(stdout.Bytes()), nil - } - - if lastErr != nil { - return "", lastErr - } - - return "", fmt.Errorf("ffmpeg analysis decode failed") -} diff --git a/backend/artist_format.go b/backend/artist_format.go deleted file mode 100644 index 29c4f26..0000000 --- a/backend/artist_format.go +++ /dev/null @@ -1,90 +0,0 @@ -package backend - -import "strings" - -func normalizeArtistSeparator(separator string) string { - separator = strings.TrimSpace(separator) - if separator == "," || separator == ";" { - return separator - } - return "" -} - -func splitArtistSegment(segment string, separator string) []string { - segment = strings.TrimSpace(segment) - if segment == "" { - return nil - } - - if strings.Contains(segment, "|||SEP|||") { - return strings.Split(segment, "|||SEP|||") - } - - parts := []string{segment} - - if separator = normalizeArtistSeparator(separator); separator != "" { - var separated []string - for _, part := range parts { - for _, item := range strings.Split(part, separator) { - separated = append(separated, item) - } - } - parts = separated - } else if strings.Contains(segment, ";") { - var separated []string - for _, part := range parts { - for _, item := range strings.Split(part, ";") { - separated = append(separated, item) - } - } - parts = separated - } - - return parts -} - -func SplitArtistCredits(artistStr, separator string) []string { - rawParts := splitArtistSegment(artistStr, separator) - if len(rawParts) == 0 { - return nil - } - - seen := make(map[string]struct{}, len(rawParts)) - result := make([]string, 0, len(rawParts)) - for _, part := range rawParts { - part = strings.TrimSpace(part) - if part == "" { - continue - } - if _, exists := seen[part]; exists { - continue - } - seen[part] = struct{}{} - result = append(result, part) - } - - return result -} - -func SplitMetadataValues(value, separator string) []string { - rawParts := splitArtistSegment(value, separator) - if len(rawParts) == 0 { - return nil - } - - seen := make(map[string]struct{}, len(rawParts)) - result := make([]string, 0, len(rawParts)) - for _, part := range rawParts { - part = strings.TrimSpace(part) - if part == "" { - continue - } - if _, exists := seen[part]; exists { - continue - } - seen[part] = struct{}{} - result = append(result, part) - } - - return result -} diff --git a/backend/config.go b/backend/config.go deleted file mode 100644 index 7da1973..0000000 --- a/backend/config.go +++ /dev/null @@ -1,249 +0,0 @@ -package backend - -import ( - "encoding/json" - "errors" - "os" - "path/filepath" - "strings" -) - -const legacyTidalAPICacheFile = "tidal-api-urls.json" - -func normalizeCustomTidalAPIValue(value interface{}) string { - customAPI, _ := value.(string) - customAPI = strings.TrimRight(strings.TrimSpace(customAPI), "/") - if strings.HasPrefix(customAPI, "https://") { - return customAPI - } - return "" -} - -func sanitizeDownloaderValue(value interface{}, allowTidal bool) string { - downloader, _ := value.(string) - switch strings.TrimSpace(strings.ToLower(downloader)) { - case "tidal": - if allowTidal { - return "tidal" - } - return "auto" - case "qobuz": - return "qobuz" - case "amazon": - return "amazon" - default: - return "auto" - } -} - -func sanitizeAutoOrderValue(value interface{}, allowTidal bool) string { - autoOrder, _ := value.(string) - allowed := map[string]struct{}{ - "qobuz": {}, - "amazon": {}, - } - fallback := "qobuz-amazon" - if allowTidal { - allowed["tidal"] = struct{}{} - fallback = "tidal-qobuz-amazon" - } - - seen := make(map[string]struct{}) - parts := make([]string, 0, 3) - for _, rawPart := range strings.Split(strings.TrimSpace(strings.ToLower(autoOrder)), "-") { - part := strings.TrimSpace(rawPart) - if part == "" { - continue - } - if _, ok := allowed[part]; !ok { - continue - } - if _, ok := seen[part]; ok { - continue - } - seen[part] = struct{}{} - parts = append(parts, part) - } - - if len(parts) < 2 { - return fallback - } - - return strings.Join(parts, "-") -} - -func SanitizeSettingsMap(settings map[string]interface{}) map[string]interface{} { - if settings == nil { - return nil - } - - sanitized := make(map[string]interface{}, len(settings)) - for key, value := range settings { - sanitized[key] = value - } - - customAPI := normalizeCustomTidalAPIValue(sanitized["customTidalApi"]) - sanitized["customTidalApi"] = customAPI - allowTidal := customAPI != "" - sanitized["downloader"] = sanitizeDownloaderValue(sanitized["downloader"], allowTidal) - sanitized["autoOrder"] = sanitizeAutoOrderValue(sanitized["autoOrder"], allowTidal) - - return sanitized -} - -func CleanupLegacyTidalPublicAPIState() error { - appDir, err := EnsureAppDir() - if err != nil { - return err - } - - cachePath := filepath.Join(appDir, legacyTidalAPICacheFile) - if err := os.Remove(cachePath); err != nil && !errors.Is(err, os.ErrNotExist) { - return err - } - - return nil -} - -func SanitizePersistedConfigSettings() error { - configPath, err := GetConfigPath() - if err != nil { - return err - } - - if _, err := os.Stat(configPath); os.IsNotExist(err) { - return nil - } - - data, err := os.ReadFile(configPath) - if err != nil { - return err - } - - var settings map[string]interface{} - if err := json.Unmarshal(data, &settings); err != nil { - return err - } - - sanitized := SanitizeSettingsMap(settings) - payload, err := json.MarshalIndent(sanitized, "", " ") - if err != nil { - return err - } - - return os.WriteFile(configPath, payload, 0o644) -} - -func GetDefaultMusicPath() string { - - homeDir, err := os.UserHomeDir() - if err != nil { - - return "C:\\Users\\Public\\Music" - } - - return filepath.Join(homeDir, "Music") -} - -func GetConfigPath() (string, error) { - dir, err := EnsureAppDir() - if err != nil { - return "", err - } - - return filepath.Join(dir, "config.json"), nil -} - -func LoadConfigSettings() (map[string]interface{}, error) { - configPath, err := GetConfigPath() - if err != nil { - return nil, err - } - - if _, err := os.Stat(configPath); os.IsNotExist(err) { - return nil, nil - } - - data, err := os.ReadFile(configPath) - if err != nil { - return nil, err - } - - var settings map[string]interface{} - if err := json.Unmarshal(data, &settings); err != nil { - return nil, err - } - - return SanitizeSettingsMap(settings), nil -} - -func GetRedownloadWithSuffixSetting() bool { - settings, err := LoadConfigSettings() - if err != nil || settings == nil { - return false - } - - enabled, _ := settings["redownloadWithSuffix"].(bool) - return enabled -} - -func GetCustomTidalAPISetting() string { - settings, err := LoadConfigSettings() - if err != nil || settings == nil { - return "" - } - - return normalizeCustomTidalAPIValue(settings["customTidalApi"]) -} - -func normalizeExistingFileCheckMode(value string) string { - switch strings.TrimSpace(strings.ToLower(value)) { - case "isrc", "upc": - return "isrc" - default: - return "filename" - } -} - -func GetExistingFileCheckModeSetting() string { - settings, err := LoadConfigSettings() - if err != nil || settings == nil { - return "filename" - } - - rawMode, _ := settings["existingFileCheckMode"].(string) - return normalizeExistingFileCheckMode(rawMode) -} - -func GetLinkResolverSetting() string { - settings, err := LoadConfigSettings() - if err != nil || settings == nil { - return linkResolverProviderDeezerSongLink - } - - resolver, _ := settings["linkResolver"].(string) - switch strings.TrimSpace(strings.ToLower(resolver)) { - case "songlink", linkResolverProviderDeezerSongLink: - return linkResolverProviderDeezerSongLink - case "songstats": - return linkResolverProviderSongstats - case "": - return linkResolverProviderDeezerSongLink - default: - return linkResolverProviderDeezerSongLink - } -} - -func GetLinkResolverAllowFallback() bool { - settings, err := LoadConfigSettings() - if err != nil || settings == nil { - return true - } - - allowFallback, ok := settings["allowResolverFallback"].(bool) - if !ok { - return true - } - - return allowFallback -} diff --git a/backend/cover.go b/backend/cover.go deleted file mode 100644 index e40256a..0000000 --- a/backend/cover.go +++ /dev/null @@ -1,595 +0,0 @@ -package backend - -import ( - "bytes" - "fmt" - "image" - "image/png" - "io" - "net/http" - "os" - "path/filepath" - "regexp" - "strings" - "time" - - xdraw "golang.org/x/image/draw" - _ "image/jpeg" -) - -const ( - spotifySize300 = "ab67616d00001e02" - spotifySize640 = "ab67616d0000b273" - spotifySizeMax = "ab67616d000082c1" -) - -type CoverDownloadRequest struct { - CoverURL string `json:"cover_url"` - TrackName string `json:"track_name"` - ArtistName string `json:"artist_name"` - AlbumName string `json:"album_name"` - AlbumArtist string `json:"album_artist"` - ReleaseDate string `json:"release_date"` - OutputDir string `json:"output_dir"` - FilenameFormat string `json:"filename_format"` - TrackNumber bool `json:"track_number"` - Position int `json:"position"` - DiscNumber int `json:"disc_number"` -} - -type CoverDownloadResponse struct { - Success bool `json:"success"` - Message string `json:"message"` - File string `json:"file,omitempty"` - Error string `json:"error,omitempty"` - AlreadyExists bool `json:"already_exists,omitempty"` -} - -type HeaderDownloadRequest struct { - HeaderURL string `json:"header_url"` - ArtistName string `json:"artist_name"` - OutputDir string `json:"output_dir"` -} - -type HeaderDownloadResponse struct { - Success bool `json:"success"` - Message string `json:"message"` - File string `json:"file,omitempty"` - Error string `json:"error,omitempty"` - AlreadyExists bool `json:"already_exists,omitempty"` -} - -type CoverClient struct { - httpClient *http.Client -} - -func NewCoverClient() *CoverClient { - return &CoverClient{ - httpClient: &http.Client{Timeout: 30 * time.Second}, - } -} - -func buildCoverFilename(trackName, artistName, albumName, albumArtist, releaseDate, filenameFormat string, includeTrackNumber bool, position, discNumber int) string { - safeTitle := sanitizeFilename(trackName) - safeArtist := sanitizeFilename(artistName) - safeAlbum := sanitizeFilename(albumName) - safeAlbumArtist := sanitizeFilename(albumArtist) - - year := "" - if len(releaseDate) >= 4 { - year = releaseDate[:4] - } - - var filename string - - if strings.Contains(filenameFormat, "{") { - filename = filenameFormat - filename = strings.ReplaceAll(filename, "{title}", safeTitle) - filename = strings.ReplaceAll(filename, "{artist}", safeArtist) - filename = strings.ReplaceAll(filename, "{album}", safeAlbum) - filename = strings.ReplaceAll(filename, "{album_artist}", safeAlbumArtist) - filename = strings.ReplaceAll(filename, "{year}", year) - filename = strings.ReplaceAll(filename, "{date}", sanitizeFilename(releaseDate)) - - if discNumber > 0 { - filename = strings.ReplaceAll(filename, "{disc}", fmt.Sprintf("%d", discNumber)) - } else { - filename = strings.ReplaceAll(filename, "{disc}", "") - } - - if position > 0 { - filename = strings.ReplaceAll(filename, "{track}", fmt.Sprintf("%02d", position)) - } else { - - filename = regexp.MustCompile(`\{track\}\.\s*`).ReplaceAllString(filename, "") - filename = regexp.MustCompile(`\{track\}\s*-\s*`).ReplaceAllString(filename, "") - filename = regexp.MustCompile(`\{track\}\s*`).ReplaceAllString(filename, "") - } - } else { - - switch filenameFormat { - case "artist-title": - filename = fmt.Sprintf("%s - %s", safeArtist, safeTitle) - case "title-artist": - filename = fmt.Sprintf("%s - %s", safeTitle, safeArtist) - case "title": - filename = safeTitle - default: - filename = fmt.Sprintf("%s - %s", safeTitle, safeArtist) - } - - if includeTrackNumber && position > 0 { - filename = fmt.Sprintf("%02d - %s", position, filename) - } - } - - return filename + ".jpg" -} - -func convertSmallToMedium(imageURL string) string { - if strings.Contains(imageURL, spotifySize300) { - return strings.Replace(imageURL, spotifySize300, spotifySize640, 1) - } - return imageURL -} - -func (c *CoverClient) getMaxResolutionURL(imageURL string) string { - - mediumURL := convertSmallToMedium(imageURL) - if strings.Contains(mediumURL, spotifySize640) { - return strings.Replace(mediumURL, spotifySize640, spotifySizeMax, 1) - } - return mediumURL -} - -func (c *CoverClient) DownloadCoverToPath(coverURL, outputPath string, embedMaxQualityCover bool) error { - if coverURL == "" { - return fmt.Errorf("cover URL is required") - } - - downloadURL := convertSmallToMedium(coverURL) - if embedMaxQualityCover { - downloadURL = c.getMaxResolutionURL(downloadURL) - } - - resp, err := c.httpClient.Get(downloadURL) - if err != nil { - return fmt.Errorf("failed to download cover: %v", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("failed to download cover: HTTP %d", resp.StatusCode) - } - - file, err := os.Create(outputPath) - if err != nil { - return fmt.Errorf("failed to create file: %v", err) - } - defer file.Close() - - _, err = io.Copy(file, resp.Body) - if err != nil { - return fmt.Errorf("failed to write cover file: %v", err) - } - - return nil -} - -func (c *CoverClient) ApplyMacOSFLACFileIcon(filePath, coverURL string, iconSize int, embedMaxQualityCover bool) error { - if filePath == "" { - return fmt.Errorf("file path is required") - } - if coverURL == "" { - return fmt.Errorf("cover URL is required") - } - - tmpFile, err := os.CreateTemp("", "spotiflac-file-icon-*.jpg") - if err != nil { - return fmt.Errorf("failed to create temporary cover file: %w", err) - } - tmpPath := tmpFile.Name() - tmpFile.Close() - defer os.Remove(tmpPath) - - if err := c.DownloadCoverToPath(coverURL, tmpPath, embedMaxQualityCover); err != nil { - return err - } - - return SetMacOSFileIconFromImage(filePath, tmpPath, iconSize) -} - -func ResizeImageForIcon(sourcePath string, iconSize int) (string, error) { - if sourcePath == "" { - return "", fmt.Errorf("source image path is required") - } - if iconSize <= 0 { - iconSize = 256 - } - - in, err := os.Open(sourcePath) - if err != nil { - return "", fmt.Errorf("failed to open source image: %w", err) - } - defer in.Close() - - srcImage, _, err := image.Decode(in) - if err != nil { - return "", fmt.Errorf("failed to decode source image: %w", err) - } - - dst := image.NewRGBA(image.Rect(0, 0, iconSize, iconSize)) - xdraw.CatmullRom.Scale(dst, dst.Bounds(), srcImage, srcImage.Bounds(), xdraw.Over, nil) - - tmpFile, err := os.CreateTemp("", "spotiflac-resized-icon-*.png") - if err != nil { - return "", fmt.Errorf("failed to create resized icon temp file: %w", err) - } - tmpPath := tmpFile.Name() - defer tmpFile.Close() - - var encoded bytes.Buffer - if err := png.Encode(&encoded, dst); err != nil { - return "", fmt.Errorf("failed to encode resized icon image: %w", err) - } - if _, err := io.Copy(tmpFile, &encoded); err != nil { - return "", fmt.Errorf("failed to write resized icon image: %w", err) - } - - return tmpPath, nil -} - -func (c *CoverClient) DownloadCover(req CoverDownloadRequest) (*CoverDownloadResponse, error) { - if req.CoverURL == "" { - return &CoverDownloadResponse{ - Success: false, - Error: "Cover URL is required", - }, fmt.Errorf("cover URL is required") - } - - outputDir := req.OutputDir - if outputDir == "" { - outputDir = GetDefaultMusicPath() - } else { - outputDir = NormalizePath(outputDir) - } - - if err := os.MkdirAll(outputDir, 0755); err != nil { - return &CoverDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to create output directory: %v", err), - }, err - } - - filenameFormat := req.FilenameFormat - if filenameFormat == "" { - filenameFormat = "title-artist" - } - filename := buildCoverFilename(req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, filenameFormat, req.TrackNumber, req.Position, req.DiscNumber) - filePath := filepath.Join(outputDir, filename) - - if fileInfo, err := os.Stat(filePath); err == nil && fileInfo.Size() > 0 { - return &CoverDownloadResponse{ - Success: true, - Message: "Cover file already exists", - File: filePath, - AlreadyExists: true, - }, nil - } - - downloadURL := c.getMaxResolutionURL(req.CoverURL) - - resp, err := c.httpClient.Get(downloadURL) - if err != nil { - return &CoverDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to download cover: %v", err), - }, err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return &CoverDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to download cover: HTTP %d", resp.StatusCode), - }, fmt.Errorf("HTTP %d", resp.StatusCode) - } - - file, err := os.Create(filePath) - if err != nil { - return &CoverDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to create file: %v", err), - }, err - } - defer file.Close() - - _, err = io.Copy(file, resp.Body) - if err != nil { - return &CoverDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to write cover file: %v", err), - }, err - } - - return &CoverDownloadResponse{ - Success: true, - Message: "Cover downloaded successfully", - File: filePath, - }, nil -} - -func (c *CoverClient) DownloadHeader(req HeaderDownloadRequest) (*HeaderDownloadResponse, error) { - if req.HeaderURL == "" { - return &HeaderDownloadResponse{ - Success: false, - Error: "Header URL is required", - }, fmt.Errorf("header URL is required") - } - - if req.ArtistName == "" { - return &HeaderDownloadResponse{ - Success: false, - Error: "Artist name is required", - }, fmt.Errorf("artist name is required") - } - - outputDir := req.OutputDir - if outputDir == "" { - outputDir = GetDefaultMusicPath() - } else { - outputDir = NormalizePath(outputDir) - } - - artistFolder := filepath.Join(outputDir, sanitizeFilename(req.ArtistName)) - if err := os.MkdirAll(artistFolder, 0755); err != nil { - return &HeaderDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to create artist folder: %v", err), - }, err - } - - filename := sanitizeFilename(req.ArtistName) + "_Header.jpg" - filePath := filepath.Join(artistFolder, filename) - - if fileInfo, err := os.Stat(filePath); err == nil && fileInfo.Size() > 0 { - return &HeaderDownloadResponse{ - Success: true, - Message: "Header file already exists", - File: filePath, - AlreadyExists: true, - }, nil - } - - resp, err := c.httpClient.Get(req.HeaderURL) - if err != nil { - return &HeaderDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to download header: %v", err), - }, err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return &HeaderDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to download header: HTTP %d", resp.StatusCode), - }, fmt.Errorf("HTTP %d", resp.StatusCode) - } - - file, err := os.Create(filePath) - if err != nil { - return &HeaderDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to create file: %v", err), - }, err - } - defer file.Close() - - _, err = io.Copy(file, resp.Body) - if err != nil { - return &HeaderDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to write header file: %v", err), - }, err - } - - return &HeaderDownloadResponse{ - Success: true, - Message: "Header downloaded successfully", - File: filePath, - }, nil -} - -type GalleryImageDownloadRequest struct { - ImageURL string `json:"image_url"` - ArtistName string `json:"artist_name"` - ImageIndex int `json:"image_index"` - OutputDir string `json:"output_dir"` -} - -type GalleryImageDownloadResponse struct { - Success bool `json:"success"` - Message string `json:"message"` - File string `json:"file,omitempty"` - Error string `json:"error,omitempty"` - AlreadyExists bool `json:"already_exists,omitempty"` -} - -func (c *CoverClient) DownloadGalleryImage(req GalleryImageDownloadRequest) (*GalleryImageDownloadResponse, error) { - if req.ImageURL == "" { - return &GalleryImageDownloadResponse{ - Success: false, - Error: "Image URL is required", - }, fmt.Errorf("image URL is required") - } - - if req.ArtistName == "" { - return &GalleryImageDownloadResponse{ - Success: false, - Error: "Artist name is required", - }, fmt.Errorf("artist name is required") - } - - outputDir := req.OutputDir - if outputDir == "" { - outputDir = GetDefaultMusicPath() - } else { - outputDir = NormalizePath(outputDir) - } - - artistFolder := filepath.Join(outputDir, sanitizeFilename(req.ArtistName)) - if err := os.MkdirAll(artistFolder, 0755); err != nil { - return &GalleryImageDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to create artist folder: %v", err), - }, err - } - - filename := sanitizeFilename(req.ArtistName) + fmt.Sprintf("_Gallery_%d.jpg", req.ImageIndex+1) - filePath := filepath.Join(artistFolder, filename) - - if fileInfo, err := os.Stat(filePath); err == nil && fileInfo.Size() > 0 { - return &GalleryImageDownloadResponse{ - Success: true, - Message: "Gallery image file already exists", - File: filePath, - AlreadyExists: true, - }, nil - } - - resp, err := c.httpClient.Get(req.ImageURL) - if err != nil { - return &GalleryImageDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to download gallery image: %v", err), - }, err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return &GalleryImageDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to download gallery image: HTTP %d", resp.StatusCode), - }, fmt.Errorf("HTTP %d", resp.StatusCode) - } - - file, err := os.Create(filePath) - if err != nil { - return &GalleryImageDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to create file: %v", err), - }, err - } - defer file.Close() - - _, err = io.Copy(file, resp.Body) - if err != nil { - return &GalleryImageDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to write gallery image file: %v", err), - }, err - } - - return &GalleryImageDownloadResponse{ - Success: true, - Message: "Gallery image downloaded successfully", - File: filePath, - }, nil -} - -type AvatarDownloadRequest struct { - AvatarURL string `json:"avatar_url"` - ArtistName string `json:"artist_name"` - OutputDir string `json:"output_dir"` -} - -type AvatarDownloadResponse struct { - Success bool `json:"success"` - Message string `json:"message"` - File string `json:"file,omitempty"` - Error string `json:"error,omitempty"` - AlreadyExists bool `json:"already_exists,omitempty"` -} - -func (c *CoverClient) DownloadAvatar(req AvatarDownloadRequest) (*AvatarDownloadResponse, error) { - if req.AvatarURL == "" { - return &AvatarDownloadResponse{ - Success: false, - Error: "Avatar URL is required", - }, fmt.Errorf("avatar URL is required") - } - - if req.ArtistName == "" { - return &AvatarDownloadResponse{ - Success: false, - Error: "Artist name is required", - }, fmt.Errorf("artist name is required") - } - - outputDir := req.OutputDir - if outputDir == "" { - outputDir = GetDefaultMusicPath() - } else { - outputDir = NormalizePath(outputDir) - } - - artistFolder := filepath.Join(outputDir, sanitizeFilename(req.ArtistName)) - if err := os.MkdirAll(artistFolder, 0755); err != nil { - return &AvatarDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to create artist folder: %v", err), - }, err - } - - filename := sanitizeFilename(req.ArtistName) + "_Avatar.jpg" - filePath := filepath.Join(artistFolder, filename) - - if fileInfo, err := os.Stat(filePath); err == nil && fileInfo.Size() > 0 { - return &AvatarDownloadResponse{ - Success: true, - Message: "Avatar file already exists", - File: filePath, - AlreadyExists: true, - }, nil - } - - resp, err := c.httpClient.Get(req.AvatarURL) - if err != nil { - return &AvatarDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to download avatar: %v", err), - }, err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return &AvatarDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to download avatar: HTTP %d", resp.StatusCode), - }, fmt.Errorf("HTTP %d", resp.StatusCode) - } - - file, err := os.Create(filePath) - if err != nil { - return &AvatarDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to create file: %v", err), - }, err - } - defer file.Close() - - _, err = io.Copy(file, resp.Body) - if err != nil { - return &AvatarDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to write avatar file: %v", err), - }, err - } - - return &AvatarDownloadResponse{ - Success: true, - Message: "Avatar downloaded successfully", - File: filePath, - }, nil -} diff --git a/backend/download_validation.go b/backend/download_validation.go deleted file mode 100644 index a465211..0000000 --- a/backend/download_validation.go +++ /dev/null @@ -1,44 +0,0 @@ -package backend - -import ( - "fmt" - "math" -) - -const ( - previewMaxSeconds = 35 - previewExpectedMinSeconds = 60 - largeMismatchMinExpected = 90 - minAllowedDurationDiff = 15 - durationDiffRatio = 0.25 -) - -func ValidateDownloadedTrackDuration(filePath string, expectedSeconds int) (bool, error) { - if filePath == "" || expectedSeconds <= 0 { - return false, nil - } - - actualDuration, err := GetAudioDuration(filePath) - if err != nil || actualDuration <= 0 { - return false, nil - } - - actualSeconds := int(math.Round(actualDuration)) - if actualSeconds <= 0 { - return false, nil - } - - if expectedSeconds >= previewExpectedMinSeconds && actualSeconds <= previewMaxSeconds { - return true, fmt.Errorf("detected preview/sample download: file is %ds, expected about %ds. file was removed", actualSeconds, expectedSeconds) - } - - if expectedSeconds >= largeMismatchMinExpected { - allowedDiff := int(math.Max(minAllowedDurationDiff, math.Round(float64(expectedSeconds)*durationDiffRatio))) - diff := int(math.Abs(float64(actualSeconds - expectedSeconds))) - if diff > allowedDiff { - return true, fmt.Errorf("downloaded file duration mismatch: file is %ds, expected about %ds. file was removed", actualSeconds, expectedSeconds) - } - } - - return true, nil -} diff --git a/backend/ffmpeg.go b/backend/ffmpeg.go deleted file mode 100644 index 04516a0..0000000 --- a/backend/ffmpeg.go +++ /dev/null @@ -1,947 +0,0 @@ -package backend - -import ( - "archive/tar" - "archive/zip" - - "fmt" - "io" - "net/http" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "sync" - "time" - - "github.com/ulikunitz/xz" - "golang.org/x/text/unicode/norm" -) - -type executableCandidate struct { - path string - source string -} - -func ValidateExecutable(path string) error { - cleanedPath := filepath.Clean(path) - if cleanedPath == "" { - return fmt.Errorf("empty path") - } - - if !filepath.IsAbs(cleanedPath) { - return fmt.Errorf("path must be absolute: %s", path) - } - - info, err := os.Stat(cleanedPath) - if err != nil { - return fmt.Errorf("failed to stat file: %w", err) - } - - if info.IsDir() { - return fmt.Errorf("path is a directory: %s", path) - } - - if runtime.GOOS != "windows" { - if info.Mode()&0111 == 0 { - return fmt.Errorf("file is not executable: %s", path) - } - } - - base := filepath.Base(cleanedPath) - validNames := map[string]bool{ - "ffmpeg": true, - "ffmpeg.exe": true, - "ffprobe": true, - "ffprobe.exe": true, - } - if !validNames[base] { - return fmt.Errorf("invalid executable name: %s", base) - } - - return nil -} - -func GetAppDir() (string, error) { - homeDir, err := os.UserHomeDir() - if err != nil { - return "", fmt.Errorf("failed to get home directory: %w", err) - } - return filepath.Join(homeDir, ".spotiflac"), nil -} - -func EnsureAppDir() (string, error) { - appDir, err := GetAppDir() - if err != nil { - return "", err - } - - if err := os.MkdirAll(appDir, 0o755); err != nil { - return "", fmt.Errorf("failed to create app directory: %w", err) - } - - return appDir, nil -} - -func GetFFmpegDir() (string, error) { - return EnsureAppDir() -} - -func copyExecutable(src, dst string) error { - if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil { - return err - } - - in, err := os.Open(src) - if err != nil { - return err - } - defer in.Close() - - out, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o755) - if err != nil { - return err - } - defer out.Close() - - if _, err = io.Copy(out, in); err != nil { - return err - } - - if err := out.Sync(); err != nil { - return err - } - - return prepareExecutableForUse(dst) -} - -func appendExecutableCandidate(candidates []executableCandidate, seen map[string]struct{}, path, source string) []executableCandidate { - cleanedPath := filepath.Clean(strings.TrimSpace(path)) - if cleanedPath == "" { - return candidates - } - if _, exists := seen[cleanedPath]; exists { - return candidates - } - - seen[cleanedPath] = struct{}{} - return append(candidates, executableCandidate{ - path: cleanedPath, - source: source, - }) -} - -func resolveSystemExecutable(executableName string) string { - if runtime.GOOS == "darwin" { - candidates := []string{ - "/opt/homebrew/bin/" + executableName, - "/usr/local/bin/" + executableName, - } - for _, candidate := range candidates { - if _, err := os.Stat(candidate); err == nil { - return candidate - } - } - } - - if runtime.GOOS != "windows" { - path, err := exec.Command("which", executableName).Output() - if err == nil { - trimmed := strings.TrimSpace(string(path)) - if trimmed != "" { - return trimmed - } - } - } - - path, err := exec.LookPath(executableName) - if err == nil { - return path - } - - return "" -} - -func runExecutableVersionCheck(path string) error { - cmd := exec.Command(path, "-version") - setHideWindow(cmd) - return cmd.Run() -} - -func removeMacOSQuarantineAttribute(path string) error { - cmd := exec.Command("xattr", "-d", "com.apple.quarantine", path) - setHideWindow(cmd) - output, err := cmd.CombinedOutput() - if err == nil { - return nil - } - - trimmedOutput := strings.TrimSpace(string(output)) - lowerOutput := strings.ToLower(trimmedOutput) - if strings.Contains(lowerOutput, "no such xattr") || strings.Contains(lowerOutput, "attribute not found") { - return nil - } - - if trimmedOutput != "" { - return fmt.Errorf("%w: %s", err, trimmedOutput) - } - - return err -} - -func prepareExecutableForUse(path string) error { - cleanedPath := filepath.Clean(strings.TrimSpace(path)) - if cleanedPath == "" { - return fmt.Errorf("empty path") - } - - if runtime.GOOS == "windows" { - return nil - } - - if err := os.Chmod(cleanedPath, 0755); err != nil { - return fmt.Errorf("failed to mark executable: %w", err) - } - - if runtime.GOOS == "darwin" { - if err := removeMacOSQuarantineAttribute(cleanedPath); err != nil { - fmt.Printf("[FFmpeg] Warning: failed to remove macOS quarantine from %s: %v\n", cleanedPath, err) - } - } - - return nil -} - -func resolveExecutablePath(executableName string) (string, string, error) { - ffmpegDir, err := GetFFmpegDir() - if err != nil { - return "", "", err - } - - localPath := filepath.Join(ffmpegDir, executableName) - nextDir := filepath.Join(filepath.Dir(ffmpegDir), ".spotiflac-next") - nextPath := filepath.Join(nextDir, executableName) - localExists := false - candidates := make([]executableCandidate, 0, 3) - seen := make(map[string]struct{}, 3) - - if systemPath := resolveSystemExecutable(executableName); systemPath != "" { - candidates = appendExecutableCandidate(candidates, seen, systemPath, "system") - } - - if _, err := os.Stat(localPath); err == nil { - localExists = true - candidates = appendExecutableCandidate(candidates, seen, localPath, "local") - } - - if !localExists { - if _, err := os.Stat(nextPath); err == nil { - if copyErr := copyExecutable(nextPath, localPath); copyErr == nil { - fmt.Printf("[FFmpeg] Copied %s from SpotiFLAC-Next folder\n", executableName) - candidates = appendExecutableCandidate(candidates, seen, localPath, "migrated") - } - } - } - - var lastErr error - for _, candidate := range candidates { - if candidate.source != "system" { - if err := prepareExecutableForUse(candidate.path); err != nil { - lastErr = err - fmt.Printf("[FFmpeg] Skipping %s %s: %v\n", candidate.source, candidate.path, err) - continue - } - } - - if err := ValidateExecutable(candidate.path); err != nil { - lastErr = err - fmt.Printf("[FFmpeg] Skipping %s %s: %v\n", candidate.source, candidate.path, err) - continue - } - - if err := runExecutableVersionCheck(candidate.path); err != nil { - lastErr = err - fmt.Printf("[FFmpeg] Skipping %s %s: %v\n", candidate.source, candidate.path, err) - continue - } - - return candidate.path, localPath, nil - } - - if len(candidates) > 0 { - if lastErr != nil { - return "", localPath, fmt.Errorf("no working %s executable found: %w", executableName, lastErr) - } - return "", localPath, fmt.Errorf("no working %s executable found", executableName) - } - - return "", localPath, fmt.Errorf("%s not found in app directory or system path", executableName) -} - -func GetFFmpegPath() (string, error) { - ffmpegName := "ffmpeg" - if runtime.GOOS == "windows" { - ffmpegName = "ffmpeg.exe" - } - - path, localPath, err := resolveExecutablePath(ffmpegName) - if err != nil { - if localPath != "" { - return localPath, err - } - return "", err - } - - return path, nil -} - -func GetFFprobePath() (string, error) { - ffprobeName := "ffprobe" - if runtime.GOOS == "windows" { - ffprobeName = "ffprobe.exe" - } - - path, localPath, err := resolveExecutablePath(ffprobeName) - if err != nil { - if localPath != "" { - return localPath, err - } - return "", err - } - - return path, nil -} - -func IsFFprobeInstalled() (bool, error) { - _, err := GetFFprobePath() - return err == nil, nil -} - -func IsFFmpegInstalled() (bool, error) { - if _, err := GetFFmpegPath(); err != nil { - return false, nil - } - - return IsFFprobeInstalled() -} - -func GetBrewPath() string { - brewPaths := []string{ - "/opt/homebrew/bin/brew", - "/usr/local/bin/brew", - } - - for _, path := range brewPaths { - if _, err := os.Stat(path); err == nil { - return path - } - } - - return "" -} - -func IsBrewFFmpegInstalled() (bool, error) { - brewPath := GetBrewPath() - if brewPath == "" { - return false, nil - } - - cmd := exec.Command(brewPath, "list", "ffmpeg") - setHideWindow(cmd) - err := cmd.Run() - return err == nil, nil -} - -func InstallFFmpegWithBrew(progressCallback func(int, string)) error { - brewPath := GetBrewPath() - if brewPath == "" { - return fmt.Errorf("brew not found") - } - - progressCallback(10, "Installing FFmpeg via Homebrew...") - - cmd := exec.Command(brewPath, "install", "ffmpeg") - setHideWindow(cmd) - output, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("failed to install ffmpeg: %w - %s", err, string(output)) - } - - progressCallback(100, "done") - - return nil -} - -const ffmpegReleaseBaseURL = "https://github.com/afkarxyz/ffmpeg-binaries/releases/download/v8.1" - -func buildFFmpegReleaseURL(assetName string) string { - return ffmpegReleaseBaseURL + "/" + assetName -} - -func getFFmpegDownloadURLs() ([]string, []string, error) { - switch runtime.GOOS { - case "windows": - return []string{buildFFmpegReleaseURL("ffmpeg-windows.zip")}, []string{buildFFmpegReleaseURL("ffprobe-windows.zip")}, nil - case "linux": - switch runtime.GOARCH { - case "amd64": - return []string{buildFFmpegReleaseURL("ffmpeg-linux-amd64.zip")}, []string{buildFFmpegReleaseURL("ffprobe-linux-amd64.zip")}, nil - case "arm64": - return []string{buildFFmpegReleaseURL("ffmpeg-linux-arm64v8.zip")}, []string{buildFFmpegReleaseURL("ffprobe-linux-arm64v8.zip")}, nil - default: - return nil, nil, fmt.Errorf("unsupported Linux architecture: %s", runtime.GOARCH) - } - case "darwin": - switch runtime.GOARCH { - case "amd64": - return []string{buildFFmpegReleaseURL("ffmpeg-macos-amd64.zip")}, []string{buildFFmpegReleaseURL("ffprobe-macos-amd64.zip")}, nil - case "arm64": - return []string{buildFFmpegReleaseURL("ffmpeg-macos-arm64.zip")}, []string{buildFFmpegReleaseURL("ffprobe-macos-arm64.zip")}, nil - default: - return nil, nil, fmt.Errorf("unsupported macOS architecture: %s", runtime.GOARCH) - } - default: - return nil, nil, fmt.Errorf("unsupported operating system: %s", runtime.GOOS) - } -} - -func DownloadFFmpeg(progressCallback func(int)) error { - - SetDownloadProgress(0) - SetDownloadSpeed(0) - SetDownloading(true) - defer SetDownloading(false) - - ffmpegDir, err := GetFFmpegDir() - if err != nil { - return err - } - - if err := os.MkdirAll(ffmpegDir, 0755); err != nil { - return fmt.Errorf("failed to create ffmpeg directory: %w", err) - } - - ffmpegInstalled, _ := IsFFmpegInstalled() - ffprobeInstalled, _ := IsFFprobeInstalled() - - ffmpegURLs, ffprobeURLs, err := getFFmpegDownloadURLs() - if err != nil { - return err - } - - if !ffmpegInstalled && !ffprobeInstalled { - if err := downloadWithFallback(ffmpegURLs, ffmpegDir, progressCallback, 0, 50); err != nil { - return err - } - if err := downloadWithFallback(ffprobeURLs, ffmpegDir, progressCallback, 50, 100); err != nil { - return err - } - return nil - } - - if !ffmpegInstalled { - return downloadWithFallback(ffmpegURLs, ffmpegDir, progressCallback, 0, 100) - } - - if !ffprobeInstalled { - return downloadWithFallback(ffprobeURLs, ffmpegDir, progressCallback, 0, 100) - } - - return nil -} - -func downloadWithFallback(urls []string, destDir string, progressCallback func(int), start, end int) error { - var lastErr error - for _, url := range urls { - fmt.Printf("[FFmpeg] Trying to download from: %s\n", url) - err := downloadAndExtract(url, destDir, progressCallback, start, end) - if err == nil { - return nil - } - lastErr = err - fmt.Printf("[FFmpeg] Attempt failed: %v\n", err) - } - return fmt.Errorf("all download attempts failed: %w", lastErr) -} - -func downloadAndExtract(url, destDir string, progressCallback func(int), progressStart, progressEnd int) error { - - tmpFile, err := os.CreateTemp("", "ffmpeg-*") - if err != nil { - return fmt.Errorf("failed to create temp file: %w", err) - } - defer os.Remove(tmpFile.Name()) - defer tmpFile.Close() - - client := &http.Client{} - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return fmt.Errorf("failed to create request: %w", err) - } - req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36") - - resp, err := client.Do(req) - if err != nil { - return fmt.Errorf("failed to download: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("failed to download: HTTP %d", resp.StatusCode) - } - - totalSize := resp.ContentLength - var downloaded int64 - lastTime := time.Now() - var lastBytes int64 - - if totalSize > 0 { - totalSizeMB := float64(totalSize) / (1024 * 1024) - fmt.Printf("[FFmpeg] Total size: %.2f MB\n", totalSizeMB) - } else { - fmt.Printf("[FFmpeg] Downloading... (size unknown)\n") - } - - buf := make([]byte, 32*1024) - for { - n, err := resp.Body.Read(buf) - if n > 0 { - _, writeErr := tmpFile.Write(buf[:n]) - if writeErr != nil { - return fmt.Errorf("failed to write to temp file: %w", writeErr) - } - downloaded += int64(n) - - mbDownloaded := float64(downloaded) / (1024 * 1024) - now := time.Now() - timeDiff := now.Sub(lastTime).Seconds() - var speedMBps float64 - - if timeDiff > 0.1 { - bytesDiff := float64(downloaded - lastBytes) - speedMBps = (bytesDiff / (1024 * 1024)) / timeDiff - lastTime = now - lastBytes = downloaded - } - - SetDownloadProgress(mbDownloaded) - if speedMBps > 0 { - SetDownloadSpeed(speedMBps) - } - - if totalSize > 0 && progressCallback != nil { - rawProgress := float64(downloaded) / float64(totalSize) - scaledProgress := progressStart + int(rawProgress*float64(progressEnd-progressStart)) - progressCallback(scaledProgress) - } - - if totalSize > 0 { - percent := float64(downloaded) * 100 / float64(totalSize) - if speedMBps > 0 { - fmt.Printf("\r[FFmpeg] Downloading: %.2f MB / %.2f MB (%.1f%%) - %.2f MB/s", - mbDownloaded, float64(totalSize)/(1024*1024), percent, speedMBps) - } else { - fmt.Printf("\r[FFmpeg] Downloading: %.2f MB / %.2f MB (%.1f%%)", - mbDownloaded, float64(totalSize)/(1024*1024), percent) - } - } else { - if speedMBps > 0 { - fmt.Printf("\r[FFmpeg] Downloading: %.2f MB - %.2f MB/s", mbDownloaded, speedMBps) - } else { - fmt.Printf("\r[FFmpeg] Downloading: %.2f MB", mbDownloaded) - } - } - } - if err == io.EOF { - break - } - if err != nil { - return fmt.Errorf("failed to read response: %w", err) - } - } - - tmpFile.Close() - - if totalSize > 0 { - fmt.Printf("\r[FFmpeg] Download complete: %.2f MB / %.2f MB (100%%) \n", - float64(downloaded)/(1024*1024), float64(totalSize)/(1024*1024)) - } else { - fmt.Printf("\r[FFmpeg] Download complete: %.2f MB \n", float64(downloaded)/(1024*1024)) - } - fmt.Printf("[FFmpeg] Extracting...\n") - - if strings.HasSuffix(url, ".tar.xz") { - return extractTarXz(tmpFile.Name(), destDir) - } - if strings.HasSuffix(url, ".zip") { - return extractZip(tmpFile.Name(), destDir) - } - return fmt.Errorf("unsupported archive format for %s", url) -} - -func extractZip(zipPath, destDir string) error { - r, err := zip.OpenReader(zipPath) - if err != nil { - return fmt.Errorf("failed to open zip: %w", err) - } - defer r.Close() - - ffmpegName := "ffmpeg" - ffprobeName := "ffprobe" - if runtime.GOOS == "windows" { - ffmpegName = "ffmpeg.exe" - ffprobeName = "ffprobe.exe" - } - - foundFFmpeg := false - foundFFprobe := false - - for _, f := range r.File { - baseName := filepath.Base(f.Name) - if f.FileInfo().IsDir() { - continue - } - - var destPath string - if baseName == ffmpegName { - destPath = filepath.Join(destDir, ffmpegName) - foundFFmpeg = true - } else if baseName == ffprobeName { - destPath = filepath.Join(destDir, ffprobeName) - foundFFprobe = true - } else { - - continue - } - - fmt.Printf("[FFmpeg] Found: %s\n", f.Name) - - rc, err := f.Open() - if err != nil { - return fmt.Errorf("failed to open file in zip: %w", err) - } - - outFile, err := os.OpenFile(destPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755) - if err != nil { - rc.Close() - return fmt.Errorf("failed to create output file: %w", err) - } - - _, err = io.Copy(outFile, rc) - rc.Close() - outFile.Close() - - if err != nil { - return fmt.Errorf("failed to extract file: %w", err) - } - - if err := prepareExecutableForUse(destPath); err != nil { - return fmt.Errorf("failed to prepare extracted executable: %w", err) - } - - fmt.Printf("[FFmpeg] Extracted to: %s\n", destPath) - } - - if !foundFFmpeg && !foundFFprobe { - return fmt.Errorf("neither ffmpeg nor ffprobe found in archive") - } - - if foundFFmpeg { - fmt.Printf("[FFmpeg] ffmpeg extracted successfully\n") - } - if foundFFprobe { - fmt.Printf("[FFmpeg] ffprobe extracted successfully\n") - } - - return nil -} - -func extractTarXz(tarXzPath, destDir string) error { - file, err := os.Open(tarXzPath) - if err != nil { - return fmt.Errorf("failed to open tar.xz: %w", err) - } - defer file.Close() - - xzReader, err := xz.NewReader(file) - if err != nil { - return fmt.Errorf("failed to create xz reader: %w", err) - } - - tarReader := tar.NewReader(xzReader) - - ffmpegName := "ffmpeg" - ffprobeName := "ffprobe" - foundFFmpeg := false - foundFFprobe := false - - for { - header, err := tarReader.Next() - if err == io.EOF { - break - } - if err != nil { - return fmt.Errorf("failed to read tar: %w", err) - } - - if header.Typeflag != tar.TypeReg { - continue - } - - baseName := filepath.Base(header.Name) - var destPath string - - if baseName == ffmpegName { - destPath = filepath.Join(destDir, ffmpegName) - foundFFmpeg = true - } else if baseName == ffprobeName { - destPath = filepath.Join(destDir, ffprobeName) - foundFFprobe = true - } else { - - continue - } - - fmt.Printf("[FFmpeg] Found: %s\n", header.Name) - - outFile, err := os.OpenFile(destPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755) - if err != nil { - return fmt.Errorf("failed to create output file: %w", err) - } - - _, err = io.Copy(outFile, tarReader) - outFile.Close() - - if err != nil { - return fmt.Errorf("failed to extract file: %w", err) - } - - if err := prepareExecutableForUse(destPath); err != nil { - return fmt.Errorf("failed to prepare extracted executable: %w", err) - } - - fmt.Printf("[FFmpeg] Extracted to: %s\n", destPath) - } - - if !foundFFmpeg && !foundFFprobe { - return fmt.Errorf("neither ffmpeg nor ffprobe found in archive") - } - - if foundFFmpeg { - fmt.Printf("[FFmpeg] ffmpeg extracted successfully\n") - } - if foundFFprobe { - fmt.Printf("[FFmpeg] ffprobe extracted successfully\n") - } - - return nil -} - -type ConvertAudioRequest struct { - InputFiles []string `json:"input_files"` - OutputFormat string `json:"output_format"` - Bitrate string `json:"bitrate"` - Codec string `json:"codec"` -} - -type ConvertAudioResult struct { - InputFile string `json:"input_file"` - OutputFile string `json:"output_file"` - Success bool `json:"success"` - Error string `json:"error,omitempty"` -} - -func ConvertAudio(req ConvertAudioRequest) ([]ConvertAudioResult, error) { - ffmpegPath, err := GetFFmpegPath() - if err != nil { - return nil, fmt.Errorf("failed to get ffmpeg path: %w", err) - } - - if err := ValidateExecutable(ffmpegPath); err != nil { - return nil, fmt.Errorf("invalid ffmpeg executable: %w", err) - } - - installed, err := IsFFmpegInstalled() - if err != nil || !installed { - return nil, fmt.Errorf("ffmpeg is not installed") - } - - results := make([]ConvertAudioResult, len(req.InputFiles)) - var wg sync.WaitGroup - var mu sync.Mutex - - for i, inputFile := range req.InputFiles { - wg.Add(1) - go func(idx int, inputFile string) { - defer wg.Done() - - result := ConvertAudioResult{ - InputFile: inputFile, - } - - inputExt := strings.ToLower(filepath.Ext(inputFile)) - baseName := strings.TrimSuffix(filepath.Base(inputFile), inputExt) - inputDir := filepath.Dir(inputFile) - - outputFormatUpper := strings.ToUpper(req.OutputFormat) - outputDir := filepath.Join(inputDir, outputFormatUpper) - - if err := os.MkdirAll(outputDir, 0755); err != nil { - result.Error = fmt.Sprintf("failed to create output directory: %v", err) - result.Success = false - mu.Lock() - results[idx] = result - mu.Unlock() - return - } - - outputExt := "." + strings.ToLower(req.OutputFormat) - outputFile := filepath.Join(outputDir, baseName+outputExt) - outputFile = norm.NFC.String(outputFile) - - if inputExt == outputExt { - result.Error = "Input and output formats are the same" - result.Success = false - mu.Lock() - results[idx] = result - mu.Unlock() - return - } - - result.OutputFile = outputFile - - var coverArtPath string - var lyrics string - var inputMetadata Metadata - - inputMetadata, err = ExtractFullMetadataFromFile(inputFile) - if err != nil { - fmt.Printf("[FFmpeg] Warning: Failed to extract metadata from %s: %v\n", inputFile, err) - } - - inputFile = norm.NFC.String(inputFile) - coverArtPath, err = ExtractCoverArt(inputFile) - if err != nil { - fmt.Printf("[FFmpeg] Warning: Failed to extract cover art from %s: %v\n", inputFile, err) - } - lyrics, err = ExtractLyrics(inputFile) - if err != nil { - fmt.Printf("[FFmpeg] Warning: Failed to extract lyrics from %s: %v\n", inputFile, err) - } else if lyrics != "" { - fmt.Printf("[FFmpeg] Lyrics extracted from %s: %d characters\n", inputFile, len(lyrics)) - } else { - fmt.Printf("[FFmpeg] No lyrics found in %s\n", inputFile) - } - - inputMetadata.Lyrics = lyrics - - args := []string{ - "-i", inputFile, - "-y", - } - - switch req.OutputFormat { - case "mp3": - args = append(args, - "-codec:a", "libmp3lame", - "-b:a", req.Bitrate, - "-map", "0:a", - "-id3v2_version", "3", - ) - case "m4a": - - codec := req.Codec - if codec == "" { - codec = "aac" - } - - if codec == "alac" { - - args = append(args, - "-codec:a", "alac", - "-map", "0:a", - ) - } else { - - args = append(args, - "-codec:a", "aac", - "-b:a", req.Bitrate, - "-map", "0:a", - ) - } - } - - args = append(args, outputFile) - - fmt.Printf("[FFmpeg] Converting: %s -> %s\n", inputFile, outputFile) - - cmd := exec.Command(ffmpegPath, args...) - - setHideWindow(cmd) - output, err := cmd.CombinedOutput() - if err != nil { - result.Error = fmt.Sprintf("conversion failed: %s - %s", err.Error(), string(output)) - result.Success = false - mu.Lock() - results[idx] = result - mu.Unlock() - - if coverArtPath != "" { - os.Remove(coverArtPath) - } - return - } - - if err := EmbedMetadataToConvertedFile(outputFile, inputMetadata, coverArtPath); err != nil { - fmt.Printf("[FFmpeg] Warning: Failed to embed metadata: %v\n", err) - } else { - fmt.Printf("[FFmpeg] Metadata embedded successfully\n") - } - - if lyrics != "" { - if err := EmbedLyricsOnlyUniversal(outputFile, lyrics); err != nil { - fmt.Printf("[FFmpeg] Warning: Failed to embed lyrics: %v\n", err) - } else { - fmt.Printf("[FFmpeg] Lyrics embedded successfully\n") - } - } - - if coverArtPath != "" { - os.Remove(coverArtPath) - } - - result.Success = true - fmt.Printf("[FFmpeg] Successfully converted: %s\n", outputFile) - - mu.Lock() - results[idx] = result - mu.Unlock() - }(i, inputFile) - } - - wg.Wait() - return results, nil -} - -type AudioFileInfo struct { - Path string `json:"path"` - Filename string `json:"filename"` - Format string `json:"format"` - Size int64 `json:"size"` -} - -func GetAudioFileInfo(filePath string) (*AudioFileInfo, error) { - info, err := os.Stat(filePath) - if err != nil { - return nil, err - } - - ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(filePath), ".")) - return &AudioFileInfo{ - Path: filePath, - Filename: filepath.Base(filePath), - Format: ext, - Size: info.Size(), - }, nil -} diff --git a/backend/ffmpeg_unix.go b/backend/ffmpeg_unix.go deleted file mode 100644 index 73b262f..0000000 --- a/backend/ffmpeg_unix.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build !windows -// +build !windows - -package backend - -import ( - "os/exec" -) - -func setHideWindow(cmd *exec.Cmd) { - -} diff --git a/backend/ffmpeg_windows.go b/backend/ffmpeg_windows.go deleted file mode 100644 index c08640e..0000000 --- a/backend/ffmpeg_windows.go +++ /dev/null @@ -1,15 +0,0 @@ -//go:build windows -// +build windows - -package backend - -import ( - "os/exec" - "syscall" -) - -func setHideWindow(cmd *exec.Cmd) { - cmd.SysProcAttr = &syscall.SysProcAttr{ - HideWindow: true, - } -} diff --git a/backend/file_dialog.go b/backend/file_dialog.go deleted file mode 100644 index a2f740f..0000000 --- a/backend/file_dialog.go +++ /dev/null @@ -1,53 +0,0 @@ -package backend - -import ( - "context" - - "github.com/wailsapp/wails/v2/pkg/runtime" -) - -func SelectMultipleFiles(ctx context.Context) ([]string, error) { - files, err := runtime.OpenMultipleFilesDialog(ctx, runtime.OpenDialogOptions{ - Title: "Select Audio Files", - Filters: []runtime.FileFilter{ - { - DisplayName: "Audio Files (*.mp3, *.m4a, *.flac, *.aac)", - Pattern: "*.mp3;*.m4a;*.flac;*.aac", - }, - { - DisplayName: "MP3 Files (*.mp3)", - Pattern: "*.mp3", - }, - { - DisplayName: "M4A Files (*.m4a)", - Pattern: "*.m4a", - }, - { - DisplayName: "FLAC Files (*.flac)", - Pattern: "*.flac", - }, - { - DisplayName: "AAC Files (*.aac)", - Pattern: "*.aac", - }, - { - DisplayName: "All Files (*.*)", - Pattern: "*.*", - }, - }, - }) - if err != nil { - return nil, err - } - return files, nil -} - -func SelectOutputDirectory(ctx context.Context) (string, error) { - dir, err := runtime.OpenDirectoryDialog(ctx, runtime.OpenDialogOptions{ - Title: "Select Output Directory", - }) - if err != nil { - return "", err - } - return dir, nil -} diff --git a/backend/fileicon_darwin.go b/backend/fileicon_darwin.go deleted file mode 100644 index dc62cbf..0000000 --- a/backend/fileicon_darwin.go +++ /dev/null @@ -1,45 +0,0 @@ -//go:build darwin - -package backend - -import ( - "fmt" - "os" - "os/exec" - "strings" -) - -func SetMacOSFileIconFromImage(filePath, imagePath string, iconSize int) error { - if filePath == "" { - return fmt.Errorf("file path is required") - } - if imagePath == "" { - return fmt.Errorf("image path is required") - } - - resizedPath, err := ResizeImageForIcon(imagePath, iconSize) - if err != nil { - return err - } - defer os.Remove(resizedPath) - - script := ` -use framework "AppKit" -on run argv - set imagePath to item 1 of argv - set targetPath to item 2 of argv - set iconImage to current application's NSImage's alloc()'s initWithContentsOfFile:imagePath - if iconImage is missing value then error "Failed to load icon image" - set didSet to (current application's NSWorkspace's sharedWorkspace()'s setIcon:iconImage forFile:targetPath options:0) as boolean - if didSet is false then error "Failed to set custom file icon" -end run -` - - cmd := exec.Command("osascript", "-", resizedPath, filePath) - cmd.Stdin = strings.NewReader(script) - output, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("failed to apply macOS file icon: %v (%s)", err, strings.TrimSpace(string(output))) - } - return nil -} diff --git a/backend/fileicon_stub.go b/backend/fileicon_stub.go deleted file mode 100644 index 31be330..0000000 --- a/backend/fileicon_stub.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build !darwin - -package backend - -func SetMacOSFileIconFromImage(filePath, imagePath string, iconSize int) error { - return nil -} diff --git a/backend/filemanager.go b/backend/filemanager.go deleted file mode 100644 index 12f3b33..0000000 --- a/backend/filemanager.go +++ /dev/null @@ -1,503 +0,0 @@ -package backend - -import ( - "encoding/json" - "fmt" - "os" - "os/exec" - "path/filepath" - "strconv" - "strings" - - id3v2 "github.com/bogem/id3v2/v2" - "github.com/go-flac/flacvorbis" - "github.com/go-flac/go-flac" -) - -type FileInfo struct { - Name string `json:"name"` - Path string `json:"path"` - IsDir bool `json:"is_dir"` - Size int64 `json:"size"` - Children []FileInfo `json:"children,omitempty"` -} - -type AudioMetadata struct { - Title string `json:"title"` - Artist string `json:"artist"` - Album string `json:"album"` - AlbumArtist string `json:"album_artist"` - TrackNumber int `json:"track_number"` - DiscNumber int `json:"disc_number"` - Year string `json:"year"` - ISRC string `json:"isrc"` - UPC string `json:"upc"` -} - -type RenamePreview struct { - OldPath string `json:"old_path"` - OldName string `json:"old_name"` - NewName string `json:"new_name"` - NewPath string `json:"new_path"` - Error string `json:"error,omitempty"` - Metadata AudioMetadata `json:"metadata"` -} - -type RenameResult struct { - OldPath string `json:"old_path"` - NewPath string `json:"new_path"` - Success bool `json:"success"` - Error string `json:"error,omitempty"` -} - -func ListDirectory(dirPath string) ([]FileInfo, error) { - entries, err := os.ReadDir(dirPath) - if err != nil { - return nil, fmt.Errorf("failed to read directory: %w", err) - } - - var result []FileInfo - for _, entry := range entries { - info, err := entry.Info() - if err != nil { - continue - } - - fileInfo := FileInfo{ - Name: entry.Name(), - Path: filepath.Join(dirPath, entry.Name()), - IsDir: entry.IsDir(), - Size: info.Size(), - } - - if entry.IsDir() { - children, err := ListDirectory(fileInfo.Path) - if err == nil { - fileInfo.Children = children - } - } - - result = append(result, fileInfo) - } - - return result, nil -} - -func ListAudioFiles(dirPath string) ([]FileInfo, error) { - var result []FileInfo - - err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { - if err != nil { - return nil - } - - if info.IsDir() { - return nil - } - - ext := strings.ToLower(filepath.Ext(path)) - if ext == ".flac" || ext == ".mp3" || ext == ".m4a" || ext == ".aac" { - result = append(result, FileInfo{ - Name: info.Name(), - Path: path, - IsDir: false, - Size: info.Size(), - }) - } - - return nil - }) - - if err != nil { - return nil, fmt.Errorf("failed to walk directory: %w", err) - } - - return result, nil -} - -func ReadAudioMetadata(filePath string) (*AudioMetadata, error) { - if !fileExists(filePath) { - return nil, fmt.Errorf("file does not exist") - } - - ext := strings.ToLower(filepath.Ext(filePath)) - - switch ext { - case ".flac": - return readFlacMetadata(filePath) - case ".mp3": - return readMp3Metadata(filePath) - case ".m4a": - return readM4aMetadata(filePath) - default: - return nil, fmt.Errorf("unsupported file format: %s", ext) - } -} - -func readFlacMetadata(filePath string) (*AudioMetadata, error) { - f, err := flac.ParseFile(filePath) - if err != nil { - return nil, fmt.Errorf("failed to parse FLAC file: %w", err) - } - - metadata := &AudioMetadata{} - - for _, block := range f.Meta { - if block.Type == flac.VorbisComment { - cmt, err := flacvorbis.ParseFromMetaDataBlock(*block) - if err != nil { - continue - } - - for _, comment := range cmt.Comments { - parts := strings.SplitN(comment, "=", 2) - if len(parts) != 2 { - continue - } - - fieldName := strings.ToUpper(parts[0]) - value := parts[1] - - switch fieldName { - case "TITLE": - metadata.Title = value - case "ARTIST": - metadata.Artist = value - case "ALBUM": - metadata.Album = value - case "ALBUMARTIST": - metadata.AlbumArtist = value - case "TRACKNUMBER": - if num, err := strconv.Atoi(value); err == nil { - metadata.TrackNumber = num - } - case "DISCNUMBER": - if num, err := strconv.Atoi(value); err == nil { - metadata.DiscNumber = num - } - case "DATE", "YEAR": - metadata.Year = value - case "ISRC", "TSRC": - metadata.ISRC = value - case "UPC": - assignPreferredUPC(&metadata.UPC, value, true) - case "BARCODE": - assignPreferredUPC(&metadata.UPC, value, false) - } - } - } - } - - return metadata, nil -} - -func readMp3Metadata(filePath string) (*AudioMetadata, error) { - tag, err := id3v2.Open(filePath, id3v2.Options{Parse: true}) - if err != nil { - return nil, fmt.Errorf("failed to open MP3 file: %w", err) - } - defer tag.Close() - - metadata := &AudioMetadata{ - Title: tag.Title(), - Artist: tag.Artist(), - Album: tag.Album(), - Year: tag.Year(), - } - - if frames := tag.GetFrames("TPE2"); len(frames) > 0 { - if textFrame, ok := frames[0].(id3v2.TextFrame); ok { - metadata.AlbumArtist = textFrame.Text - } - } - - if frames := tag.GetFrames(tag.CommonID("Track number/Position in set")); len(frames) > 0 { - if textFrame, ok := frames[0].(id3v2.TextFrame); ok { - trackStr := strings.Split(textFrame.Text, "/")[0] - if num, err := strconv.Atoi(trackStr); err == nil { - metadata.TrackNumber = num - } - } - } - - if frames := tag.GetFrames(tag.CommonID("Part of a set")); len(frames) > 0 { - if textFrame, ok := frames[0].(id3v2.TextFrame); ok { - discStr := strings.Split(textFrame.Text, "/")[0] - if num, err := strconv.Atoi(discStr); err == nil { - metadata.DiscNumber = num - } - } - } - - if frames := tag.GetFrames("TSRC"); len(frames) > 0 { - if textFrame, ok := frames[0].(id3v2.TextFrame); ok { - metadata.ISRC = textFrame.Text - } - } - if frames := tag.GetFrames("TXXX"); len(frames) > 0 { - for _, frame := range frames { - userTextFrame, ok := frame.(id3v2.UserDefinedTextFrame) - if !ok { - continue - } - matched, preferred := classifyUPCDescription(userTextFrame.Description) - if !matched { - continue - } - assignPreferredUPC(&metadata.UPC, userTextFrame.Value, preferred) - if preferred && strings.TrimSpace(metadata.UPC) != "" { - break - } - } - } - - return metadata, nil -} - -func readMetadataWithFFprobe(filePath string) (*AudioMetadata, error) { - ffprobePath, err := GetFFprobePath() - if err != nil { - return nil, err - } - - if err := ValidateExecutable(ffprobePath); err != nil { - return nil, fmt.Errorf("invalid ffprobe executable: %w", err) - } - - cmd := exec.Command(ffprobePath, - "-v", "quiet", - "-print_format", "json", - "-show_format", - "-show_streams", - filePath, - ) - - setHideWindow(cmd) - - output, err := cmd.Output() - if err != nil { - return nil, err - } - - var result struct { - Format struct { - Tags map[string]string `json:"tags"` - } `json:"format"` - Streams []struct { - Tags map[string]string `json:"tags"` - } `json:"streams"` - } - - if err := json.Unmarshal(output, &result); err != nil { - return nil, err - } - - metadata := &AudioMetadata{} - - allTags := make(map[string]string) - - for _, stream := range result.Streams { - for key, value := range stream.Tags { - allTags[strings.ToLower(key)] = value - } - } - - for key, value := range result.Format.Tags { - allTags[strings.ToLower(key)] = value - } - - for key, value := range allTags { - switch key { - case "title": - metadata.Title = value - case "artist": - metadata.Artist = value - case "album": - metadata.Album = value - case "album_artist", "albumartist": - metadata.AlbumArtist = value - case "track": - - trackStr := strings.Split(value, "/")[0] - if num, err := strconv.Atoi(trackStr); err == nil { - metadata.TrackNumber = num - } - case "disc": - discStr := strings.Split(value, "/")[0] - if num, err := strconv.Atoi(discStr); err == nil { - metadata.DiscNumber = num - } - case "date", "year": - if metadata.Year == "" || len(value) > len(metadata.Year) { - metadata.Year = value - } - case "isrc", "tsrc": - metadata.ISRC = value - } - } - - metadata.UPC = firstPreferredFFprobeUPCValue(allTags) - - return metadata, nil -} - -func readM4aMetadata(filePath string) (*AudioMetadata, error) { - metadata, err := readMetadataWithFFprobe(filePath) - if err != nil { - return &AudioMetadata{}, nil - } - return metadata, nil -} - -func GenerateFilename(metadata *AudioMetadata, format string, ext string) string { - if metadata == nil { - return "" - } - - result := format - - year := metadata.Year - if len(year) >= 4 { - year = year[:4] - } - - result = strings.ReplaceAll(result, "{title}", sanitizeFilenameForRename(metadata.Title)) - result = strings.ReplaceAll(result, "{artist}", sanitizeFilenameForRename(metadata.Artist)) - result = strings.ReplaceAll(result, "{album}", sanitizeFilenameForRename(metadata.Album)) - result = strings.ReplaceAll(result, "{album_artist}", sanitizeFilenameForRename(metadata.AlbumArtist)) - result = strings.ReplaceAll(result, "{year}", sanitizeFilenameForRename(year)) - result = strings.ReplaceAll(result, "{date}", sanitizeFilenameForRename(metadata.Year)) - result = strings.ReplaceAll(result, "{isrc}", sanitizeFilenameForRename(metadata.ISRC)) - - if metadata.TrackNumber > 0 { - result = strings.ReplaceAll(result, "{track}", fmt.Sprintf("%02d", metadata.TrackNumber)) - } else { - result = strings.ReplaceAll(result, "{track}", "") - } - - if metadata.DiscNumber > 0 { - result = strings.ReplaceAll(result, "{disc}", fmt.Sprintf("%d", metadata.DiscNumber)) - } else { - result = strings.ReplaceAll(result, "{disc}", "") - } - - result = strings.TrimSpace(result) - result = strings.Join(strings.Fields(result), " ") - - result = strings.Trim(result, " -._") - - if result == "" { - return "" - } - - return result + ext -} - -func sanitizeFilenameForRename(name string) string { - - invalid := []string{"<", ">", ":", "\"", "/", "\\", "|", "?", "*"} - result := name - for _, char := range invalid { - result = strings.ReplaceAll(result, char, "") - } - return strings.TrimSpace(result) -} - -func PreviewRename(files []string, format string) []RenamePreview { - var previews []RenamePreview - - for _, filePath := range files { - preview := RenamePreview{ - OldPath: filePath, - OldName: filepath.Base(filePath), - } - - metadata, err := ReadAudioMetadata(filePath) - if err != nil { - preview.Error = err.Error() - previews = append(previews, preview) - continue - } - - preview.Metadata = *metadata - - ext := filepath.Ext(filePath) - newName := GenerateFilename(metadata, format, ext) - - if newName == "" { - preview.Error = "Could not generate filename (missing metadata)" - previews = append(previews, preview) - continue - } - - preview.NewName = newName - preview.NewPath = filepath.Join(filepath.Dir(filePath), newName) - - previews = append(previews, preview) - } - - return previews -} - -func GetFileSizes(files []string) map[string]int64 { - result := make(map[string]int64) - for _, filePath := range files { - info, err := os.Stat(filePath) - if err == nil { - result[filePath] = info.Size() - } - } - return result -} - -func RenameFiles(files []string, format string) []RenameResult { - var results []RenameResult - - for _, filePath := range files { - result := RenameResult{ - OldPath: filePath, - } - - metadata, err := ReadAudioMetadata(filePath) - if err != nil { - result.Error = err.Error() - result.Success = false - results = append(results, result) - continue - } - - ext := filepath.Ext(filePath) - newName := GenerateFilename(metadata, format, ext) - - if newName == "" { - result.Error = "Could not generate filename (missing metadata)" - result.Success = false - results = append(results, result) - continue - } - - newPath := filepath.Join(filepath.Dir(filePath), newName) - result.NewPath = newPath - - if newPath != filePath { - if _, err := os.Stat(newPath); err == nil { - result.Error = "File already exists" - result.Success = false - results = append(results, result) - continue - } - } - - if err := os.Rename(filePath, newPath); err != nil { - result.Error = err.Error() - result.Success = false - results = append(results, result) - continue - } - - result.Success = true - results = append(results, result) - } - - return results -} diff --git a/backend/filename.go b/backend/filename.go deleted file mode 100644 index 91ae94d..0000000 --- a/backend/filename.go +++ /dev/null @@ -1,239 +0,0 @@ -package backend - -import ( - "fmt" - "os" - "path/filepath" - "regexp" - "strings" - "unicode" - "unicode/utf8" -) - -func buildFormattedFilenameBase(trackName, artistName, albumName, albumArtist, releaseDate, filenameFormat, playlistName, playlistOwner, isrc string, includeTrackNumber bool, position, discNumber int, useAlbumTrackNumber bool) string { - safeTitle := SanitizeFilename(trackName) - safeArtist := SanitizeFilename(artistName) - safeAlbum := SanitizeFilename(albumName) - safeAlbumArtist := SanitizeFilename(albumArtist) - safeISRC := SanitizeOptionalFilename(isrc) - - safePlaylist := SanitizeFilename(playlistName) - safeCreator := SanitizeFilename(playlistOwner) - - year := "" - if len(releaseDate) >= 4 { - year = releaseDate[:4] - } - - var filename string - - if strings.Contains(filenameFormat, "{") { - filename = filenameFormat - filename = strings.ReplaceAll(filename, "{title}", safeTitle) - filename = strings.ReplaceAll(filename, "{artist}", safeArtist) - filename = strings.ReplaceAll(filename, "{album}", safeAlbum) - filename = strings.ReplaceAll(filename, "{album_artist}", safeAlbumArtist) - filename = strings.ReplaceAll(filename, "{year}", year) - filename = strings.ReplaceAll(filename, "{date}", SanitizeFilename(releaseDate)) - filename = strings.ReplaceAll(filename, "{playlist}", safePlaylist) - filename = strings.ReplaceAll(filename, "{creator}", safeCreator) - filename = strings.ReplaceAll(filename, "{isrc}", safeISRC) - - if discNumber > 0 { - filename = strings.ReplaceAll(filename, "{disc}", fmt.Sprintf("%d", discNumber)) - } else { - filename = strings.ReplaceAll(filename, "{disc}", "") - } - - if position > 0 { - filename = strings.ReplaceAll(filename, "{track}", fmt.Sprintf("%02d", position)) - } else { - - filename = regexp.MustCompile(`\{track\}\.\s*`).ReplaceAllString(filename, "") - filename = regexp.MustCompile(`\{track\}\s*-\s*`).ReplaceAllString(filename, "") - filename = regexp.MustCompile(`\{track\}\s*`).ReplaceAllString(filename, "") - } - } else { - - switch filenameFormat { - case "artist-title": - filename = fmt.Sprintf("%s - %s", safeArtist, safeTitle) - case "title": - filename = safeTitle - default: - filename = fmt.Sprintf("%s - %s", safeTitle, safeArtist) - } - - if includeTrackNumber && position > 0 { - filename = fmt.Sprintf("%02d. %s", position, filename) - } - } - - return filename -} - -func BuildExpectedFilename(trackName, artistName, albumName, albumArtist, releaseDate, filenameFormat, playlistName, playlistOwner string, includeTrackNumber bool, position, discNumber int, useAlbumTrackNumber bool, extra ...string) string { - isrc := "" - if len(extra) > 0 { - isrc = extra[0] - } - - return buildFormattedFilenameBase(trackName, artistName, albumName, albumArtist, releaseDate, filenameFormat, playlistName, playlistOwner, isrc, includeTrackNumber, position, discNumber, useAlbumTrackNumber) + ".flac" -} - -func ResolveOutputPathForDownload(path string, redownloadWithSuffix bool) (string, bool) { - if !redownloadWithSuffix { - if info, err := os.Stat(path); err == nil && info.Size() > 0 { - return path, true - } - return path, false - } - - if info, err := os.Stat(path); err != nil || info.Size() == 0 { - return path, false - } - - ext := filepath.Ext(path) - base := strings.TrimSuffix(path, ext) - - for i := 1; ; i++ { - candidate := fmt.Sprintf("%s_%02d%s", base, i, ext) - if info, err := os.Stat(candidate); err != nil || info.Size() == 0 { - return candidate, false - } - } -} - -func mustFileSize(path string) int64 { - info, err := os.Stat(path) - if err != nil { - return 0 - } - return info.Size() -} - -func SanitizeFilename(name string) string { - - sanitized := strings.ReplaceAll(name, "/", " ") - - re := regexp.MustCompile(`[<>:"\\|?*]`) - sanitized = re.ReplaceAllString(sanitized, " ") - - var result strings.Builder - for _, r := range sanitized { - - if r < 0x20 && r != 0x09 && r != 0x0A && r != 0x0D { - continue - } - if r == 0x7F { - continue - } - - if unicode.IsControl(r) && r != 0x09 && r != 0x0A && r != 0x0D { - continue - } - - result.WriteRune(r) - } - - sanitized = result.String() - sanitized = strings.TrimSpace(sanitized) - - sanitized = strings.Trim(sanitized, ". ") - - re = regexp.MustCompile(`\s+`) - sanitized = re.ReplaceAllString(sanitized, " ") - - re = regexp.MustCompile(`_+`) - sanitized = re.ReplaceAllString(sanitized, "_") - - sanitized = strings.Trim(sanitized, "_ ") - - if sanitized == "" { - return "Unknown" - } - - if !utf8.ValidString(sanitized) { - - sanitized = strings.ToValidUTF8(sanitized, "_") - } - - return sanitized -} - -func GetFirstArtist(artistString string) string { - if artistString == "" { - return "" - } - delimiters := []string{", ", " & ", " feat. ", " ft. ", " featuring "} - for _, d := range delimiters { - if idx := strings.Index(strings.ToLower(artistString), d); idx != -1 { - return strings.TrimSpace(artistString[:idx]) - } - } - return artistString -} - -func NormalizePath(folderPath string) string { - return strings.ReplaceAll(folderPath, "/", string(filepath.Separator)) -} - -func GetSeparator() string { - settings, err := LoadConfigSettings() - if err != nil || settings == nil { - return "; " - } - - if sep, ok := settings["separator"].(string); ok { - if sep == "comma" { - return ", " - } - if sep == "semicolon" { - return "; " - } - } - return "; " -} - -func SanitizeFolderPath(folderPath string) string { - - normalizedPath := strings.ReplaceAll(folderPath, "/", string(filepath.Separator)) - - sep := string(filepath.Separator) - - parts := strings.Split(normalizedPath, sep) - sanitizedParts := make([]string, 0, len(parts)) - - for i, part := range parts { - - if i == 0 && len(part) == 2 && part[1] == ':' { - sanitizedParts = append(sanitizedParts, part) - continue - } - - if i == 0 && part == "" { - sanitizedParts = append(sanitizedParts, part) - continue - } - - sanitized := sanitizeFolderName(part) - if sanitized != "" { - sanitizedParts = append(sanitizedParts, sanitized) - } - } - - return strings.Join(sanitizedParts, sep) -} - -func sanitizeFolderName(name string) string { return SanitizeFilename(name) } - -func sanitizeFilename(name string) string { - return SanitizeFilename(name) -} - -func SanitizeOptionalFilename(name string) string { - if strings.TrimSpace(name) == "" { - return "" - } - return SanitizeFilename(name) -} diff --git a/backend/folder.go b/backend/folder.go deleted file mode 100644 index db33d2a..0000000 --- a/backend/folder.go +++ /dev/null @@ -1,115 +0,0 @@ -package backend - -import ( - "context" - "os/exec" - "runtime" - - wailsRuntime "github.com/wailsapp/wails/v2/pkg/runtime" -) - -func OpenFolderInExplorer(path string) error { - var cmd *exec.Cmd - - switch runtime.GOOS { - case "windows": - cmd = exec.Command("explorer", path) - case "darwin": - cmd = exec.Command("open", path) - case "linux": - cmd = exec.Command("xdg-open", path) - default: - cmd = exec.Command("xdg-open", path) - } - - return cmd.Start() -} - -func SelectFolderDialog(ctx context.Context, defaultPath string) (string, error) { - - if defaultPath == "" { - defaultPath = GetDefaultMusicPath() - } - - options := wailsRuntime.OpenDialogOptions{ - Title: "Select Download Folder", - DefaultDirectory: defaultPath, - } - - selectedPath, err := wailsRuntime.OpenDirectoryDialog(ctx, options) - if err != nil { - return "", err - } - - if selectedPath == "" { - return "", nil - } - - return selectedPath, nil -} - -func SelectFileDialog(ctx context.Context) (string, error) { - options := wailsRuntime.OpenDialogOptions{ - Title: "Select Audio File for Analysis", - Filters: []wailsRuntime.FileFilter{ - { - DisplayName: "Audio Files (*.flac;*.mp3;*.m4a;*.aac)", - Pattern: "*.flac;*.mp3;*.m4a;*.aac", - }, - { - DisplayName: "FLAC Audio Files (*.flac)", - Pattern: "*.flac", - }, - { - DisplayName: "MP3 Audio Files (*.mp3)", - Pattern: "*.mp3", - }, - { - DisplayName: "M4A Audio Files (*.m4a)", - Pattern: "*.m4a", - }, - { - DisplayName: "AAC Audio Files (*.aac)", - Pattern: "*.aac", - }, - { - DisplayName: "All Files (*.*)", - Pattern: "*.*", - }, - }, - } - - selectedFile, err := wailsRuntime.OpenFileDialog(ctx, options) - if err != nil { - return "", err - } - - if selectedFile == "" { - return "", nil - } - - return selectedFile, nil -} - -func SelectImageVideoDialog(ctx context.Context) ([]string, error) { - options := wailsRuntime.OpenDialogOptions{ - Title: "Select Image or Video", - Filters: []wailsRuntime.FileFilter{ - { - DisplayName: "Supported Files (*.jpg, *.png, *.mp4, *.mov, ...)", - Pattern: "*.jpg;*.jpeg;*.png;*.gif;*.webp;*.mp4;*.mkv;*.webm;*.mov", - }, - { - DisplayName: "All Files (*.*)", - Pattern: "*.*", - }, - }, - } - - selectedPaths, err := wailsRuntime.OpenMultipleFilesDialog(ctx, options) - if err != nil { - return nil, err - } - - return selectedPaths, nil -} diff --git a/backend/history.go b/backend/history.go deleted file mode 100644 index 18804c0..0000000 --- a/backend/history.go +++ /dev/null @@ -1,323 +0,0 @@ -package backend - -import ( - "encoding/json" - "fmt" - "path/filepath" - "sort" - "time" - - bolt "go.etcd.io/bbolt" -) - -type HistoryItem struct { - ID string `json:"id"` - SpotifyID string `json:"spotify_id"` - Title string `json:"title"` - Artists string `json:"artists"` - Album string `json:"album"` - DurationStr string `json:"duration_str"` - CoverURL string `json:"cover_url"` - Quality string `json:"quality"` - Format string `json:"format"` - Path string `json:"path"` - Source string `json:"source"` - Timestamp int64 `json:"timestamp"` -} - -var historyDB *bolt.DB - -const ( - historyBucket = "DownloadHistory" - maxHistory = 10000 -) - -func InitHistoryDB(appName string) error { - - appDir, err := EnsureAppDir() - if err != nil { - return err - } - dbPath := filepath.Join(appDir, "history.db") - - db, err := bolt.Open(dbPath, 0600, &bolt.Options{Timeout: 1 * time.Second}) - if err != nil { - return err - } - - err = db.Update(func(tx *bolt.Tx) error { - _, err := tx.CreateBucketIfNotExists([]byte(historyBucket)) - return err - }) - - if err != nil { - db.Close() - return err - } - - historyDB = db - return nil -} - -func CloseHistoryDB() { - if historyDB != nil { - historyDB.Close() - } -} - -func AddHistoryItem(item HistoryItem, appName string) error { - if historyDB == nil { - if err := InitHistoryDB(appName); err != nil { - return err - } - } - return historyDB.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists([]byte(historyBucket)) - if err != nil { - return err - } - id, _ := b.NextSequence() - - item.ID = fmt.Sprintf("%d-%d", time.Now().UnixNano(), id) - item.Timestamp = time.Now().Unix() - - buf, err := json.Marshal(item) - if err != nil { - return err - } - - if b.Stats().KeyN >= maxHistory { - c := b.Cursor() - - toDelete := maxHistory / 20 - if toDelete < 1 { - toDelete = 1 - } - - count := 0 - for k, _ := c.First(); k != nil && count < toDelete; k, _ = c.Next() { - if err := b.Delete(k); err != nil { - return err - } - count++ - } - } - - return b.Put([]byte(item.ID), buf) - }) -} - -func GetHistoryItems(appName string) ([]HistoryItem, error) { - if historyDB == nil { - if err := InitHistoryDB(appName); err != nil { - return nil, err - } - } - var items []HistoryItem - err := historyDB.View(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte(historyBucket)) - if b == nil { - return nil - } - c := b.Cursor() - - for k, v := c.First(); k != nil; k, v = c.Next() { - var item HistoryItem - if err := json.Unmarshal(v, &item); err == nil { - items = append(items, item) - } - } - return nil - }) - - sort.Slice(items, func(i, j int) bool { - return items[i].Timestamp > items[j].Timestamp - }) - - return items, err -} - -func ClearHistory(appName string) error { - if historyDB == nil { - if err := InitHistoryDB(appName); err != nil { - return err - } - } - return historyDB.Update(func(tx *bolt.Tx) error { - return tx.DeleteBucket([]byte(historyBucket)) - }) -} - -type FetchHistoryItem struct { - ID string `json:"id"` - URL string `json:"url"` - Type string `json:"type"` - Name string `json:"name"` - Info string `json:"info"` - Image string `json:"image"` - Data string `json:"data"` - Timestamp int64 `json:"timestamp"` -} - -const ( - fetchHistoryBucket = "FetchHistory" -) - -func AddFetchHistoryItem(item FetchHistoryItem, appName string) error { - if historyDB == nil { - if err := InitHistoryDB(appName); err != nil { - return err - } - } - return historyDB.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists([]byte(fetchHistoryBucket)) - if err != nil { - return err - } - id, _ := b.NextSequence() - - if item.URL != "" { - c := b.Cursor() - for k, v := c.First(); k != nil; k, v = c.Next() { - var existing FetchHistoryItem - if err := json.Unmarshal(v, &existing); err == nil { - if existing.URL == item.URL && existing.Type == item.Type { - if err := b.Delete(k); err != nil { - return err - } - } - } - } - } - - item.ID = fmt.Sprintf("%d-%d", time.Now().UnixNano(), id) - item.Timestamp = time.Now().Unix() - - buf, err := json.Marshal(item) - if err != nil { - return err - } - - if b.Stats().KeyN >= maxHistory { - c := b.Cursor() - toDelete := maxHistory / 20 - if toDelete < 1 { - toDelete = 1 - } - count := 0 - for k, _ := c.First(); k != nil && count < toDelete; k, _ = c.Next() { - if err := b.Delete(k); err != nil { - return err - } - count++ - } - } - - return b.Put([]byte(item.ID), buf) - }) -} - -func GetFetchHistoryItems(appName string) ([]FetchHistoryItem, error) { - if historyDB == nil { - if err := InitHistoryDB(appName); err != nil { - return nil, err - } - } - var items []FetchHistoryItem - err := historyDB.View(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte(fetchHistoryBucket)) - if b == nil { - return nil - } - c := b.Cursor() - - for k, v := c.First(); k != nil; k, v = c.Next() { - var item FetchHistoryItem - if err := json.Unmarshal(v, &item); err == nil { - items = append(items, item) - } - } - return nil - }) - - sort.Slice(items, func(i, j int) bool { - return items[i].Timestamp > items[j].Timestamp - }) - - return items, err -} - -func ClearFetchHistory(appName string) error { - if historyDB == nil { - if err := InitHistoryDB(appName); err != nil { - return err - } - } - return historyDB.Update(func(tx *bolt.Tx) error { - return tx.DeleteBucket([]byte(fetchHistoryBucket)) - }) -} - -func ClearFetchHistoryByType(itemType string, appName string) error { - if historyDB == nil { - if err := InitHistoryDB(appName); err != nil { - return err - } - } - return historyDB.Update(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte(fetchHistoryBucket)) - if b == nil { - return nil - } - - var keysToDelete [][]byte - - c := b.Cursor() - for k, v := c.First(); k != nil; k, v = c.Next() { - var item FetchHistoryItem - if err := json.Unmarshal(v, &item); err == nil { - if item.Type == itemType { - keysToDelete = append(keysToDelete, k) - } - } - } - - for _, k := range keysToDelete { - if err := b.Delete(k); err != nil { - return err - } - } - return nil - }) -} - -func DeleteHistoryItem(id string, appName string) error { - if historyDB == nil { - if err := InitHistoryDB(appName); err != nil { - return err - } - } - return historyDB.Update(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte(historyBucket)) - if b == nil { - return nil - } - - return b.Delete([]byte(id)) - }) -} - -func DeleteFetchHistoryItem(id string, appName string) error { - if historyDB == nil { - if err := InitHistoryDB(appName); err != nil { - return err - } - } - return historyDB.Update(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte(fetchHistoryBucket)) - if b == nil { - return nil - } - return b.Delete([]byte(id)) - }) -} diff --git a/backend/http_headers.go b/backend/http_headers.go deleted file mode 100644 index 4d6a042..0000000 --- a/backend/http_headers.go +++ /dev/null @@ -1,20 +0,0 @@ -package backend - -import ( - "io" - "net/http" -) - -const DefaultDownloaderUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36" - -func NewRequestWithDefaultHeaders(method string, rawURL string, body io.Reader) (*http.Request, error) { - req, err := http.NewRequest(method, rawURL, body) - if err != nil { - return nil, err - } - - req.Header.Set("User-Agent", DefaultDownloaderUserAgent) - req.Header.Set("Accept", "application/json, text/plain, */*") - - return req, nil -} diff --git a/backend/isrc_cache.go b/backend/isrc_cache.go deleted file mode 100644 index cbe6b34..0000000 --- a/backend/isrc_cache.go +++ /dev/null @@ -1,137 +0,0 @@ -package backend - -import ( - "encoding/json" - "fmt" - "path/filepath" - "strings" - "sync" - "time" - - bolt "go.etcd.io/bbolt" -) - -const ( - isrcCacheDBFile = "isrc_cache.db" - isrcCacheBucket = "SpotifyTrackISRC" -) - -type isrcCacheEntry struct { - TrackID string `json:"track_id"` - ISRC string `json:"isrc"` - UpdatedAt int64 `json:"updated_at"` -} - -var ( - isrcCacheDB *bolt.DB - isrcCacheDBMu sync.Mutex -) - -func InitISRCCacheDB() error { - isrcCacheDBMu.Lock() - defer isrcCacheDBMu.Unlock() - - if isrcCacheDB != nil { - return nil - } - - appDir, err := EnsureAppDir() - if err != nil { - return err - } - - dbPath := filepath.Join(appDir, isrcCacheDBFile) - db, err := bolt.Open(dbPath, 0o600, &bolt.Options{Timeout: 1 * time.Second}) - if err != nil { - return err - } - - if err := db.Update(func(tx *bolt.Tx) error { - _, err := tx.CreateBucketIfNotExists([]byte(isrcCacheBucket)) - return err - }); err != nil { - db.Close() - return err - } - - isrcCacheDB = db - return nil -} - -func CloseISRCCacheDB() { - isrcCacheDBMu.Lock() - defer isrcCacheDBMu.Unlock() - - if isrcCacheDB != nil { - _ = isrcCacheDB.Close() - isrcCacheDB = nil - } -} - -func GetCachedISRC(trackID string) (string, error) { - normalizedTrackID := strings.TrimSpace(trackID) - if normalizedTrackID == "" { - return "", nil - } - - if err := InitISRCCacheDB(); err != nil { - return "", err - } - - var cachedISRC string - err := isrcCacheDB.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(isrcCacheBucket)) - if bucket == nil { - return nil - } - - value := bucket.Get([]byte(normalizedTrackID)) - if len(value) == 0 { - return nil - } - - var entry isrcCacheEntry - if err := json.Unmarshal(value, &entry); err != nil { - return err - } - - cachedISRC = strings.ToUpper(strings.TrimSpace(entry.ISRC)) - return nil - }) - if err != nil { - return "", err - } - - return cachedISRC, nil -} - -func PutCachedISRC(trackID string, isrc string) error { - normalizedTrackID := strings.TrimSpace(trackID) - normalizedISRC := strings.ToUpper(strings.TrimSpace(isrc)) - if normalizedTrackID == "" || normalizedISRC == "" { - return nil - } - - if err := InitISRCCacheDB(); err != nil { - return err - } - - entry := isrcCacheEntry{ - TrackID: normalizedTrackID, - ISRC: normalizedISRC, - UpdatedAt: time.Now().Unix(), - } - - payload, err := json.Marshal(entry) - if err != nil { - return fmt.Errorf("failed to encode ISRC cache entry: %w", err) - } - - return isrcCacheDB.Update(func(tx *bolt.Tx) error { - bucket, err := tx.CreateBucketIfNotExists([]byte(isrcCacheBucket)) - if err != nil { - return err - } - return bucket.Put([]byte(normalizedTrackID), payload) - }) -} diff --git a/backend/isrc_finder.go b/backend/isrc_finder.go deleted file mode 100644 index 4796c37..0000000 --- a/backend/isrc_finder.go +++ /dev/null @@ -1,464 +0,0 @@ -package backend - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "math/big" - "net/http" - "net/url" - "os" - "path/filepath" - "strconv" - "strings" - "sync" - "time" -) - -const ( - spotifySessionTokenURL = "https://open.spotify.com/api/token" - spotifyGIDMetadataURL = "https://spclient.wg.spotify.com/metadata/4/%s/%s?market=from_token" - spotifyBase62Alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - spotifyTokenCacheFile = ".isrc-finder-token.json" -) - -var spotifyAnonymousTokenMu sync.Mutex - -type spotifyAnonymousToken struct { - AccessToken string `json:"accessToken"` - AccessTokenExpirationTimestampMs int64 `json:"accessTokenExpirationTimestampMs"` -} - -type spotifyTrackRawData struct { - Album struct { - GID string `json:"gid"` - } `json:"album"` - ExternalID []struct { - Type string `json:"type"` - ID string `json:"id"` - } `json:"external_id"` -} - -type spotifyAlbumRawData struct { - ExternalID []struct { - Type string `json:"type"` - ID string `json:"id"` - } `json:"external_id"` -} - -type SpotifyTrackIdentifiers struct { - ISRC string `json:"isrc,omitempty"` - UPC string `json:"upc,omitempty"` -} - -func GetSpotifyTrackIdentifiersDirect(spotifyTrackID string) (SpotifyTrackIdentifiers, error) { - normalizedTrackID, err := extractSpotifyTrackID(spotifyTrackID) - if err != nil { - return SpotifyTrackIdentifiers{}, err - } - - identifiers := SpotifyTrackIdentifiers{} - - cachedISRC, err := GetCachedISRC(normalizedTrackID) - if err != nil { - fmt.Printf("Warning: failed to read ISRC cache: %v\n", err) - } else if cachedISRC != "" { - fmt.Printf("Found ISRC in cache: %s\n", cachedISRC) - identifiers.ISRC = cachedISRC - } - - httpClient := &http.Client{Timeout: 30 * time.Second} - - payload, metadataErr := fetchSpotifyTrackRawData(httpClient, normalizedTrackID) - if metadataErr == nil { - metadataIdentifiers, extractErr := extractSpotifyTrackIdentifiers(httpClient, payload) - if extractErr == nil { - mergeSpotifyTrackIdentifiers(&identifiers, metadataIdentifiers) - if identifiers.ISRC != "" { - fmt.Printf("Found identifiers via Spotify metadata: isrc=%s upc=%s\n", identifiers.ISRC, identifiers.UPC) - cacheResolvedSpotifyTrackISRC(normalizedTrackID, "", identifiers.ISRC) - } - if identifiers.ISRC != "" && identifiers.UPC != "" { - return identifiers, nil - } - } - metadataErr = extractErr - } - - if metadataErr != nil { - fmt.Printf("Warning: Spotify metadata identifier lookup failed, falling back to Soundplate: %v\n", metadataErr) - } - - if identifiers.ISRC == "" { - client := NewSongLinkClient() - isrc, resolvedTrackID, soundplateErr := client.lookupSpotifyISRCViaSoundplate(normalizedTrackID) - if soundplateErr == nil && isrc != "" { - identifiers.ISRC = isrc - fmt.Printf("Found ISRC via Soundplate: %s\n", isrc) - cacheResolvedSpotifyTrackISRC(normalizedTrackID, resolvedTrackID, isrc) - return identifiers, nil - } - - if metadataErr != nil && soundplateErr != nil { - return identifiers, fmt.Errorf("spotify metadata lookup failed: %v | soundplate lookup failed: %w", metadataErr, soundplateErr) - } - if soundplateErr != nil && identifiers.UPC == "" { - return identifiers, soundplateErr - } - } - - if identifiers.ISRC != "" || identifiers.UPC != "" { - return identifiers, nil - } - if metadataErr != nil { - return identifiers, metadataErr - } - - return identifiers, fmt.Errorf("no Spotify identifiers found for track %s", normalizedTrackID) -} - -func (s *SongLinkClient) lookupSpotifyISRC(spotifyTrackID string) (string, error) { - identifiers, err := GetSpotifyTrackIdentifiersDirect(spotifyTrackID) - if err != nil { - return "", err - } - if identifiers.ISRC == "" { - return "", fmt.Errorf("no Spotify ISRC found for track %s", strings.TrimSpace(spotifyTrackID)) - } - - return identifiers.ISRC, nil -} - -func cacheResolvedSpotifyTrackISRC(trackID string, resolvedTrackID string, isrc string) { - if err := PutCachedISRC(trackID, isrc); err != nil { - fmt.Printf("Warning: failed to write ISRC cache: %v\n", err) - } - if resolvedTrackID != "" && resolvedTrackID != trackID { - if err := PutCachedISRC(resolvedTrackID, isrc); err != nil { - fmt.Printf("Warning: failed to write ISRC cache for resolved track ID: %v\n", err) - } - } -} - -func mergeSpotifyTrackIdentifiers(target *SpotifyTrackIdentifiers, incoming SpotifyTrackIdentifiers) { - if incoming.ISRC != "" { - target.ISRC = strings.TrimSpace(incoming.ISRC) - } - if incoming.UPC != "" { - target.UPC = strings.TrimSpace(incoming.UPC) - } -} - -func lookupSpotifyAlbumUPC(albumID string) (string, error) { - normalizedAlbumID := strings.TrimSpace(albumID) - if normalizedAlbumID == "" { - return "", fmt.Errorf("spotify album ID is required") - } - - httpClient := &http.Client{Timeout: 30 * time.Second} - payload, err := fetchSpotifyAlbumRawData(httpClient, normalizedAlbumID) - if err != nil { - return "", err - } - - return extractSpotifyAlbumUPC(payload) -} - -func requestSpotifyBytes(client *http.Client, targetURL string, headers map[string]string) ([]byte, error) { - req, err := http.NewRequest(http.MethodGet, targetURL, nil) - if err != nil { - return nil, err - } - - for key, value := range headers { - req.Header.Set(key, value) - } - - resp, err := client.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices { - details := strings.TrimSpace(string(body)) - if details == "" { - details = resp.Status - } - return nil, fmt.Errorf("request failed: %s", details) - } - - return body, nil -} - -func requestSpotifyJSON(client *http.Client, targetURL string, headers map[string]string, target interface{}) error { - body, err := requestSpotifyBytes(client, targetURL, headers) - if err != nil { - return err - } - - if err := json.Unmarshal(body, target); err != nil { - return fmt.Errorf("failed to parse JSON response: %w", err) - } - - return nil -} - -func loadSpotifyCachedToken() (*spotifyAnonymousToken, error) { - cachePath, err := spotifyTokenCachePath() - if err != nil { - return nil, err - } - - body, err := os.ReadFile(cachePath) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return nil, nil - } - return nil, fmt.Errorf("failed to read token cache: %w", err) - } - - var token spotifyAnonymousToken - if err := json.Unmarshal(body, &token); err != nil { - return nil, fmt.Errorf("failed to read token cache: %w", err) - } - - return &token, nil -} - -func saveSpotifyCachedToken(token *spotifyAnonymousToken) error { - cachePath, err := spotifyTokenCachePath() - if err != nil { - return err - } - - if err := os.MkdirAll(filepath.Dir(cachePath), 0o755); err != nil { - return fmt.Errorf("failed to create token cache directory: %w", err) - } - - body, err := json.MarshalIndent(token, "", " ") - if err != nil { - return err - } - - if err := os.WriteFile(cachePath, body, 0o644); err != nil { - return fmt.Errorf("failed to write token cache: %w", err) - } - - return nil -} - -func spotifyTokenCachePath() (string, error) { - appDir, err := EnsureAppDir() - if err != nil { - return "", err - } - - return filepath.Join(appDir, spotifyTokenCacheFile), nil -} - -func spotifyTokenIsValid(token *spotifyAnonymousToken) bool { - if token == nil || token.AccessToken == "" || token.AccessTokenExpirationTimestampMs == 0 { - return false - } - - return time.Now().UnixMilli() < token.AccessTokenExpirationTimestampMs-30_000 -} - -func requestSpotifyAnonymousAccessToken(client *http.Client) (string, error) { - spotifyAnonymousTokenMu.Lock() - defer spotifyAnonymousTokenMu.Unlock() - - cachedToken, err := loadSpotifyCachedToken() - if err != nil { - return "", err - } - - if spotifyTokenIsValid(cachedToken) { - return cachedToken.AccessToken, nil - } - - generatedTOTP, version, err := generateSpotifyTOTP(time.Now()) - if err != nil { - return "", fmt.Errorf("failed to generate Spotify TOTP: %w", err) - } - - query := url.Values{ - "reason": {"init"}, - "productType": {"web-player"}, - "totp": {generatedTOTP}, - "totpServer": {generatedTOTP}, - "totpVer": {strconv.Itoa(version)}, - } - - var token spotifyAnonymousToken - if err := requestSpotifyJSON(client, spotifySessionTokenURL+"?"+query.Encode(), nil, &token); err != nil { - return "", err - } - - if err := saveSpotifyCachedToken(&token); err != nil { - return "", err - } - - return token.AccessToken, nil -} - -func extractSpotifyTrackID(value string) (string, error) { - value = strings.TrimSpace(value) - if value == "" { - return "", errors.New("track input is required") - } - - if strings.HasPrefix(value, "spotify:track:") { - return value[strings.LastIndex(value, ":")+1:], nil - } - - parsed, err := url.Parse(value) - if err == nil && (parsed.Scheme == "http" || parsed.Scheme == "https") { - parts := strings.Split(strings.Trim(parsed.Path, "/"), "/") - if len(parts) >= 2 && parts[0] == "track" { - return parts[1], nil - } - return "", errors.New("expected URL like https://open.spotify.com/track/") - } - - if len(value) == 22 { - return value, nil - } - - return "", errors.New("track must be a Spotify track ID, URL, or URI") -} - -func spotifyTrackIDToGID(trackID string) (string, error) { - return spotifyEntityIDToGID(trackID) -} - -func spotifyEntityIDToGID(entityID string) (string, error) { - if entityID == "" { - return "", errors.New("entity ID is empty") - } - - value := big.NewInt(0) - base := big.NewInt(62) - - for _, char := range entityID { - index := strings.IndexRune(spotifyBase62Alphabet, char) - if index < 0 { - return "", fmt.Errorf("invalid base62 character: %q", string(char)) - } - - value.Mul(value, base) - value.Add(value, big.NewInt(int64(index))) - } - - hexValue := value.Text(16) - if len(hexValue) < 32 { - hexValue = strings.Repeat("0", 32-len(hexValue)) + hexValue - } - - return hexValue, nil -} - -func fetchSpotifyTrackRawData(client *http.Client, trackID string) ([]byte, error) { - gid, err := spotifyTrackIDToGID(trackID) - if err != nil { - return nil, err - } - - return fetchSpotifyRawMetadataByGID(client, "track", gid) -} - -func fetchSpotifyAlbumRawData(client *http.Client, albumID string) ([]byte, error) { - gid, err := spotifyEntityIDToGID(albumID) - if err != nil { - return nil, err - } - - return fetchSpotifyRawMetadataByGID(client, "album", gid) -} - -func fetchSpotifyRawMetadataByGID(client *http.Client, entityType string, gid string) ([]byte, error) { - accessToken, err := requestSpotifyAnonymousAccessToken(client) - if err != nil { - return nil, err - } - - return requestSpotifyBytes( - client, - fmt.Sprintf(spotifyGIDMetadataURL, entityType, gid), - map[string]string{ - "authorization": "Bearer " + accessToken, - "accept": "application/json", - "user-agent": songLinkUserAgent, - }, - ) -} - -func extractSpotifyTrackIdentifiers(client *http.Client, payload []byte) (SpotifyTrackIdentifiers, error) { - var track spotifyTrackRawData - if err := json.Unmarshal(payload, &track); err != nil { - return SpotifyTrackIdentifiers{}, fmt.Errorf("failed to decode Spotify track metadata: %w", err) - } - - identifiers := SpotifyTrackIdentifiers{} - for _, externalID := range track.ExternalID { - if strings.EqualFold(strings.TrimSpace(externalID.Type), "isrc") { - if isrc := firstISRCMatch(externalID.ID); isrc != "" { - identifiers.ISRC = isrc - break - } - } - } - - if identifiers.ISRC == "" { - identifiers.ISRC = firstISRCMatch(string(payload)) - } - - albumGID := strings.TrimSpace(track.Album.GID) - if client != nil && albumGID != "" { - albumPayload, err := fetchSpotifyRawMetadataByGID(client, "album", albumGID) - if err == nil { - if upc, upcErr := extractSpotifyAlbumUPC(albumPayload); upcErr == nil { - identifiers.UPC = upc - } - } - } - - return identifiers, nil -} - -func extractSpotifyTrackISRC(payload []byte) (string, error) { - identifiers, err := extractSpotifyTrackIdentifiers(nil, payload) - if err != nil { - return "", err - } - if identifiers.ISRC != "" { - return identifiers.ISRC, nil - } - - return "", fmt.Errorf("ISRC not found in Spotify track metadata") -} - -func extractSpotifyAlbumUPC(payload []byte) (string, error) { - var album spotifyAlbumRawData - if err := json.Unmarshal(payload, &album); err != nil { - return "", fmt.Errorf("failed to decode Spotify album metadata: %w", err) - } - - for _, externalID := range album.ExternalID { - if strings.EqualFold(strings.TrimSpace(externalID.Type), "upc") { - upc := strings.TrimSpace(externalID.ID) - if upc != "" { - return upc, nil - } - } - } - - return "", fmt.Errorf("UPC not found in Spotify album metadata") -} diff --git a/backend/isrc_helper.go b/backend/isrc_helper.go deleted file mode 100644 index 2f8283b..0000000 --- a/backend/isrc_helper.go +++ /dev/null @@ -1,22 +0,0 @@ -package backend - -import "strings" - -func ResolveTrackISRC(spotifyTrackID string) string { - spotifyTrackID = strings.TrimSpace(spotifyTrackID) - if spotifyTrackID == "" { - return "" - } - - if cachedISRC, err := GetCachedISRC(spotifyTrackID); err == nil && cachedISRC != "" { - return strings.ToUpper(strings.TrimSpace(cachedISRC)) - } - - client := NewSongLinkClient() - isrc, err := client.GetISRCDirect(spotifyTrackID) - if err != nil { - return "" - } - - return strings.ToUpper(strings.TrimSpace(isrc)) -} diff --git a/backend/link_resolver.go b/backend/link_resolver.go deleted file mode 100644 index 2c23573..0000000 --- a/backend/link_resolver.go +++ /dev/null @@ -1,154 +0,0 @@ -package backend - -import ( - "errors" - "fmt" - "strings" -) - -type resolvedTrackLinks struct { - TidalURL string - AmazonURL string - DeezerURL string - ISRC string -} - -const ( - linkResolverProviderSongstats = "songstats" - linkResolverProviderDeezerSongLink = "deezer-songlink" -) - -func (s *SongLinkClient) resolveSpotifyTrackLinks(spotifyTrackID string, region string) (*resolvedTrackLinks, error) { - links := &resolvedTrackLinks{} - var attempts []string - - isrc, err := s.lookupSpotifyISRC(spotifyTrackID) - if err != nil { - attempts = append(attempts, fmt.Sprintf("spotify isrc: %v", err)) - } else { - links.ISRC = isrc - } - - if links.ISRC != "" { - resolvers := orderedLinkResolvers() - - for _, resolver := range resolvers { - switch resolver { - case linkResolverProviderSongstats: - addedData, songstatsErr := s.resolveLinksViaSongstats(links) - if songstatsErr != nil { - attempts = append(attempts, fmt.Sprintf("songstats: %v", songstatsErr)) - } else if addedData { - fmt.Println("Using Songstats as configured link resolver") - } - case linkResolverProviderDeezerSongLink: - addedData, deezerSongLinkErr := s.resolveLinksViaDeezerSongLink(links, region) - if deezerSongLinkErr != nil { - attempts = append(attempts, fmt.Sprintf("deezer-songlink: %v", deezerSongLinkErr)) - } else if addedData { - fmt.Println("Using Songlink as configured link resolver") - } - } - - if links.TidalURL != "" && links.AmazonURL != "" { - return links, nil - } - } - } - - if hasAnySongLinkData(links) { - return links, nil - } - - if len(attempts) == 0 { - attempts = append(attempts, "no streaming URLs found") - } - - return links, errors.New(strings.Join(attempts, " | ")) -} - -func orderedLinkResolvers() []string { - preferred := GetLinkResolverSetting() - if !GetLinkResolverAllowFallback() { - if preferred == linkResolverProviderDeezerSongLink { - return []string{linkResolverProviderDeezerSongLink} - } - return []string{linkResolverProviderSongstats} - } - - if preferred == linkResolverProviderDeezerSongLink { - return []string{ - linkResolverProviderDeezerSongLink, - linkResolverProviderSongstats, - } - } - - return []string{ - linkResolverProviderSongstats, - linkResolverProviderDeezerSongLink, - } -} - -func (s *SongLinkClient) resolveLinksViaSongstats(links *resolvedTrackLinks) (bool, error) { - if links == nil || links.ISRC == "" { - return false, fmt.Errorf("ISRC is required for Songstats resolver") - } - - before := *links - - fmt.Printf("Fetching Songstats links for ISRC %s\n", links.ISRC) - if err := s.populateLinksFromSongstats(links, links.ISRC); err != nil { - return false, err - } - - return *links != before, nil -} - -func (s *SongLinkClient) resolveLinksViaDeezerSongLink(links *resolvedTrackLinks, region string) (bool, error) { - if links == nil || links.ISRC == "" { - return false, fmt.Errorf("ISRC is required for Deezer song.link resolver") - } - - before := *links - var attempts []string - - if links.DeezerURL == "" { - fmt.Printf("Resolving Deezer track from ISRC %s\n", links.ISRC) - deezerURL, err := s.lookupDeezerTrackURLByISRC(links.ISRC) - if err != nil { - attempts = append(attempts, fmt.Sprintf("deezer isrc: %v", err)) - } else { - links.DeezerURL = deezerURL - fmt.Printf("Found Deezer URL: %s\n", links.DeezerURL) - } - } - - if links.DeezerURL != "" { - fmt.Println("Resolving streaming URLs from song.link via Deezer URL...") - deezerResp, err := s.fetchSongLinkLinksByURL(links.DeezerURL, region) - if err != nil { - attempts = append(attempts, fmt.Sprintf("song.link deezer: %v", err)) - } else { - mergeSongLinkResponse(links, deezerResp) - } - - if links.ISRC == "" { - if resolvedISRC, deezerISRCErr := getDeezerISRC(links.DeezerURL); deezerISRCErr == nil { - links.ISRC = resolvedISRC - } - } - } - - if *links != before { - if len(attempts) == 0 { - return true, nil - } - return true, errors.New(strings.Join(attempts, " | ")) - } - - if len(attempts) == 0 { - attempts = append(attempts, "no links found via deezer-songlink") - } - - return false, errors.New(strings.Join(attempts, " | ")) -} diff --git a/backend/lyrics.go b/backend/lyrics.go deleted file mode 100644 index 16e025a..0000000 --- a/backend/lyrics.go +++ /dev/null @@ -1,540 +0,0 @@ -package backend - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "os" - "path/filepath" - "regexp" - "strings" - "time" -) - -type LRCLibResponse struct { - ID int `json:"id"` - Name string `json:"name"` - TrackName string `json:"trackName"` - ArtistName string `json:"artistName"` - AlbumName string `json:"albumName"` - Duration float64 `json:"duration"` - Instrumental bool `json:"instrumental"` - PlainLyrics string `json:"plainLyrics"` - SyncedLyrics string `json:"syncedLyrics"` -} - -type LyricsLine struct { - StartTimeMs string `json:"startTimeMs"` - Words string `json:"words"` - EndTimeMs string `json:"endTimeMs"` -} - -type LyricsResponse struct { - Error bool `json:"error"` - SyncType string `json:"syncType"` - Lines []LyricsLine `json:"lines"` -} - -type LyricsDownloadRequest struct { - SpotifyID string `json:"spotify_id"` - TrackName string `json:"track_name"` - ArtistName string `json:"artist_name"` - AlbumName string `json:"album_name"` - AlbumArtist string `json:"album_artist"` - ReleaseDate string `json:"release_date"` - ISRC string `json:"isrc"` - OutputDir string `json:"output_dir"` - FilenameFormat string `json:"filename_format"` - TrackNumber bool `json:"track_number"` - Position int `json:"position"` - UseAlbumTrackNumber bool `json:"use_album_track_number"` - DiscNumber int `json:"disc_number"` -} - -type LyricsDownloadResponse struct { - Success bool `json:"success"` - Message string `json:"message"` - File string `json:"file,omitempty"` - Error string `json:"error,omitempty"` - AlreadyExists bool `json:"already_exists,omitempty"` -} - -type LyricsClient struct { - httpClient *http.Client -} - -func NewLyricsClient() *LyricsClient { - return &LyricsClient{ - httpClient: &http.Client{Timeout: 15 * time.Second}, - } -} - -func (c *LyricsClient) FetchLyricsWithMetadata(trackName, artistName, albumName string, duration int) (*LyricsResponse, error) { - - apiURL := fmt.Sprintf("https://lrclib.net/api/get?artist_name=%s&track_name=%s", - url.QueryEscape(artistName), - url.QueryEscape(trackName)) - - if albumName != "" { - apiURL = fmt.Sprintf("%s&album_name=%s", apiURL, url.QueryEscape(albumName)) - } - - if duration > 0 { - apiURL = fmt.Sprintf("%s&duration=%d", apiURL, duration) - } - - resp, err := c.httpClient.Get(apiURL) - if err != nil { - return nil, fmt.Errorf("failed to fetch from LRCLIB: %v", err) - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return nil, fmt.Errorf("LRCLIB returned status %d", resp.StatusCode) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("failed to read LRCLIB response: %v", err) - } - - var lrcLibResp LRCLibResponse - if err := json.Unmarshal(body, &lrcLibResp); err != nil { - return nil, fmt.Errorf("failed to parse LRCLIB response: %v", err) - } - - if lrcLibResp.SyncedLyrics == "" && lrcLibResp.PlainLyrics == "" { - return nil, fmt.Errorf("LRCLIB returned empty lyrics") - } - - return c.convertLRCLibToLyricsResponse(&lrcLibResp), nil -} - -func (c *LyricsClient) convertLRCLibToLyricsResponse(lrcLib *LRCLibResponse) *LyricsResponse { - resp := &LyricsResponse{ - Error: false, - SyncType: "LINE_SYNCED", - Lines: []LyricsLine{}, - } - - lyricsText := lrcLib.SyncedLyrics - if lyricsText == "" { - lyricsText = lrcLib.PlainLyrics - resp.SyncType = "UNSYNCED" - } - - if lyricsText == "" { - resp.Error = true - return resp - } - - lines := strings.Split(lyricsText, "\n") - for _, line := range lines { - line = strings.TrimSpace(line) - if line == "" { - continue - } - - if strings.HasPrefix(line, "[") && len(line) > 10 { - closeBracket := strings.Index(line, "]") - if closeBracket > 0 { - timestamp := line[1:closeBracket] - words := strings.TrimSpace(line[closeBracket+1:]) - - ms := lrcTimestampToMs(timestamp) - resp.Lines = append(resp.Lines, LyricsLine{ - StartTimeMs: fmt.Sprintf("%d", ms), - Words: words, - }) - continue - } - } - - resp.Lines = append(resp.Lines, LyricsLine{ - StartTimeMs: "", - Words: line, - }) - } - - return resp -} - -func lrcTimestampToMs(timestamp string) int64 { - var minutes, seconds, centiseconds int64 - - n, _ := fmt.Sscanf(timestamp, "%d:%d.%d", &minutes, &seconds, ¢iseconds) - if n >= 2 { - return minutes*60*1000 + seconds*1000 + centiseconds*10 - } - return 0 -} - -func (c *LyricsClient) FetchLyricsFromLRCLibSearch(trackName, artistName string) (*LyricsResponse, error) { - - apiURL := fmt.Sprintf("https://lrclib.net/api/search?artist_name=%s&track_name=%s", - url.QueryEscape(artistName), - url.QueryEscape(trackName)) - - resp, err := c.httpClient.Get(apiURL) - if err != nil { - return nil, fmt.Errorf("request failed: %v", err) - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return nil, fmt.Errorf("status %d", resp.StatusCode) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("read failed: %v", err) - } - - var results []LRCLibResponse - if err := json.Unmarshal(body, &results); err != nil { - return nil, fmt.Errorf("parse failed: %v", err) - } - - if len(results) == 0 { - return nil, fmt.Errorf("no results found") - } - - var bestSynced *LRCLibResponse - var bestPlain *LRCLibResponse - for i := range results { - if results[i].SyncedLyrics != "" && bestSynced == nil { - bestSynced = &results[i] - } - if results[i].PlainLyrics != "" && bestPlain == nil { - bestPlain = &results[i] - } - if bestSynced != nil { - break - } - } - - best := bestSynced - if best == nil { - best = bestPlain - } - if best == nil { - best = &results[0] - } - - if best.SyncedLyrics == "" && best.PlainLyrics == "" { - return nil, fmt.Errorf("no lyrics found in search results") - } - - return c.convertLRCLibToLyricsResponse(best), nil -} - -func simplifyTrackName(name string) string { - - if idx := strings.Index(name, "("); idx > 0 { - name = strings.TrimSpace(name[:idx]) - } - - if idx := strings.Index(name, " - "); idx > 0 { - name = strings.TrimSpace(name[:idx]) - } - return name -} - -func isSynced(resp *LyricsResponse) bool { - return resp != nil && !resp.Error && resp.SyncType == "LINE_SYNCED" && len(resp.Lines) > 0 -} - -func hasLyrics(resp *LyricsResponse) bool { - return resp != nil && !resp.Error && len(resp.Lines) > 0 -} - -func (c *LyricsClient) FetchLyricsAllSources(spotifyID, trackName, artistName, albumName string, duration int) (*LyricsResponse, string, error) { - - var unsyncedFallback *LyricsResponse - var unsyncedSource string - - check := func(resp *LyricsResponse, err error, source string) (*LyricsResponse, string, bool) { - if err != nil || resp == nil || resp.Error || len(resp.Lines) == 0 { - return nil, "", false - } - if isSynced(resp) { - return resp, source, true - } - - if unsyncedFallback == nil { - unsyncedFallback = resp - unsyncedSource = source - } - return nil, "", false - } - - var resp *LyricsResponse - var src string - var found bool - - resp, _ = c.FetchLyricsWithMetadata(trackName, artistName, albumName, duration) - resp, src, found = check(resp, nil, "LRCLIB") - if found { - fmt.Printf(" [LRCLIB] Synced found via exact match (with album)\n") - return resp, src, nil - } - fmt.Printf(" LRCLIB exact (with album): no synced\n") - - if albumName != "" { - resp, _ = c.FetchLyricsWithMetadata(trackName, artistName, "", duration) - resp, src, found = check(resp, nil, "LRCLIB (no album)") - if found { - fmt.Printf(" [LRCLIB] Synced found via exact match (no album)\n") - return resp, src, nil - } - fmt.Printf(" LRCLIB exact (no album): no synced\n") - } - - resp, _ = c.FetchLyricsFromLRCLibSearch(trackName, artistName) - resp, src, found = check(resp, nil, "LRCLIB Search") - if found { - fmt.Printf(" [LRCLIB] Synced found via search\n") - return resp, src, nil - } - fmt.Printf(" LRCLIB search: no synced\n") - - simplifiedTrack := simplifyTrackName(trackName) - if simplifiedTrack != trackName { - fmt.Printf(" Trying simplified name: %s\n", simplifiedTrack) - - resp, _ = c.FetchLyricsWithMetadata(simplifiedTrack, artistName, albumName, duration) - resp, src, found = check(resp, nil, "LRCLIB (simplified)") - if found { - fmt.Printf(" [LRCLIB] Synced found via simplified exact\n") - return resp, src, nil - } - - resp, _ = c.FetchLyricsFromLRCLibSearch(simplifiedTrack, artistName) - resp, src, found = check(resp, nil, "LRCLIB Search (simplified)") - if found { - fmt.Printf(" [LRCLIB] Synced found via simplified search\n") - return resp, src, nil - } - } - - if unsyncedFallback != nil { - fmt.Printf(" [LRCLIB] No synced found, using unsynced from: %s\n", unsyncedSource) - return unsyncedFallback, unsyncedSource + " (unsynced)", nil - } - - return nil, "", fmt.Errorf("lyrics not found in any source") -} - -func (c *LyricsClient) ConvertToLRC(lyrics *LyricsResponse, trackName, artistName string) string { - var sb strings.Builder - - sb.WriteString(fmt.Sprintf("[ti:%s]\n", trackName)) - sb.WriteString(fmt.Sprintf("[ar:%s]\n", artistName)) - sb.WriteString("[by:SpotiFlac]\n") - sb.WriteString("\n") - - for _, line := range lyrics.Lines { - if line.Words == "" { - continue - } - - if line.StartTimeMs == "" { - sb.WriteString(fmt.Sprintf("%s\n", line.Words)) - } else { - - timestamp := msToLRCTimestamp(line.StartTimeMs) - sb.WriteString(fmt.Sprintf("%s%s\n", timestamp, line.Words)) - } - } - - return sb.String() -} - -func msToLRCTimestamp(msStr string) string { - var ms int64 - fmt.Sscanf(msStr, "%d", &ms) - - totalSeconds := ms / 1000 - minutes := totalSeconds / 60 - seconds := totalSeconds % 60 - centiseconds := (ms % 1000) / 10 - - return fmt.Sprintf("[%02d:%02d.%02d]", minutes, seconds, centiseconds) -} - -func buildLyricsFilename(trackName, artistName, albumName, albumArtist, releaseDate, filenameFormat, isrc string, includeTrackNumber bool, position, discNumber int) string { - safeTitle := sanitizeFilename(trackName) - safeArtist := sanitizeFilename(artistName) - safeAlbum := sanitizeFilename(albumName) - safeAlbumArtist := sanitizeFilename(albumArtist) - safeISRC := SanitizeOptionalFilename(isrc) - - year := "" - if len(releaseDate) >= 4 { - year = releaseDate[:4] - } - - var filename string - - if strings.Contains(filenameFormat, "{") { - filename = filenameFormat - filename = strings.ReplaceAll(filename, "{title}", safeTitle) - filename = strings.ReplaceAll(filename, "{artist}", safeArtist) - filename = strings.ReplaceAll(filename, "{album}", safeAlbum) - filename = strings.ReplaceAll(filename, "{album_artist}", safeAlbumArtist) - filename = strings.ReplaceAll(filename, "{year}", year) - filename = strings.ReplaceAll(filename, "{date}", sanitizeFilename(releaseDate)) - filename = strings.ReplaceAll(filename, "{isrc}", safeISRC) - - if discNumber > 0 { - filename = strings.ReplaceAll(filename, "{disc}", fmt.Sprintf("%d", discNumber)) - } else { - filename = strings.ReplaceAll(filename, "{disc}", "") - } - - if position > 0 { - filename = strings.ReplaceAll(filename, "{track}", fmt.Sprintf("%02d", position)) - } else { - - filename = regexp.MustCompile(`\{track\}\.\s*`).ReplaceAllString(filename, "") - filename = regexp.MustCompile(`\{track\}\s*-\s*`).ReplaceAllString(filename, "") - filename = regexp.MustCompile(`\{track\}\s*`).ReplaceAllString(filename, "") - } - } else { - - switch filenameFormat { - case "artist-title": - filename = fmt.Sprintf("%s - %s", safeArtist, safeTitle) - case "title": - filename = safeTitle - default: - filename = fmt.Sprintf("%s - %s", safeTitle, safeArtist) - } - - if includeTrackNumber && position > 0 { - filename = fmt.Sprintf("%02d. %s", position, filename) - } - } - - return filename + ".lrc" -} - -func findAudioFileForLyrics(dir, trackName, artistName string) string { - - safeTitle := sanitizeFilename(trackName) - safeArtist := sanitizeFilename(artistName) - - audioExts := []string{".flac", ".mp3", ".m4a", ".FLAC", ".MP3", ".M4A"} - - patterns := []string{ - fmt.Sprintf("%s - %s", safeTitle, safeArtist), - fmt.Sprintf("%s - %s", safeArtist, safeTitle), - safeTitle, - } - - entries, err := os.ReadDir(dir) - if err != nil { - return "" - } - - for _, entry := range entries { - if entry.IsDir() { - continue - } - - filename := entry.Name() - baseName := strings.TrimSuffix(filename, filepath.Ext(filename)) - - for _, pattern := range patterns { - if strings.HasPrefix(baseName, pattern) || strings.Contains(baseName, pattern) { - ext := strings.ToLower(filepath.Ext(filename)) - for _, audioExt := range audioExts { - if ext == strings.ToLower(audioExt) { - return filepath.Join(dir, filename) - } - } - } - } - } - - return "" -} - -func (c *LyricsClient) DownloadLyrics(req LyricsDownloadRequest) (*LyricsDownloadResponse, error) { - if req.SpotifyID == "" { - return &LyricsDownloadResponse{ - Success: false, - Error: "Spotify ID is required", - }, fmt.Errorf("spotify ID is required") - } - - outputDir := req.OutputDir - if outputDir == "" { - outputDir = GetDefaultMusicPath() - } else { - outputDir = NormalizePath(outputDir) - } - - if err := os.MkdirAll(outputDir, 0755); err != nil { - return &LyricsDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to create output directory: %v", err), - }, err - } - - filenameFormat := req.FilenameFormat - if filenameFormat == "" { - filenameFormat = "title-artist" - } - resolvedISRC := strings.TrimSpace(req.ISRC) - if resolvedISRC == "" && strings.Contains(filenameFormat, "{isrc}") { - resolvedISRC = ResolveTrackISRC(req.SpotifyID) - } - filename := buildLyricsFilename(req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, filenameFormat, resolvedISRC, req.TrackNumber, req.Position, req.DiscNumber) - filePath := filepath.Join(outputDir, filename) - - filePath, alreadyExists := ResolveOutputPathForDownload(filePath, GetRedownloadWithSuffixSetting()) - if alreadyExists { - return &LyricsDownloadResponse{ - Success: true, - Message: "Lyrics file already exists", - File: filePath, - AlreadyExists: true, - }, nil - } - - audioDuration := 0 - audioFile := findAudioFileForLyrics(outputDir, req.TrackName, req.ArtistName) - if audioFile != "" { - duration, err := GetAudioDuration(audioFile) - if err == nil && duration > 0 { - audioDuration = int(duration) - fmt.Printf("[DownloadLyrics] Found audio file, duration: %d seconds\n", audioDuration) - } - } - - lyrics, _, err := c.FetchLyricsAllSources(req.SpotifyID, req.TrackName, req.ArtistName, req.AlbumName, audioDuration) - if err != nil { - return &LyricsDownloadResponse{ - Success: false, - Error: err.Error(), - }, err - } - - lrcContent := c.ConvertToLRC(lyrics, req.TrackName, req.ArtistName) - - if err := os.WriteFile(filePath, []byte(lrcContent), 0644); err != nil { - return &LyricsDownloadResponse{ - Success: false, - Error: fmt.Sprintf("failed to write LRC file: %v", err), - }, err - } - - return &LyricsDownloadResponse{ - Success: true, - Message: "Lyrics downloaded successfully", - File: filePath, - }, nil -} diff --git a/backend/metadata.go b/backend/metadata.go deleted file mode 100644 index f438338..0000000 --- a/backend/metadata.go +++ /dev/null @@ -1,1255 +0,0 @@ -package backend - -import ( - "encoding/json" - "fmt" - "os" - "os/exec" - pathfilepath "path/filepath" - "strconv" - "strings" - - id3v2 "github.com/bogem/id3v2/v2" - "github.com/go-flac/flacpicture" - "github.com/go-flac/flacvorbis" - "github.com/go-flac/go-flac" - "golang.org/x/text/unicode/norm" -) - -type Metadata struct { - Title string - Artist string - Album string - AlbumArtist string - Separator string - Date string - ReleaseDate string - TrackNumber int - TotalTracks int - DiscNumber int - TotalDiscs int - URL string - Comment string - Copyright string - Publisher string - Composer string - Lyrics string - Description string - ISRC string - UPC string - Genre string -} - -func resolveMetadataSeparator(separator string) string { - if normalized := normalizeArtistSeparator(separator); normalized != "" { - return normalized - } - - return normalizeArtistSeparator(GetSeparator()) -} - -func displayMetadataSeparator(separator string) string { - if resolved := resolveMetadataSeparator(separator); resolved != "" { - return resolved + " " - } - - return "; " -} - -func addVorbisTagValues(cmt *flacvorbis.MetaDataBlockVorbisComment, key string, values []string) { - for _, value := range values { - value = strings.TrimSpace(value) - if value == "" { - continue - } - - _ = cmt.Add(key, value) - } -} - -func addMP3TextFrame(tag *id3v2.Tag, frameID string, value string) { - tag.DeleteFrames(frameID) - value = strings.TrimSpace(value) - if value == "" { - return - } - - tag.AddTextFrame(frameID, id3v2.EncodingUTF8, value) -} - -func joinMultiValueText(values []string, separator string, nullSeparated bool) string { - cleaned := make([]string, 0, len(values)) - for _, value := range values { - value = strings.TrimSpace(value) - if value != "" { - cleaned = append(cleaned, value) - } - } - - if len(cleaned) == 0 { - return "" - } - if len(cleaned) == 1 { - return cleaned[0] - } - if nullSeparated { - return strings.Join(cleaned, "\x00") - } - - return strings.Join(cleaned, displayMetadataSeparator(separator)) -} - -func EmbedMetadata(filepath string, metadata Metadata, coverPath string) error { - f, err := flac.ParseFile(filepath) - if err != nil { - return fmt.Errorf("failed to parse FLAC file: %w", err) - } - - var cmtIdx = -1 - for idx, block := range f.Meta { - if block.Type == flac.VorbisComment { - cmtIdx = idx - break - } - } - - cmt := flacvorbis.New() - separator := resolveMetadataSeparator(metadata.Separator) - - if metadata.Title != "" { - _ = cmt.Add(flacvorbis.FIELD_TITLE, metadata.Title) - } - if artistValues := SplitArtistCredits(metadata.Artist, separator); len(artistValues) > 0 { - addVorbisTagValues(cmt, flacvorbis.FIELD_ARTIST, artistValues) - } else if metadata.Artist != "" { - _ = cmt.Add(flacvorbis.FIELD_ARTIST, metadata.Artist) - } - if metadata.Album != "" { - _ = cmt.Add(flacvorbis.FIELD_ALBUM, metadata.Album) - } - if albumArtistValues := SplitArtistCredits(metadata.AlbumArtist, separator); len(albumArtistValues) > 0 { - addVorbisTagValues(cmt, "ALBUMARTIST", albumArtistValues) - } else if metadata.AlbumArtist != "" { - _ = cmt.Add("ALBUMARTIST", metadata.AlbumArtist) - } - if metadata.Date != "" { - _ = cmt.Add(flacvorbis.FIELD_DATE, metadata.Date) - } - if metadata.TrackNumber > 0 { - _ = cmt.Add(flacvorbis.FIELD_TRACKNUMBER, strconv.Itoa(metadata.TrackNumber)) - } - if metadata.TotalTracks > 0 { - _ = cmt.Add("TOTALTRACKS", strconv.Itoa(metadata.TotalTracks)) - } - if metadata.DiscNumber > 0 { - _ = cmt.Add("DISCNUMBER", strconv.Itoa(metadata.DiscNumber)) - } - if metadata.TotalDiscs > 0 { - _ = cmt.Add("TOTALDISCS", strconv.Itoa(metadata.TotalDiscs)) - } - if metadata.Copyright != "" { - _ = cmt.Add("COPYRIGHT", metadata.Copyright) - } - if metadata.Publisher != "" { - _ = cmt.Add("PUBLISHER", metadata.Publisher) - } - if composerValues := SplitArtistCredits(metadata.Composer, separator); len(composerValues) > 0 { - addVorbisTagValues(cmt, "COMPOSER", composerValues) - } else if metadata.Composer != "" { - _ = cmt.Add("COMPOSER", metadata.Composer) - } - if metadata.Description != "" { - _ = cmt.Add("DESCRIPTION", metadata.Description) - } - if comment := resolveMetadataComment(metadata); comment != "" { - _ = cmt.Add("COMMENT", comment) - } - - if metadata.ISRC != "" { - _ = cmt.Add("ISRC", metadata.ISRC) - } - if metadata.UPC != "" { - _ = cmt.Add(preferredUPCTagKey, metadata.UPC) - } - - if genreValues := SplitMetadataValues(metadata.Genre, separator); len(genreValues) > 0 { - addVorbisTagValues(cmt, "GENRE", genreValues) - } else if metadata.Genre != "" { - _ = cmt.Add("GENRE", metadata.Genre) - } - - if metadata.Lyrics != "" { - _ = cmt.Add("LYRICS", metadata.Lyrics) - } - - cmtBlock := cmt.Marshal() - if cmtIdx < 0 { - f.Meta = append(f.Meta, &cmtBlock) - } else { - f.Meta[cmtIdx] = &cmtBlock - } - - if coverPath != "" && fileExists(coverPath) { - if err := embedCoverArt(f, coverPath); err != nil { - fmt.Printf("Warning: Failed to embed cover art: %v\n", err) - } - } - - if err := f.Save(filepath); err != nil { - return fmt.Errorf("failed to save FLAC file: %w", err) - } - - return nil -} - -func embedCoverArt(f *flac.File, coverPath string) error { - imgData, err := os.ReadFile(coverPath) - if err != nil { - return fmt.Errorf("failed to read cover image: %w", err) - } - - picture, err := flacpicture.NewFromImageData( - flacpicture.PictureTypeFrontCover, - "Cover", - imgData, - "image/jpeg", - ) - if err != nil { - return fmt.Errorf("failed to create picture block: %w", err) - } - - pictureBlock := picture.Marshal() - - for i := len(f.Meta) - 1; i >= 0; i-- { - if f.Meta[i].Type == flac.Picture { - f.Meta = append(f.Meta[:i], f.Meta[i+1:]...) - } - } - - f.Meta = append(f.Meta, &pictureBlock) - - return nil -} - -func fileExists(path string) bool { - _, err := os.Stat(path) - return err == nil -} - -func extractYear(releaseDate string) string { - if releaseDate == "" { - return "" - } - - if len(releaseDate) >= 4 { - return releaseDate[:4] - } - return releaseDate -} - -func resolveMetadataComment(metadata Metadata) string { - if comment := strings.TrimSpace(metadata.Comment); comment != "" { - return comment - } - - return strings.TrimSpace(metadata.URL) -} - -func EmbedLyricsOnly(filepath string, lyrics string) error { - if lyrics == "" { - return nil - } - f, err := flac.ParseFile(filepath) - if err != nil { - return fmt.Errorf("failed to parse FLAC file: %w", err) - } - - var cmtIdx = -1 - var existingCmt *flacvorbis.MetaDataBlockVorbisComment - for idx, block := range f.Meta { - if block.Type == flac.VorbisComment { - cmtIdx = idx - existingCmt, err = flacvorbis.ParseFromMetaDataBlock(*block) - if err != nil { - existingCmt = nil - } - break - } - } - - cmt := flacvorbis.New() - - if existingCmt != nil { - for _, comment := range existingCmt.Comments { - parts := strings.SplitN(comment, "=", 2) - if len(parts) == 2 { - fieldName := strings.ToUpper(parts[0]) - if fieldName != "LYRICS" && fieldName != "UNSYNCEDLYRICS" && fieldName != "SYNCEDLYRICS" { - _ = cmt.Add(parts[0], parts[1]) - } - } - } - } - - _ = cmt.Add("LYRICS", lyrics) - - cmtBlock := cmt.Marshal() - if cmtIdx < 0 { - f.Meta = append(f.Meta, &cmtBlock) - } else { - f.Meta[cmtIdx] = &cmtBlock - } - - if err := f.Save(filepath); err != nil { - return fmt.Errorf("failed to save FLAC file: %w", err) - } - - return nil -} - -func ExtractCoverArt(filePath string) (string, error) { - filePath = norm.NFC.String(filePath) - ext := strings.ToLower(pathfilepath.Ext(filePath)) - - var coverPath string - var err error - - switch ext { - case ".mp3": - coverPath, err = extractCoverFromMp3(filePath) - case ".m4a", ".flac": - coverPath, err = extractCoverFromM4AOrFlac(filePath) - default: - return "", fmt.Errorf("unsupported file format: %s", ext) - } - - if err != nil || coverPath == "" { - fmt.Printf("[ExtractCoverArt] Library extraction failed for %s, trying FFmpeg fallback...\n", filePath) - ffmpegCover, ffmpegErr := extractCoverWithFFmpeg(filePath) - if ffmpegErr == nil { - return ffmpegCover, nil - } - return coverPath, err - } - - return coverPath, nil -} - -func extractCoverWithFFmpeg(filePath string) (string, error) { - ffmpegPath, err := GetFFmpegPath() - if err != nil { - return "", err - } - - tmpFile, err := os.CreateTemp("", "cover-*.jpg") - if err != nil { - return "", err - } - tmpPath := tmpFile.Name() - tmpFile.Close() - - cmd := exec.Command(ffmpegPath, - "-i", filePath, - "-an", - "-vframes", "1", - "-f", "image2", - "-update", "1", - "-y", - tmpPath, - ) - - setHideWindow(cmd) - if output, err := cmd.CombinedOutput(); err != nil { - os.Remove(tmpPath) - return "", fmt.Errorf("ffmpeg cover extraction failed: %v, output: %s", err, string(output)) - } - - if info, err := os.Stat(tmpPath); err != nil || info.Size() == 0 { - os.Remove(tmpPath) - return "", fmt.Errorf("ffmpeg produced empty cover file") - } - - return tmpPath, nil -} - -func extractCoverFromMp3(filePath string) (string, error) { - tag, err := id3v2.Open(filePath, id3v2.Options{Parse: true}) - if err != nil { - return "", fmt.Errorf("failed to open MP3 file: %w", err) - } - defer tag.Close() - - pictures := tag.GetFrames(tag.CommonID("Attached picture")) - if len(pictures) == 0 { - return "", fmt.Errorf("no cover art found") - } - - pic, ok := pictures[0].(id3v2.PictureFrame) - if !ok { - return "", fmt.Errorf("invalid picture frame") - } - - tmpFile, err := os.CreateTemp("", "cover-*.jpg") - if err != nil { - return "", fmt.Errorf("failed to create temp file: %w", err) - } - defer tmpFile.Close() - - if _, err := tmpFile.Write(pic.Picture); err != nil { - os.Remove(tmpFile.Name()) - return "", fmt.Errorf("failed to write cover art: %w", err) - } - - return tmpFile.Name(), nil -} - -func extractCoverFromM4AOrFlac(filePath string) (string, error) { - ext := strings.ToLower(pathfilepath.Ext(filePath)) - - if ext == ".flac" { - f, err := flac.ParseFile(filePath) - if err != nil { - return "", fmt.Errorf("failed to parse FLAC file: %w", err) - } - - for _, block := range f.Meta { - if block.Type == flac.Picture { - pic, err := flacpicture.ParseFromMetaDataBlock(*block) - if err != nil { - continue - } - - tmpFile, err := os.CreateTemp("", "cover-*.jpg") - if err != nil { - return "", fmt.Errorf("failed to create temp file: %w", err) - } - defer tmpFile.Close() - - if _, err := tmpFile.Write(pic.ImageData); err != nil { - os.Remove(tmpFile.Name()) - return "", fmt.Errorf("failed to write cover art: %w", err) - } - - return tmpFile.Name(), nil - } - } - return "", fmt.Errorf("no cover art found") - } - - return "", nil -} - -func ExtractLyrics(filePath string) (string, error) { - filePath = norm.NFC.String(filePath) - ext := strings.ToLower(pathfilepath.Ext(filePath)) - - var lyrics string - var err error - - switch ext { - case ".mp3": - lyrics, err = extractLyricsFromMp3(filePath) - case ".flac": - lyrics, err = extractLyricsFromFlac(filePath) - case ".m4a": - return "", nil - default: - return "", fmt.Errorf("unsupported file format: %s", ext) - } - - if (err != nil || lyrics == "") && ext != ".m4a" { - fmt.Printf("[ExtractLyrics] Library extraction failed for %s, trying ffprobe fallback...\n", filePath) - ffprobeLyrics, ffprobeErr := extractLyricsWithFFprobe(filePath) - if ffprobeErr == nil && ffprobeLyrics != "" { - return ffprobeLyrics, nil - } - } - - return lyrics, err -} - -func extractLyricsWithFFprobe(filePath string) (string, error) { - ffprobePath, err := GetFFprobePath() - if err != nil { - return "", err - } - - cmd := exec.Command(ffprobePath, - "-v", "quiet", - "-show_entries", "format_tags=lyrics:format_tags=unsyncedlyrics:format_tags=lyric", - "-of", "json", - filePath, - ) - - setHideWindow(cmd) - output, err := cmd.CombinedOutput() - if err != nil { - return "", err - } - - var result struct { - Format struct { - Tags map[string]string `json:"tags"` - } `json:"format"` - } - - if err := json.Unmarshal(output, &result); err != nil { - return "", err - } - - tags := result.Format.Tags - for _, key := range []string{"lyrics", "unsyncedlyrics", "lyric", "LYRICS", "UNSYNCEDLYRICS", "LYRIC"} { - if val, ok := tags[key]; ok && val != "" { - return val, nil - } - } - - return "", nil -} - -func extractLyricsFromMp3(filePath string) (string, error) { - tag, err := id3v2.Open(filePath, id3v2.Options{Parse: true}) - if err != nil { - return "", fmt.Errorf("failed to open MP3 file: %w", err) - } - defer tag.Close() - - usltFrames := tag.GetFrames(tag.CommonID("Unsynchronised lyrics/text transcription")) - if len(usltFrames) == 0 { - fmt.Printf("[ExtractLyrics] No USLT frames found in MP3: %s\n", filePath) - return "", nil - } - - uslt, ok := usltFrames[0].(id3v2.UnsynchronisedLyricsFrame) - if !ok { - fmt.Printf("[ExtractLyrics] USLT frame type assertion failed in MP3: %s\n", filePath) - return "", nil - } - - if uslt.Lyrics == "" { - fmt.Printf("[ExtractLyrics] USLT frame has empty lyrics in MP3: %s\n", filePath) - return "", nil - } - - fmt.Printf("[ExtractLyrics] Successfully extracted lyrics from MP3: %s (%d characters)\n", filePath, len(uslt.Lyrics)) - return uslt.Lyrics, nil -} - -func extractLyricsFromFlac(filePath string) (string, error) { - f, err := flac.ParseFile(filePath) - if err != nil { - return "", fmt.Errorf("failed to parse FLAC file: %w", err) - } - - for _, block := range f.Meta { - if block.Type == flac.VorbisComment { - cmt, err := flacvorbis.ParseFromMetaDataBlock(*block) - if err != nil { - continue - } - - for _, comment := range cmt.Comments { - parts := strings.SplitN(comment, "=", 2) - if len(parts) == 2 { - fieldName := strings.ToUpper(parts[0]) - if fieldName == "LYRICS" || fieldName == "UNSYNCEDLYRICS" { - lyrics := parts[1] - fmt.Printf("[ExtractLyrics] Successfully extracted lyrics from FLAC: %s (%d characters)\n", filePath, len(lyrics)) - return lyrics, nil - } - } - } - } - } - - fmt.Printf("[ExtractLyrics] No lyrics found in FLAC: %s\n", filePath) - return "", nil -} - -func EmbedCoverArtOnly(filePath string, coverPath string) error { - if coverPath == "" || !fileExists(coverPath) { - return nil - } - - ext := strings.ToLower(pathfilepath.Ext(filePath)) - - switch ext { - case ".mp3": - return embedCoverToMp3(filePath, coverPath) - case ".m4a": - - return nil - default: - return fmt.Errorf("unsupported file format: %s", ext) - } -} - -func embedCoverToMp3(filePath string, coverPath string) error { - tag, err := id3v2.Open(filePath, id3v2.Options{Parse: true}) - if err != nil { - return fmt.Errorf("failed to open MP3 file: %w", err) - } - defer tag.Close() - - tag.DeleteFrames(tag.CommonID("Attached picture")) - - artwork, err := os.ReadFile(coverPath) - if err != nil { - return fmt.Errorf("failed to read cover art: %w", err) - } - - pic := id3v2.PictureFrame{ - Encoding: id3v2.EncodingUTF8, - MimeType: "image/jpeg", - PictureType: id3v2.PTFrontCover, - Description: "Front cover", - Picture: artwork, - } - tag.AddAttachedPicture(pic) - - if err := tag.Save(); err != nil { - return fmt.Errorf("failed to save MP3 tags: %w", err) - } - - return nil -} - -func EmbedLyricsOnlyMP3(filepath string, lyrics string) error { - if lyrics == "" { - return nil - } - - validatedLyrics, err := validateLyricsDuration(lyrics, filepath) - if err != nil { - fmt.Printf("[EmbedLyricsOnlyMP3] Warning: Failed to validate lyrics duration: %v, using original lyrics\n", err) - validatedLyrics = lyrics - } - lyrics = validatedLyrics - - tag, err := id3v2.Open(filepath, id3v2.Options{Parse: true}) - if err != nil { - return fmt.Errorf("failed to open MP3 file: %w", err) - } - defer tag.Close() - - tag.DeleteFrames(tag.CommonID("Unsynchronised lyrics/text transcription")) - - usltFrame := id3v2.UnsynchronisedLyricsFrame{ - Encoding: id3v2.EncodingUTF8, - Language: "eng", - ContentDescriptor: "", - Lyrics: lyrics, - } - tag.AddUnsynchronisedLyricsFrame(usltFrame) - - if err := tag.Save(); err != nil { - return fmt.Errorf("failed to save MP3 tags: %w", err) - } - - return nil -} - -func embedLyricsToM4A(filepath string, lyrics string) error { - - validatedLyrics, err := validateLyricsDuration(lyrics, filepath) - if err != nil { - fmt.Printf("[embedLyricsToM4A] Warning: Failed to validate lyrics duration: %v, using original lyrics\n", err) - validatedLyrics = lyrics - } - lyrics = validatedLyrics - - ffmpegPath, err := GetFFmpegPath() - if err != nil { - return fmt.Errorf("ffmpeg not found: %w", err) - } - - if err := ValidateExecutable(ffmpegPath); err != nil { - return fmt.Errorf("invalid ffmpeg executable: %w", err) - } - - tmpOutputFile := strings.TrimSuffix(filepath, pathfilepath.Ext(filepath)) + ".tmp" + pathfilepath.Ext(filepath) - defer func() { - - if _, err := os.Stat(tmpOutputFile); err == nil { - os.Remove(tmpOutputFile) - } - }() - - cmd := exec.Command(ffmpegPath, - "-i", filepath, - "-map", "0", - "-map_metadata", "0", - "-metadata", "lyrics-eng="+lyrics, - "-metadata", "lyrics="+lyrics, - "-codec", "copy", - "-f", "ipod", - "-y", - tmpOutputFile, - ) - - setHideWindow(cmd) - - output, err := cmd.CombinedOutput() - if err != nil { - fmt.Printf("[FFmpeg] Error embedding lyrics to M4A: %s\n", string(output)) - return fmt.Errorf("ffmpeg failed to embed lyrics: %s - %w", string(output), err) - } - - if err := os.Rename(tmpOutputFile, filepath); err != nil { - return fmt.Errorf("failed to replace original file: %w", err) - } - - fmt.Printf("[FFmpeg] Lyrics embedded to M4A successfully: %d characters\n", len(lyrics)) - return nil -} - -func EmbedLyricsOnlyUniversal(filepath string, lyrics string) error { - if lyrics == "" { - return nil - } - - validatedLyrics, err := validateLyricsDuration(lyrics, filepath) - if err != nil { - fmt.Printf("[EmbedLyricsOnlyUniversal] Warning: Failed to validate lyrics duration: %v, using original lyrics\n", err) - validatedLyrics = lyrics - } - lyrics = validatedLyrics - - ext := strings.ToLower(pathfilepath.Ext(filepath)) - switch ext { - case ".mp3": - return EmbedLyricsOnlyMP3(filepath, lyrics) - case ".flac": - return EmbedLyricsOnly(filepath, lyrics) - case ".m4a": - return embedLyricsToM4A(filepath, lyrics) - default: - return fmt.Errorf("unsupported file format for lyrics embedding: %s", ext) - } -} - -func GetAudioDuration(filepath string) (float64, error) { - ext := strings.ToLower(pathfilepath.Ext(filepath)) - - if ext == ".flac" { - duration, err := getFlacDuration(filepath) - if err == nil && duration > 0 { - return duration, nil - } - } - - return getDurationWithFFprobe(filepath) -} - -func getFlacDuration(filepath string) (float64, error) { - f, err := flac.ParseFile(filepath) - if err != nil { - return 0, err - } - - if len(f.Meta) > 0 { - streamInfo := f.Meta[0] - if streamInfo.Type == flac.StreamInfo { - data := streamInfo.Data - if len(data) >= 18 { - - sampleRate := uint32(data[10])<<12 | uint32(data[11])<<4 | uint32(data[12])>>4 - - totalSamples := uint64(data[13]&0x0F)<<32 | - uint64(data[14])<<24 | - uint64(data[15])<<16 | - uint64(data[16])<<8 | - uint64(data[17]) - - if sampleRate > 0 { - return float64(totalSamples) / float64(sampleRate), nil - } - } - } - } - - return 0, fmt.Errorf("could not extract duration from FLAC file") -} - -func getDurationWithFFprobe(filepath string) (float64, error) { - ffprobePath, err := GetFFprobePath() - if err != nil { - return 0, err - } - - if err := ValidateExecutable(ffprobePath); err != nil { - return 0, fmt.Errorf("invalid ffprobe executable: %w", err) - } - - cmd := exec.Command(ffprobePath, - "-v", "quiet", - "-print_format", "json", - "-show_format", - filepath, - ) - - setHideWindow(cmd) - - output, err := cmd.Output() - if err != nil { - return 0, err - } - - var result struct { - Format struct { - Duration string `json:"duration"` - } `json:"format"` - } - - if err := json.Unmarshal(output, &result); err != nil { - return 0, err - } - - if result.Format.Duration == "" { - return 0, fmt.Errorf("duration not found in ffprobe output") - } - - duration, err := strconv.ParseFloat(result.Format.Duration, 64) - if err != nil { - return 0, err - } - - return duration, nil -} - -func validateLyricsDuration(lyrics string, filepath string) (string, error) { - - duration, err := GetAudioDuration(filepath) - if err != nil { - - fmt.Printf("[ValidateLyrics] Warning: Could not get audio duration: %v, skipping validation\n", err) - return lyrics, nil - } - - if duration <= 0 { - - fmt.Printf("[ValidateLyrics] Warning: Invalid duration (%f seconds), skipping validation\n", duration) - return lyrics, nil - } - - durationMs := int64(duration * 1000) - - lines := strings.Split(lyrics, "\n") - var validLines []string - - for _, line := range lines { - trimmedLine := strings.TrimSpace(line) - if trimmedLine == "" { - validLines = append(validLines, line) - continue - } - - if strings.HasPrefix(trimmedLine, "[") { - - closeBracket := strings.Index(trimmedLine, "]") - if closeBracket > 0 { - timestampStr := trimmedLine[1:closeBracket] - - ms := parseLRCTimestamp(timestampStr) - if ms >= 0 { - if ms <= durationMs { - validLines = append(validLines, line) - } else { - fmt.Printf("[ValidateLyrics] Filtered out line with timestamp %s (exceeds duration %d ms): %s\n", timestampStr, durationMs, trimmedLine) - } - } else { - - validLines = append(validLines, line) - } - continue - } - } else { - - validLines = append(validLines, line) - } - } - - return strings.Join(validLines, "\n"), nil -} - -func parseLRCTimestamp(timestamp string) int64 { - var minutes, seconds, centiseconds int64 - n, _ := fmt.Sscanf(timestamp, "%d:%d.%d", &minutes, &seconds, ¢iseconds) - if n >= 2 { - return minutes*60*1000 + seconds*1000 + centiseconds*10 - } - return -1 -} - -func ExtractFullMetadataFromFile(filePath string) (Metadata, error) { - filePath = norm.NFC.String(filePath) - var metadata Metadata - - ffprobePath, err := GetFFprobePath() - if err != nil { - return metadata, err - } - - if err := ValidateExecutable(ffprobePath); err != nil { - return metadata, fmt.Errorf("invalid ffprobe executable: %w", err) - } - - cmd := exec.Command(ffprobePath, - "-v", "quiet", - "-print_format", "json", - "-show_format", - "-show_streams", - filePath, - ) - - setHideWindow(cmd) - - output, err := cmd.Output() - if err != nil { - return metadata, err - } - - var result struct { - Format struct { - Tags map[string]string `json:"tags"` - } `json:"format"` - Streams []struct { - Tags map[string]string `json:"tags"` - } `json:"streams"` - } - - if err := json.Unmarshal(output, &result); err != nil { - return metadata, err - } - - allTags := make(map[string]string) - - for _, stream := range result.Streams { - for key, value := range stream.Tags { - allTags[strings.ToLower(key)] = value - } - } - - for key, value := range result.Format.Tags { - allTags[strings.ToLower(key)] = value - } - - for key, value := range allTags { - switch key { - case "title": - metadata.Title = value - case "artist": - metadata.Artist = value - case "album": - metadata.Album = value - case "album_artist", "albumartist": - metadata.AlbumArtist = value - case "date", "year": - if metadata.Date == "" || len(value) > len(metadata.Date) { - metadata.Date = value - } - case "track": - - parts := strings.Split(value, "/") - if len(parts) > 0 { - if num, err := strconv.Atoi(parts[0]); err == nil { - metadata.TrackNumber = num - } - } - if len(parts) > 1 { - if num, err := strconv.Atoi(parts[1]); err == nil { - metadata.TotalTracks = num - } - } - case "disc": - - parts := strings.Split(value, "/") - if len(parts) > 0 { - if num, err := strconv.Atoi(parts[0]); err == nil { - metadata.DiscNumber = num - } - } - if len(parts) > 1 { - if num, err := strconv.Atoi(parts[1]); err == nil { - metadata.TotalDiscs = num - } - } - case "copyright", "tcop": - metadata.Copyright = value - case "publisher", "tpub", "label": - metadata.Publisher = value - case "composer", "writer", "wm/composer", "©wrt": - metadata.Composer = value - case "genre", "tcon": - metadata.Genre = value - case "url": - metadata.URL = value - case "isrc", "tsrc": - metadata.ISRC = value - case "comment", "comments": - if metadata.Comment == "" { - metadata.Comment = value - } - case "description": - if metadata.Description == "" { - metadata.Description = value - } - } - } - - metadata.UPC = firstPreferredFFprobeUPCValue(allTags) - - return metadata, nil -} - -func EmbedMetadataToConvertedFile(filePath string, metadata Metadata, coverPath string) error { - filePath = norm.NFC.String(filePath) - ext := strings.ToLower(pathfilepath.Ext(filePath)) - - switch ext { - case ".flac": - - return EmbedMetadata(filePath, metadata, coverPath) - case ".mp3": - return embedMetadataToMP3(filePath, metadata, coverPath) - case ".m4a": - return embedMetadataToM4A(filePath, metadata, coverPath) - default: - return fmt.Errorf("unsupported file format: %s", ext) - } -} - -func embedMetadataToMP3(filePath string, metadata Metadata, coverPath string) error { - tag, err := id3v2.Open(filePath, id3v2.Options{Parse: true}) - if err != nil { - return fmt.Errorf("failed to open MP3 file: %w", err) - } - defer tag.Close() - separator := resolveMetadataSeparator(metadata.Separator) - - tag.DeleteFrames("TXXX") - - if metadata.Title != "" { - tag.SetTitle(metadata.Title) - } - if metadata.Album != "" { - tag.SetAlbum(metadata.Album) - } - if metadata.Date != "" { - year := metadata.Date - if len(year) >= 4 { - year = year[:4] - } - tag.SetYear(year) - } - - artistText := joinMultiValueText(SplitArtistCredits(metadata.Artist, separator), separator, true) - if artistText == "" { - artistText = strings.TrimSpace(metadata.Artist) - } - addMP3TextFrame(tag, "TPE1", artistText) - - albumArtistText := joinMultiValueText(SplitArtistCredits(metadata.AlbumArtist, separator), separator, true) - if albumArtistText == "" { - albumArtistText = strings.TrimSpace(metadata.AlbumArtist) - } - addMP3TextFrame(tag, "TPE2", albumArtistText) - - if metadata.TrackNumber > 0 { - tag.DeleteFrames(tag.CommonID("Track number/Position in set")) - trackStr := strconv.Itoa(metadata.TrackNumber) - if metadata.TotalTracks > 0 { - trackStr = fmt.Sprintf("%d/%d", metadata.TrackNumber, metadata.TotalTracks) - } - tag.AddTextFrame(tag.CommonID("Track number/Position in set"), id3v2.EncodingUTF8, trackStr) - } - - if metadata.DiscNumber > 0 { - tag.DeleteFrames(tag.CommonID("Part of a set")) - discStr := strconv.Itoa(metadata.DiscNumber) - if metadata.TotalDiscs > 0 { - discStr = fmt.Sprintf("%d/%d", metadata.DiscNumber, metadata.TotalDiscs) - } - tag.AddTextFrame(tag.CommonID("Part of a set"), id3v2.EncodingUTF8, discStr) - } - - if metadata.Copyright != "" { - addMP3TextFrame(tag, "TCOP", metadata.Copyright) - } - - if metadata.Publisher != "" { - addMP3TextFrame(tag, "TPUB", metadata.Publisher) - } - - composerText := joinMultiValueText(SplitArtistCredits(metadata.Composer, separator), separator, true) - if composerText == "" { - composerText = strings.TrimSpace(metadata.Composer) - } - addMP3TextFrame(tag, "TCOM", composerText) - - if metadata.ISRC != "" { - addMP3TextFrame(tag, "TSRC", metadata.ISRC) - } - if metadata.UPC != "" { - tag.AddUserDefinedTextFrame(id3v2.UserDefinedTextFrame{ - Encoding: id3v2.EncodingUTF8, - Description: "UPC", - Value: metadata.UPC, - }) - } - - if comment := resolveMetadataComment(metadata); comment != "" { - tag.DeleteFrames(tag.CommonID("Comments")) - tag.AddCommentFrame(id3v2.CommentFrame{ - Encoding: id3v2.EncodingUTF8, - Language: "eng", - Description: "", - Text: comment, - }) - } - - if coverPath != "" && fileExists(coverPath) { - - tag.DeleteFrames(tag.CommonID("Attached picture")) - - artwork, err := os.ReadFile(coverPath) - if err == nil { - pic := id3v2.PictureFrame{ - Encoding: id3v2.EncodingUTF8, - MimeType: "image/jpeg", - PictureType: id3v2.PTFrontCover, - Description: "Cover", - Picture: artwork, - } - tag.AddAttachedPicture(pic) - } else { - fmt.Printf("[EmbedMetadataToMP3] Warning: Failed to read cover art file: %v\n", err) - } - } - - genreText := joinMultiValueText(SplitMetadataValues(metadata.Genre, separator), separator, true) - if genreText == "" { - genreText = strings.TrimSpace(metadata.Genre) - } - addMP3TextFrame(tag, "TCON", genreText) - - if err := tag.Save(); err != nil { - return fmt.Errorf("failed to save MP3 tags: %w", err) - } - - return nil -} - -func embedMetadataToM4A(filePath string, metadata Metadata, coverPath string) error { - ffmpegPath, err := GetFFmpegPath() - if err != nil { - return fmt.Errorf("ffmpeg not found: %w", err) - } - - if err := ValidateExecutable(ffmpegPath); err != nil { - return fmt.Errorf("invalid ffmpeg executable: %w", err) - } - - args := []string{ - "-i", filePath, - "-y", - } - separator := resolveMetadataSeparator(metadata.Separator) - - if coverPath != "" && fileExists(coverPath) { - args = append(args, "-i", coverPath) - args = append(args, "-map", "0:a", "-map", "1", "-c:a", "copy", "-c:v", "copy", "-disposition:v:0", "attached_pic") - } else { - args = append(args, "-map", "0", "-codec", "copy") - } - - if metadata.Title != "" { - args = append(args, "-metadata", "title="+metadata.Title) - } - artistText := joinMultiValueText(SplitArtistCredits(metadata.Artist, separator), separator, false) - if artistText == "" { - artistText = strings.TrimSpace(metadata.Artist) - } - if artistText != "" { - args = append(args, "-metadata", "artist="+artistText) - } - if metadata.Album != "" { - args = append(args, "-metadata", "album="+metadata.Album) - } - albumArtistText := joinMultiValueText(SplitArtistCredits(metadata.AlbumArtist, separator), separator, false) - if albumArtistText == "" { - albumArtistText = strings.TrimSpace(metadata.AlbumArtist) - } - if albumArtistText != "" { - args = append(args, "-metadata", "album_artist="+albumArtistText) - } - if metadata.Date != "" { - args = append(args, "-metadata", "date="+metadata.Date) - } - if metadata.TrackNumber > 0 { - trackStr := strconv.Itoa(metadata.TrackNumber) - if metadata.TotalTracks > 0 { - trackStr = fmt.Sprintf("%d/%d", metadata.TrackNumber, metadata.TotalTracks) - } - args = append(args, "-metadata", "track="+trackStr) - } - if metadata.DiscNumber > 0 { - discStr := strconv.Itoa(metadata.DiscNumber) - if metadata.TotalDiscs > 0 { - discStr = fmt.Sprintf("%d/%d", metadata.DiscNumber, metadata.TotalDiscs) - } - args = append(args, "-metadata", "disk="+discStr) - } - if metadata.Copyright != "" { - args = append(args, "-metadata", "copyright="+metadata.Copyright) - } - if metadata.Publisher != "" { - args = append(args, "-metadata", "publisher="+metadata.Publisher) - } - composerText := joinMultiValueText(SplitArtistCredits(metadata.Composer, separator), separator, false) - if composerText == "" { - composerText = strings.TrimSpace(metadata.Composer) - } - if composerText != "" { - args = append(args, "-metadata", "composer="+composerText) - } - if metadata.ISRC != "" { - args = append(args, "-metadata", "isrc="+metadata.ISRC) - } - if metadata.UPC != "" { - args = append(args, "-metadata", "upc="+metadata.UPC) - } - genreText := joinMultiValueText(SplitMetadataValues(metadata.Genre, separator), separator, false) - if genreText == "" { - genreText = strings.TrimSpace(metadata.Genre) - } - if genreText != "" { - args = append(args, "-metadata", "genre="+genreText) - } - if comment := resolveMetadataComment(metadata); comment != "" { - args = append(args, "-metadata", "comment="+comment) - } - - tmpOutputFile := strings.TrimSuffix(filePath, pathfilepath.Ext(filePath)) + ".tmp" + pathfilepath.Ext(filePath) - defer func() { - if _, err := os.Stat(tmpOutputFile); err == nil { - os.Remove(tmpOutputFile) - } - }() - - args = append(args, "-f", "ipod", tmpOutputFile) - - cmd := exec.Command(ffmpegPath, args...) - setHideWindow(cmd) - - output, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("ffmpeg failed to embed metadata: %s - %w", string(output), err) - } - - if err := os.Rename(tmpOutputFile, filePath); err != nil { - return fmt.Errorf("failed to replace original file: %w", err) - } - - return nil -} diff --git a/backend/musicbrainz.go b/backend/musicbrainz.go deleted file mode 100644 index f7fdf21..0000000 --- a/backend/musicbrainz.go +++ /dev/null @@ -1,331 +0,0 @@ -package backend - -import ( - "encoding/json" - "fmt" - "net/http" - "net/url" - "strings" - "sync" - "time" - - "golang.org/x/text/cases" - "golang.org/x/text/language" -) - -var AppVersion = "Unknown" - -const ( - musicBrainzAPIBase = "https://musicbrainz.org/ws/2" - musicBrainzRequestTimeout = 10 * time.Second - musicBrainzRequestRetries = 3 - musicBrainzRequestRetryWait = 3 * time.Second - musicBrainzMinRequestInterval = 1100 * time.Millisecond - musicBrainzThrottleCooldownOn503 = 5 * time.Second - musicBrainzStatusCheckSkipWindow = 5 * time.Minute -) - -type musicBrainzStatusError struct { - StatusCode int -} - -func (e *musicBrainzStatusError) Error() string { - return fmt.Sprintf("MusicBrainz API returned status: %d", e.StatusCode) -} - -type musicBrainzInflightCall struct { - done chan struct{} - result Metadata - err error -} - -var ( - musicBrainzCache sync.Map - musicBrainzInflightMu sync.Mutex - musicBrainzInflight = make(map[string]*musicBrainzInflightCall) - - musicBrainzThrottleMu sync.Mutex - musicBrainzNextRequest time.Time - musicBrainzBlockedTill time.Time - - musicBrainzStatusMu sync.RWMutex - musicBrainzLastCheckedAt time.Time - musicBrainzLastCheckedOnline bool -) - -func SetMusicBrainzStatusCheckResult(online bool) { - musicBrainzStatusMu.Lock() - defer musicBrainzStatusMu.Unlock() - - musicBrainzLastCheckedAt = time.Now() - musicBrainzLastCheckedOnline = online -} - -func ShouldSkipMusicBrainzMetadataFetch() bool { - musicBrainzStatusMu.RLock() - defer musicBrainzStatusMu.RUnlock() - - if musicBrainzLastCheckedAt.IsZero() { - return false - } - - if musicBrainzLastCheckedOnline { - return false - } - - return time.Since(musicBrainzLastCheckedAt) <= musicBrainzStatusCheckSkipWindow -} - -type MusicBrainzRecordingResponse struct { - Recordings []struct { - ID string `json:"id"` - Title string `json:"title"` - Length int `json:"length"` - Releases []struct { - ID string `json:"id"` - Title string `json:"title"` - Status string `json:"status"` - ReleaseGroup struct { - ID string `json:"id"` - Title string `json:"title"` - PrimaryType string `json:"primary-type"` - } `json:"release-group"` - Date string `json:"date"` - Country string `json:"country"` - Media []struct { - Format string `json:"format"` - } `json:"media"` - LabelInfo []struct { - Label struct { - Name string `json:"name"` - } `json:"label"` - } `json:"label-info"` - } `json:"releases"` - ArtistCredit []struct { - Artist struct { - ID string `json:"id"` - Name string `json:"name"` - } `json:"artist"` - } `json:"artist-credit"` - Tags []struct { - Count int `json:"count"` - Name string `json:"name"` - } `json:"tags"` - } `json:"recordings"` -} - -func musicBrainzCacheKey(isrc string, useSingleGenre bool) string { - separator := strings.TrimSpace(GetSeparator()) - if separator == "" { - separator = ";" - } - - return strings.ToUpper(strings.TrimSpace(isrc)) + "|" + fmt.Sprintf("%t", useSingleGenre) + "|" + separator -} - -func waitForMusicBrainzRequestSlot() { - musicBrainzThrottleMu.Lock() - - readyAt := musicBrainzNextRequest - if musicBrainzBlockedTill.After(readyAt) { - readyAt = musicBrainzBlockedTill - } - - now := time.Now() - if readyAt.Before(now) { - readyAt = now - } - - musicBrainzNextRequest = readyAt.Add(musicBrainzMinRequestInterval) - waitDuration := time.Until(readyAt) - - musicBrainzThrottleMu.Unlock() - - if waitDuration > 0 { - time.Sleep(waitDuration) - } -} - -func noteMusicBrainzThrottle() { - musicBrainzThrottleMu.Lock() - defer musicBrainzThrottleMu.Unlock() - - cooldownUntil := time.Now().Add(musicBrainzThrottleCooldownOn503) - if cooldownUntil.After(musicBrainzBlockedTill) { - musicBrainzBlockedTill = cooldownUntil - } - if musicBrainzNextRequest.Before(musicBrainzBlockedTill) { - musicBrainzNextRequest = musicBrainzBlockedTill - } -} - -func shouldRetryMusicBrainzRequest(err error) bool { - if err == nil { - return false - } - - statusErr, ok := err.(*musicBrainzStatusError) - if !ok { - return true - } - - return statusErr.StatusCode == http.StatusServiceUnavailable || statusErr.StatusCode >= http.StatusInternalServerError -} - -func queryMusicBrainzRecordings(client *http.Client, query string) (*MusicBrainzRecordingResponse, error) { - reqURL := fmt.Sprintf("%s/recording?query=%s&fmt=json&inc=releases+artist-credits+tags+media+release-groups+labels", musicBrainzAPIBase, url.QueryEscape(query)) - - req, err := http.NewRequest(http.MethodGet, reqURL, nil) - if err != nil { - return nil, err - } - - req.Header.Set("User-Agent", fmt.Sprintf("SpotiFLAC/%s ( support@spotbye.qzz.io )", AppVersion)) - req.Header.Set("Accept", "application/json") - - var lastErr error - for attempt := 0; attempt < musicBrainzRequestRetries; attempt++ { - waitForMusicBrainzRequestSlot() - - resp, err := client.Do(req) - if err == nil && resp != nil && resp.StatusCode == http.StatusOK { - defer resp.Body.Close() - - var mbResp MusicBrainzRecordingResponse - if decodeErr := json.NewDecoder(resp.Body).Decode(&mbResp); decodeErr != nil { - return nil, decodeErr - } - - return &mbResp, nil - } - - if err != nil { - lastErr = err - } else if resp == nil { - lastErr = fmt.Errorf("empty response from MusicBrainz") - } else { - if resp.StatusCode == http.StatusServiceUnavailable { - noteMusicBrainzThrottle() - } - lastErr = &musicBrainzStatusError{StatusCode: resp.StatusCode} - resp.Body.Close() - } - - if attempt < musicBrainzRequestRetries-1 && shouldRetryMusicBrainzRequest(lastErr) { - time.Sleep(musicBrainzRequestRetryWait) - continue - } - - break - } - - if lastErr == nil { - lastErr = fmt.Errorf("empty response from MusicBrainz") - } - - return nil, lastErr -} - -func FetchMusicBrainzMetadata(isrc, title, artist, album string, useSingleGenre bool, embedGenre bool) (Metadata, error) { - var meta Metadata - var resultErr error - - if !embedGenre { - return meta, nil - } - - if isrc == "" { - resultErr = fmt.Errorf("no ISRC provided") - return meta, resultErr - } - - cacheKey := musicBrainzCacheKey(isrc, useSingleGenre) - if cached, ok := musicBrainzCache.Load(cacheKey); ok { - return cached.(Metadata), nil - } - - if ShouldSkipMusicBrainzMetadataFetch() { - resultErr = fmt.Errorf("skipping MusicBrainz lookup because the latest status check reported offline") - return meta, resultErr - } - - musicBrainzInflightMu.Lock() - if call, ok := musicBrainzInflight[cacheKey]; ok { - musicBrainzInflightMu.Unlock() - <-call.done - return call.result, call.err - } - - call := &musicBrainzInflightCall{done: make(chan struct{})} - musicBrainzInflight[cacheKey] = call - musicBrainzInflightMu.Unlock() - - defer func() { - call.result = meta - call.err = resultErr - - musicBrainzInflightMu.Lock() - delete(musicBrainzInflight, cacheKey) - close(call.done) - musicBrainzInflightMu.Unlock() - }() - - client := &http.Client{ - Timeout: musicBrainzRequestTimeout, - } - - query := fmt.Sprintf("isrc:%s", isrc) - mbResp, err := queryMusicBrainzRecordings(client, query) - if err != nil { - resultErr = err - return meta, resultErr - } - - if len(mbResp.Recordings) == 0 { - resultErr = fmt.Errorf("no recordings found for ISRC: %s", isrc) - return meta, resultErr - } - - recording := mbResp.Recordings[0] - - var genres []string - caser := cases.Title(language.English) - - if useSingleGenre { - - maxCount := -1 - var bestTag string - - for _, tag := range recording.Tags { - if tag.Count > maxCount { - maxCount = tag.Count - bestTag = tag.Name - } - } - - if bestTag != "" { - meta.Genre = caser.String(bestTag) - } - } else { - for _, tag := range recording.Tags { - - genres = append(genres, caser.String(tag.Name)) - } - if len(genres) > 0 { - - if len(genres) > 5 { - genres = genres[:5] - } - meta.Genre = strings.Join(genres, GetSeparator()) - } - } - - if meta.Genre == "" { - resultErr = fmt.Errorf("no genre tags found in MusicBrainz") - return meta, resultErr - } - - musicBrainzCache.Store(cacheKey, meta) - - return meta, nil -} diff --git a/backend/progress.go b/backend/progress.go deleted file mode 100644 index 0a43155..0000000 --- a/backend/progress.go +++ /dev/null @@ -1,419 +0,0 @@ -package backend - -import ( - "fmt" - "io" - "sync" - "time" -) - -type DownloadStatus string - -const ( - StatusQueued DownloadStatus = "queued" - StatusDownloading DownloadStatus = "downloading" - StatusCompleted DownloadStatus = "completed" - StatusFailed DownloadStatus = "failed" - StatusSkipped DownloadStatus = "skipped" -) - -type DownloadItem struct { - ID string `json:"id"` - TrackName string `json:"track_name"` - ArtistName string `json:"artist_name"` - AlbumName string `json:"album_name"` - SpotifyID string `json:"spotify_id"` - Status DownloadStatus `json:"status"` - Progress float64 `json:"progress"` - TotalSize float64 `json:"total_size"` - Speed float64 `json:"speed"` - StartTime int64 `json:"start_time"` - EndTime int64 `json:"end_time"` - ErrorMessage string `json:"error_message"` - FilePath string `json:"file_path"` -} - -var ( - currentProgress float64 - currentProgressLock sync.RWMutex - isDownloading bool - downloadingLock sync.RWMutex - currentSpeed float64 - speedLock sync.RWMutex - - downloadQueue []DownloadItem - downloadQueueLock sync.RWMutex - currentItemID string - currentItemLock sync.RWMutex - totalDownloaded float64 - totalDownloadedLock sync.RWMutex - sessionStartTime int64 - sessionStartLock sync.RWMutex -) - -type ProgressInfo struct { - IsDownloading bool `json:"is_downloading"` - MBDownloaded float64 `json:"mb_downloaded"` - SpeedMBps float64 `json:"speed_mbps"` -} - -type DownloadQueueInfo struct { - IsDownloading bool `json:"is_downloading"` - Queue []DownloadItem `json:"queue"` - CurrentSpeed float64 `json:"current_speed"` - TotalDownloaded float64 `json:"total_downloaded"` - SessionStartTime int64 `json:"session_start_time"` - QueuedCount int `json:"queued_count"` - CompletedCount int `json:"completed_count"` - FailedCount int `json:"failed_count"` - SkippedCount int `json:"skipped_count"` -} - -func GetDownloadProgress() ProgressInfo { - downloadingLock.RLock() - downloading := isDownloading - downloadingLock.RUnlock() - - currentProgressLock.RLock() - progress := currentProgress - currentProgressLock.RUnlock() - - speedLock.RLock() - speed := currentSpeed - speedLock.RUnlock() - - return ProgressInfo{ - IsDownloading: downloading, - MBDownloaded: progress, - SpeedMBps: speed, - } -} - -func SetDownloadSpeed(mbps float64) { - speedLock.Lock() - currentSpeed = mbps - speedLock.Unlock() -} - -func SetDownloadProgress(mbDownloaded float64) { - currentProgressLock.Lock() - currentProgress = mbDownloaded - currentProgressLock.Unlock() -} - -func SetDownloading(downloading bool) { - downloadingLock.Lock() - isDownloading = downloading - downloadingLock.Unlock() - - if !downloading { - - SetDownloadProgress(0) - SetDownloadSpeed(0) - } -} - -type ProgressWriter struct { - writer io.Writer - total int64 - lastPrinted int64 - startTime int64 - lastTime int64 - lastBytes int64 - itemID string -} - -func NewProgressWriter(writer io.Writer) *ProgressWriter { - now := getCurrentTimeMillis() - return &ProgressWriter{ - writer: writer, - total: 0, - lastPrinted: 0, - startTime: now, - lastTime: now, - lastBytes: 0, - itemID: "", - } -} - -func NewProgressWriterWithID(writer io.Writer, itemID string) *ProgressWriter { - pw := NewProgressWriter(writer) - pw.itemID = itemID - return pw -} - -func getCurrentTimeMillis() int64 { - return time.Now().UnixMilli() -} - -func (pw *ProgressWriter) Write(p []byte) (int, error) { - n, err := pw.writer.Write(p) - pw.total += int64(n) - - if pw.total-pw.lastPrinted >= 256*1024 { - mbDownloaded := float64(pw.total) / (1024 * 1024) - - now := getCurrentTimeMillis() - timeDiff := float64(now-pw.lastTime) / 1000.0 - bytesDiff := float64(pw.total - pw.lastBytes) - - var speedMBps float64 - if timeDiff > 0 { - speedMBps = (bytesDiff / (1024 * 1024)) / timeDiff - SetDownloadSpeed(speedMBps) - fmt.Printf("\rDownloaded: %.2f MB (%.2f MB/s)", mbDownloaded, speedMBps) - } else { - fmt.Printf("\rDownloaded: %.2f MB", mbDownloaded) - } - - SetDownloadProgress(mbDownloaded) - - if pw.itemID != "" { - UpdateItemProgress(pw.itemID, mbDownloaded, speedMBps) - } - - pw.lastPrinted = pw.total - pw.lastTime = now - pw.lastBytes = pw.total - } - - return n, err -} - -func (pw *ProgressWriter) GetTotal() int64 { - return pw.total -} - -func AddToQueue(id, trackName, artistName, albumName, spotifyID string) { - downloadQueueLock.Lock() - defer downloadQueueLock.Unlock() - - item := DownloadItem{ - ID: id, - TrackName: trackName, - ArtistName: artistName, - AlbumName: albumName, - SpotifyID: spotifyID, - Status: StatusQueued, - Progress: 0, - TotalSize: 0, - Speed: 0, - StartTime: 0, - EndTime: 0, - } - - downloadQueue = append(downloadQueue, item) - - sessionStartLock.Lock() - if sessionStartTime == 0 { - sessionStartTime = time.Now().Unix() - } - sessionStartLock.Unlock() -} - -func StartDownloadItem(id string) { - downloadQueueLock.Lock() - defer downloadQueueLock.Unlock() - - for i := range downloadQueue { - if downloadQueue[i].ID == id { - downloadQueue[i].Status = StatusDownloading - downloadQueue[i].StartTime = time.Now().Unix() - downloadQueue[i].Progress = 0 - break - } - } - - currentItemLock.Lock() - currentItemID = id - currentItemLock.Unlock() -} - -func UpdateItemProgress(id string, progress, speed float64) { - downloadQueueLock.Lock() - defer downloadQueueLock.Unlock() - - for i := range downloadQueue { - if downloadQueue[i].ID == id { - downloadQueue[i].Progress = progress - downloadQueue[i].Speed = speed - break - } - } -} - -func GetCurrentItemID() string { - currentItemLock.RLock() - defer currentItemLock.RUnlock() - return currentItemID -} - -func CompleteDownloadItem(id, filePath string, finalSize float64) { - downloadQueueLock.Lock() - defer downloadQueueLock.Unlock() - - for i := range downloadQueue { - if downloadQueue[i].ID == id { - downloadQueue[i].Status = StatusCompleted - downloadQueue[i].EndTime = time.Now().Unix() - downloadQueue[i].FilePath = filePath - downloadQueue[i].Progress = finalSize - downloadQueue[i].TotalSize = finalSize - - totalDownloadedLock.Lock() - totalDownloaded += finalSize - totalDownloadedLock.Unlock() - break - } - } -} - -func FailDownloadItem(id, errorMsg string) { - downloadQueueLock.Lock() - defer downloadQueueLock.Unlock() - - for i := range downloadQueue { - if downloadQueue[i].ID == id { - downloadQueue[i].Status = StatusFailed - downloadQueue[i].EndTime = time.Now().Unix() - downloadQueue[i].ErrorMessage = errorMsg - break - } - } -} - -func SkipDownloadItem(id, filePath string) { - downloadQueueLock.Lock() - defer downloadQueueLock.Unlock() - - for i := range downloadQueue { - if downloadQueue[i].ID == id { - downloadQueue[i].Status = StatusSkipped - downloadQueue[i].EndTime = time.Now().Unix() - downloadQueue[i].FilePath = filePath - break - } - } -} - -func GetDownloadQueue() DownloadQueueInfo { - - ResetSessionIfComplete() - - downloadQueueLock.RLock() - defer downloadQueueLock.RUnlock() - - downloadingLock.RLock() - downloading := isDownloading - downloadingLock.RUnlock() - - speedLock.RLock() - speed := currentSpeed - speedLock.RUnlock() - - totalDownloadedLock.RLock() - total := totalDownloaded - totalDownloadedLock.RUnlock() - - sessionStartLock.RLock() - sessionStart := sessionStartTime - sessionStartLock.RUnlock() - - var queued, completed, failed, skipped int - for _, item := range downloadQueue { - switch item.Status { - case StatusQueued: - queued++ - case StatusCompleted: - completed++ - case StatusFailed: - failed++ - case StatusSkipped: - skipped++ - } - } - - queueCopy := make([]DownloadItem, len(downloadQueue)) - copy(queueCopy, downloadQueue) - - return DownloadQueueInfo{ - IsDownloading: downloading, - Queue: queueCopy, - CurrentSpeed: speed, - TotalDownloaded: total, - SessionStartTime: sessionStart, - QueuedCount: queued, - CompletedCount: completed, - FailedCount: failed, - SkippedCount: skipped, - } -} - -func ClearDownloadQueue() { - downloadQueueLock.Lock() - defer downloadQueueLock.Unlock() - - newQueue := make([]DownloadItem, 0) - for _, item := range downloadQueue { - if item.Status == StatusQueued || item.Status == StatusDownloading { - newQueue = append(newQueue, item) - } - } - downloadQueue = newQueue -} - -func ClearAllDownloads() { - downloadQueueLock.Lock() - downloadQueue = []DownloadItem{} - downloadQueueLock.Unlock() - - totalDownloadedLock.Lock() - totalDownloaded = 0 - totalDownloadedLock.Unlock() - - sessionStartLock.Lock() - sessionStartTime = 0 - sessionStartLock.Unlock() - - currentItemLock.Lock() - currentItemID = "" - currentItemLock.Unlock() - - SetDownloadProgress(0) - SetDownloadSpeed(0) -} - -func CancelAllQueuedItems() { - downloadQueueLock.Lock() - defer downloadQueueLock.Unlock() - - for i := range downloadQueue { - if downloadQueue[i].Status == StatusQueued { - downloadQueue[i].Status = StatusSkipped - downloadQueue[i].EndTime = time.Now().Unix() - downloadQueue[i].ErrorMessage = "Cancelled" - } - } -} - -func ResetSessionIfComplete() { - downloadQueueLock.RLock() - hasActiveOrQueued := false - for _, item := range downloadQueue { - if item.Status == StatusQueued || item.Status == StatusDownloading { - hasActiveOrQueued = true - break - } - } - downloadQueueLock.RUnlock() - - if !hasActiveOrQueued { - sessionStartLock.Lock() - sessionStartTime = 0 - sessionStartLock.Unlock() - - totalDownloadedLock.Lock() - totalDownloaded = 0 - totalDownloadedLock.Unlock() - } -} diff --git a/backend/provider_endpoints.go b/backend/provider_endpoints.go deleted file mode 100644 index 9c9ae9b..0000000 --- a/backend/provider_endpoints.go +++ /dev/null @@ -1,88 +0,0 @@ -package backend - -import ( - "net/url" - "strings" -) - -const amazonMusicAPIBaseURL = "https://amazon.spotbye.qzz.io" - -const ( - qobuzWJHEBaseURL = "https://music.wjhe.top" - qobuzWJHESearchAPIURL = qobuzWJHEBaseURL + "/api/music/qobuz/search" - qobuzWJHEStreamAPIURL = qobuzWJHEBaseURL + "/api/music/qobuz/url" - qobuzMusicDLDownloadAPIURL = "https://www.musicdl.me/api/qobuz/download" - qobuzGDStudioAPIURLXYZ = "https://music.gdstudio.xyz/api.php" - qobuzGDStudioAPIURLORG = "https://music.gdstudio.org/api.php" - qobuzGDStudioVersion = "2026.5.10" -) - -var defaultQobuzDownloadProviderURLs = []string{ - qobuzWJHEStreamAPIURL, - qobuzGDStudioAPIURLXYZ, - qobuzGDStudioAPIURLORG, - qobuzMusicDLDownloadAPIURL, -} - -func GetQobuzDownloadProviderURLs() []string { - return append([]string(nil), defaultQobuzDownloadProviderURLs...) -} - -func GetQobuzWJHESearchAPIURL() string { - return qobuzWJHESearchAPIURL -} - -func GetQobuzWJHEStreamAPIURL() string { - return qobuzWJHEStreamAPIURL -} - -func GetQobuzMusicDLDownloadAPIURL() string { - return qobuzMusicDLDownloadAPIURL -} - -func GetQobuzGDStudioAPIURLs() []string { - return []string{qobuzGDStudioAPIURLXYZ, qobuzGDStudioAPIURLORG} -} - -func GetQobuzGDStudioPrimaryAPIURL() string { - return qobuzGDStudioAPIURLXYZ -} - -func GetQobuzGDStudioFallbackAPIURL() string { - return qobuzGDStudioAPIURLORG -} - -func GetQobuzGDStudioSignatureHost(apiURL string) string { - parsed, err := url.Parse(strings.TrimSpace(apiURL)) - if err != nil || strings.TrimSpace(parsed.Host) == "" { - return "" - } - return strings.TrimSpace(parsed.Host) -} - -func GetQobuzGDStudioVersion() string { - return qobuzGDStudioVersion -} - -func IsQobuzWJHEProviderURL(raw string) bool { - candidate := strings.TrimSpace(raw) - return candidate == qobuzWJHEStreamAPIURL || strings.HasPrefix(candidate, qobuzWJHEStreamAPIURL+"?") -} - -func IsQobuzMusicDLProviderURL(raw string) bool { - return strings.EqualFold(strings.TrimSpace(raw), qobuzMusicDLDownloadAPIURL) -} - -func IsQobuzGDStudioProviderURL(raw string) bool { - candidate := strings.TrimSpace(raw) - for _, apiURL := range GetQobuzGDStudioAPIURLs() { - if candidate == apiURL || strings.HasPrefix(candidate, apiURL+"?") { - return true - } - } - return false -} - -func GetAmazonMusicAPIBaseURL() string { - return amazonMusicAPIBaseURL -} diff --git a/backend/provider_priority.go b/backend/provider_priority.go deleted file mode 100644 index 68377ef..0000000 --- a/backend/provider_priority.go +++ /dev/null @@ -1,215 +0,0 @@ -package backend - -import ( - "encoding/json" - "fmt" - "path/filepath" - "sort" - "strings" - "sync" - "time" - - bolt "go.etcd.io/bbolt" -) - -const ( - providerPriorityDBFile = "provider_priority.db" - providerPriorityBucket = "ProviderPriority" -) - -type providerPriorityEntry struct { - Service string `json:"service"` - Provider string `json:"provider"` - LastOutcome string `json:"last_outcome"` - LastAttempt int64 `json:"last_attempt"` - LastSuccess int64 `json:"last_success"` - LastFailure int64 `json:"last_failure"` - SuccessCount int64 `json:"success_count"` - FailureCount int64 `json:"failure_count"` -} - -var ( - providerPriorityDB *bolt.DB - providerPriorityDBMu sync.Mutex -) - -func InitProviderPriorityDB() error { - providerPriorityDBMu.Lock() - defer providerPriorityDBMu.Unlock() - - if providerPriorityDB != nil { - return nil - } - - appDir, err := EnsureAppDir() - if err != nil { - return err - } - - dbPath := filepath.Join(appDir, providerPriorityDBFile) - db, err := bolt.Open(dbPath, 0o600, &bolt.Options{Timeout: 1 * time.Second}) - if err != nil { - return err - } - - if err := db.Update(func(tx *bolt.Tx) error { - _, err := tx.CreateBucketIfNotExists([]byte(providerPriorityBucket)) - return err - }); err != nil { - db.Close() - return err - } - - providerPriorityDB = db - return nil -} - -func CloseProviderPriorityDB() { - providerPriorityDBMu.Lock() - defer providerPriorityDBMu.Unlock() - - if providerPriorityDB != nil { - _ = providerPriorityDB.Close() - providerPriorityDB = nil - } -} - -func prioritizeProviders(service string, providers []string) []string { - ordered := append([]string(nil), providers...) - if len(ordered) < 2 { - return ordered - } - - if err := InitProviderPriorityDB(); err != nil { - fmt.Printf("Warning: failed to init provider priority DB: %v\n", err) - return ordered - } - - serviceKey := strings.TrimSpace(strings.ToLower(service)) - entries := make(map[string]providerPriorityEntry, len(ordered)) - - if err := providerPriorityDB.View(func(tx *bolt.Tx) error { - bucket := tx.Bucket([]byte(providerPriorityBucket)) - if bucket == nil { - return nil - } - - for _, provider := range ordered { - if raw := bucket.Get([]byte(providerPriorityKey(serviceKey, provider))); len(raw) > 0 { - var entry providerPriorityEntry - if err := json.Unmarshal(raw, &entry); err != nil { - return err - } - entries[provider] = entry - } - } - return nil - }); err != nil { - fmt.Printf("Warning: failed to read provider priority DB: %v\n", err) - return ordered - } - - originalIndex := make(map[string]int, len(ordered)) - for idx, provider := range ordered { - originalIndex[provider] = idx - } - - sort.SliceStable(ordered, func(i, j int) bool { - left := entries[ordered[i]] - right := entries[ordered[j]] - - leftRank := providerOutcomeRank(left.LastOutcome) - rightRank := providerOutcomeRank(right.LastOutcome) - if leftRank != rightRank { - return leftRank > rightRank - } - - if left.LastSuccess != right.LastSuccess { - return left.LastSuccess > right.LastSuccess - } - - if left.LastAttempt != right.LastAttempt { - return left.LastAttempt > right.LastAttempt - } - - return originalIndex[ordered[i]] < originalIndex[ordered[j]] - }) - - return ordered -} - -func recordProviderSuccess(service string, provider string) { - recordProviderOutcome(service, provider, true) -} - -func recordProviderFailure(service string, provider string) { - recordProviderOutcome(service, provider, false) -} - -func recordProviderOutcome(service string, provider string, success bool) { - if strings.TrimSpace(service) == "" || strings.TrimSpace(provider) == "" { - return - } - - if err := InitProviderPriorityDB(); err != nil { - fmt.Printf("Warning: failed to init provider priority DB: %v\n", err) - return - } - - serviceKey := strings.TrimSpace(strings.ToLower(service)) - providerKey := providerPriorityKey(serviceKey, provider) - now := time.Now().Unix() - - if err := providerPriorityDB.Update(func(tx *bolt.Tx) error { - bucket, err := tx.CreateBucketIfNotExists([]byte(providerPriorityBucket)) - if err != nil { - return err - } - - entry := providerPriorityEntry{ - Service: serviceKey, - Provider: provider, - } - - if raw := bucket.Get([]byte(providerKey)); len(raw) > 0 { - if err := json.Unmarshal(raw, &entry); err != nil { - return err - } - } - - entry.LastAttempt = now - if success { - entry.LastOutcome = "success" - entry.LastSuccess = now - entry.SuccessCount++ - } else { - entry.LastOutcome = "failure" - entry.LastFailure = now - entry.FailureCount++ - } - - payload, err := json.Marshal(entry) - if err != nil { - return err - } - - return bucket.Put([]byte(providerKey), payload) - }); err != nil { - fmt.Printf("Warning: failed to update provider priority DB: %v\n", err) - } -} - -func providerOutcomeRank(outcome string) int { - switch strings.TrimSpace(strings.ToLower(outcome)) { - case "success": - return 2 - case "": - return 1 - default: - return 0 - } -} - -func providerPriorityKey(service string, provider string) string { - return strings.TrimSpace(strings.ToLower(service)) + "|" + strings.TrimSpace(provider) -} diff --git a/backend/qobuz.go b/backend/qobuz.go deleted file mode 100644 index 0a6dea5..0000000 --- a/backend/qobuz.go +++ /dev/null @@ -1,1127 +0,0 @@ -package backend - -import ( - "bytes" - "crypto/aes" - "crypto/cipher" - "crypto/md5" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "os" - "path/filepath" - "regexp" - "strconv" - "strings" - "sync" - "time" -) - -type QobuzDownloader struct { - client *http.Client -} - -type QobuzTrack struct { - ID int64 `json:"id"` - Title string `json:"title"` - Version string `json:"version"` - Duration int `json:"duration"` - TrackNumber int `json:"track_number"` - MediaNumber int `json:"media_number"` - ISRC string `json:"isrc"` - Copyright string `json:"copyright"` - MaximumBitDepth int `json:"maximum_bit_depth"` - MaximumSamplingRate float64 `json:"maximum_sampling_rate"` - Hires bool `json:"hires"` - HiresStreamable bool `json:"hires_streamable"` - ReleaseDateOriginal string `json:"release_date_original"` - Performer struct { - Name string `json:"name"` - ID int64 `json:"id"` - } `json:"performer"` - Album struct { - Title string `json:"title"` - ID string `json:"id"` - Image struct { - Small string `json:"small"` - Thumbnail string `json:"thumbnail"` - Large string `json:"large"` - } `json:"image"` - Artist struct { - Name string `json:"name"` - ID int64 `json:"id"` - } `json:"artist"` - Label struct { - Name string `json:"name"` - } `json:"label"` - } `json:"album"` -} - -type qobuzMusicDLRequest struct { - URL string `json:"url"` - Quality string `json:"quality"` -} - -type qobuzMusicDLResponse struct { - Success bool `json:"success"` - Type string `json:"type"` - URLType string `json:"url_type"` - TrackID string `json:"track_id"` - Quality string `json:"quality_label"` - DownloadURL string `json:"download_url"` - Message string `json:"message"` - Error string `json:"error"` -} - -type qobuzPublicSearchResponse struct { - Tracks struct { - Total int `json:"total"` - Items []QobuzTrack `json:"items"` - } `json:"tracks"` -} - -const qobuzProbeTrackID int64 = 341032040 - -var ( - qobuzMusicDLDebugKeyOnce sync.Once - qobuzMusicDLDebugKey string - qobuzMusicDLDebugKeyErr error - qobuzStreamingURLPattern = regexp.MustCompile(`https?://[^\s"'<>\\)]+`) -) - -var qobuzMusicDLDebugKeySeedParts = [][]byte{ - {0x73, 0x70, 0x6f, 0x74, 0x69, 0x66}, - {0x6c, 0x61, 0x63, 0x3a, 0x71, 0x6f}, - {0x62, 0x75, 0x7a, 0x3a, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x64, 0x6c, 0x3a, 0x76, 0x31}, -} - -var qobuzMusicDLDebugKeyAAD = []byte{ - 0x71, 0x6f, 0x62, 0x75, 0x7a, 0x7c, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x64, - 0x6c, 0x7c, 0x64, 0x65, 0x62, 0x75, 0x67, 0x7c, 0x76, 0x31, -} - -var qobuzMusicDLDebugKeyNonce = []byte{ - 0x91, 0x2a, 0x5c, 0x77, 0x0f, 0x33, 0xa8, 0x14, 0x62, 0x9d, 0xce, 0x41, -} - -var qobuzMusicDLDebugKeyCiphertext = []byte{ - 0xf3, 0x4a, 0x83, 0x45, 0x24, 0xb6, 0x22, 0xaf, 0xd6, 0xc3, 0x6e, 0x2d, - 0x56, 0xd1, 0xbb, 0x0b, 0xe9, 0x1b, 0x4f, 0x1c, 0x5f, 0x41, 0x55, 0xc2, - 0xc6, 0xdf, 0xad, 0x21, 0x58, 0xfe, 0xd5, 0xb8, 0x2d, 0x29, 0xf9, 0x9e, - 0x6f, 0xd6, -} - -var qobuzMusicDLDebugKeyTag = []byte{ - 0x69, 0x0c, 0x42, 0x70, 0x14, 0x83, 0xff, 0x14, 0xc8, 0xbe, 0x17, 0x00, - 0x69, 0xb1, 0xfe, 0xbb, -} - -func NewQobuzDownloader() *QobuzDownloader { - return &QobuzDownloader{ - client: &http.Client{ - Timeout: 60 * time.Second, - }, - } -} - -func previewQobuzResponseBody(body []byte, maxLen int) string { - preview := strings.TrimSpace(string(body)) - if len(preview) > maxLen { - return preview[:maxLen] + "..." - } - return preview -} - -func buildQobuzOpenTrackURL(trackID int64) string { - return fmt.Sprintf("https://open.qobuz.com/track/%d", trackID) -} - -func getQobuzMusicDLDebugKey() (string, error) { - qobuzMusicDLDebugKeyOnce.Do(func() { - hasher := sha256.New() - for _, part := range qobuzMusicDLDebugKeySeedParts { - hasher.Write(part) - } - - block, err := aes.NewCipher(hasher.Sum(nil)) - if err != nil { - qobuzMusicDLDebugKeyErr = err - return - } - - gcm, err := cipher.NewGCM(block) - if err != nil { - qobuzMusicDLDebugKeyErr = err - return - } - - sealed := make([]byte, 0, len(qobuzMusicDLDebugKeyCiphertext)+len(qobuzMusicDLDebugKeyTag)) - sealed = append(sealed, qobuzMusicDLDebugKeyCiphertext...) - sealed = append(sealed, qobuzMusicDLDebugKeyTag...) - - plaintext, err := gcm.Open(nil, qobuzMusicDLDebugKeyNonce, sealed, qobuzMusicDLDebugKeyAAD) - if err != nil { - qobuzMusicDLDebugKeyErr = err - return - } - - qobuzMusicDLDebugKey = string(plaintext) - }) - - if qobuzMusicDLDebugKeyErr != nil { - return "", qobuzMusicDLDebugKeyErr - } - - return qobuzMusicDLDebugKey, nil -} - -func firstNonEmptyQobuzValue(values ...string) string { - for _, value := range values { - trimmed := strings.TrimSpace(value) - if trimmed != "" { - return trimmed - } - } - return "" -} - -func normalizeQobuzSearchValue(value string) string { - replacer := strings.NewReplacer( - "&", " and ", - "feat.", " ", - "ft.", " ", - "/", " ", - "-", " ", - "_", " ", - ) - normalized := strings.ToLower(strings.TrimSpace(value)) - normalized = replacer.Replace(normalized) - return strings.Join(strings.Fields(normalized), " ") -} - -func qobuzTrackDisplayArtist(track QobuzTrack) string { - return firstNonEmptyQobuzValue(track.Performer.Name, track.Album.Artist.Name) -} - -func qobuzTrackSupportsHiRes(track QobuzTrack) bool { - if track.Hires || track.HiresStreamable { - return true - } - return track.MaximumBitDepth >= 24 || track.MaximumSamplingRate > 48 -} - -func scoreQobuzSearchCandidate(track QobuzTrack, spotifyTrackName string, spotifyArtistName string, spotifyAlbumName string) int { - score := 0 - - titleNeedle := normalizeQobuzSearchValue(spotifyTrackName) - titleHaystack := normalizeQobuzSearchValue(track.Title) - switch { - case titleNeedle != "" && titleHaystack == titleNeedle: - score += 1000 - case titleNeedle != "" && (strings.Contains(titleHaystack, titleNeedle) || strings.Contains(titleNeedle, titleHaystack)): - score += 500 - } - - artistNeedle := normalizeQobuzSearchValue(spotifyArtistName) - artistHaystack := normalizeQobuzSearchValue(qobuzTrackDisplayArtist(track)) - switch { - case artistNeedle != "" && artistHaystack == artistNeedle: - score += 300 - case artistNeedle != "" && artistHaystack != "" && (strings.Contains(artistHaystack, artistNeedle) || strings.Contains(artistNeedle, artistHaystack)): - score += 180 - } - - albumNeedle := normalizeQobuzSearchValue(spotifyAlbumName) - albumHaystack := normalizeQobuzSearchValue(track.Album.Title) - switch { - case albumNeedle != "" && albumHaystack == albumNeedle: - score += 150 - case albumNeedle != "" && albumHaystack != "" && (strings.Contains(albumHaystack, albumNeedle) || strings.Contains(albumNeedle, albumHaystack)): - score += 90 - } - - if qobuzTrackSupportsHiRes(track) { - score += 40 - } else if track.MaximumBitDepth >= 16 { - score += 20 - } - - return score -} - -func mapQobuzWJHEQuality(quality string) (int, string) { - switch strings.TrimSpace(quality) { - case "27", "7": - return 2000, "flac" - case "", "6": - return 1000, "flac" - default: - return 320, "mp3" - } -} - -func buildQobuzWJHEDownloadURL(trackID int64, quality string) string { - wjheQuality, wjheFormat := mapQobuzWJHEQuality(quality) - params := url.Values{ - "ID": {strconv.FormatInt(trackID, 10)}, - "quality": {strconv.Itoa(wjheQuality)}, - "format": {wjheFormat}, - } - return GetQobuzWJHEStreamAPIURL() + "?" + params.Encode() -} - -func qobuzURLLooksStreamable(raw string) bool { - candidate := strings.TrimSpace(raw) - if candidate == "" { - return false - } - - parsed, err := url.Parse(candidate) - if err != nil { - return false - } - - return (parsed.Scheme == "http" || parsed.Scheme == "https") && parsed.Host != "" -} - -func findQobuzStreamingURLInPayload(payload interface{}) string { - switch value := payload.(type) { - case string: - candidate := strings.ReplaceAll(strings.TrimSpace(value), `\/`, `/`) - if qobuzURLLooksStreamable(candidate) { - return candidate - } - case []interface{}: - for _, item := range value { - if url := findQobuzStreamingURLInPayload(item); url != "" { - return url - } - } - case map[string]interface{}: - for _, key := range []string{"download_url", "url", "play_url", "stream_url", "link", "file"} { - if nested, ok := value[key]; ok { - if url := findQobuzStreamingURLInPayload(nested); url != "" { - return url - } - } - } - for _, nested := range value { - if url := findQobuzStreamingURLInPayload(nested); url != "" { - return url - } - } - } - - return "" -} - -func extractQobuzStreamingURL(body []byte) string { - trimmed := strings.TrimSpace(string(body)) - if trimmed == "" { - return "" - } - - var directResp struct { - URL string `json:"url"` - DownloadURL string `json:"download_url"` - Data struct { - URL string `json:"url"` - DownloadURL string `json:"download_url"` - } `json:"data"` - } - if err := json.Unmarshal(body, &directResp); err == nil { - for _, candidate := range []string{ - directResp.DownloadURL, - directResp.URL, - directResp.Data.DownloadURL, - directResp.Data.URL, - } { - if qobuzURLLooksStreamable(candidate) { - return candidate - } - } - } - - var genericPayload interface{} - if err := json.Unmarshal(body, &genericPayload); err == nil { - if streamURL := findQobuzStreamingURLInPayload(genericPayload); streamURL != "" { - return streamURL - } - } - - if openIdx := strings.Index(trimmed, "("); openIdx >= 0 { - if closeIdx := strings.LastIndex(trimmed, ")"); closeIdx > openIdx+1 { - callbackBody := strings.TrimSpace(trimmed[openIdx+1 : closeIdx]) - if streamURL := extractQobuzStreamingURL([]byte(callbackBody)); streamURL != "" { - return streamURL - } - } - } - - for _, match := range qobuzStreamingURLPattern.FindAllString(trimmed, -1) { - candidate := strings.ReplaceAll(match, `\/`, `/`) - if qobuzURLLooksStreamable(candidate) { - return candidate - } - } - - return "" -} - -func newQobuzNoRedirectClient(base *http.Client) *http.Client { - if base == nil { - return &http.Client{ - Timeout: 20 * time.Second, - CheckRedirect: func(req *http.Request, via []*http.Request) error { - return http.ErrUseLastResponse - }, - } - } - - cloned := *base - if cloned.Timeout == 0 { - cloned.Timeout = 20 * time.Second - } - cloned.CheckRedirect = func(req *http.Request, via []*http.Request) error { - return http.ErrUseLastResponse - } - return &cloned -} - -func (q *QobuzDownloader) searchByISRC(isrc string, spotifyTrackName string, spotifyArtistName string, spotifyAlbumName string) (*QobuzTrack, error) { - if strings.HasPrefix(isrc, "qobuz_") { - trackID := strings.TrimSpace(strings.TrimPrefix(isrc, "qobuz_")) - resp, err := doQobuzSignedRequest(http.MethodGet, "track/get", url.Values{"track_id": {trackID}}, q.client) - if err != nil { - return nil, fmt.Errorf("failed to fetch track from Qobuz public API: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - body, _ := io.ReadAll(io.LimitReader(resp.Body, 512)) - return nil, fmt.Errorf("Qobuz public API track/get returned status %d: %s", resp.StatusCode, previewQobuzResponseBody(body, 256)) - } - - var trackResp QobuzTrack - if err := json.NewDecoder(resp.Body).Decode(&trackResp); err != nil { - return nil, fmt.Errorf("failed to decode Qobuz public track/get response: %w", err) - } - - return &trackResp, nil - } - - queries := []string{strings.TrimSpace(isrc)} - if fallbackQuery := strings.TrimSpace(strings.Join([]string{spotifyTrackName, spotifyArtistName}, " ")); fallbackQuery != "" { - queries = append(queries, fallbackQuery) - } - - var lastErr error - for _, query := range queries { - if strings.TrimSpace(query) == "" { - continue - } - - var searchResp qobuzPublicSearchResponse - if err := doQobuzSignedJSONRequest("track/search", url.Values{ - "query": {strings.TrimSpace(query)}, - "limit": {"10"}, - }, &searchResp); err != nil { - lastErr = fmt.Errorf("failed to search Qobuz public API: %w", err) - continue - } - - if searchResp.Tracks.Total == 0 || len(searchResp.Tracks.Items) == 0 { - lastErr = fmt.Errorf("track not found for query: %s", query) - continue - } - - bestIndex := 0 - bestScore := -1 - for idx, candidate := range searchResp.Tracks.Items { - score := scoreQobuzSearchCandidate(candidate, spotifyTrackName, spotifyArtistName, spotifyAlbumName) - if idx == 0 || score > bestScore { - bestIndex = idx - bestScore = score - } - } - - selected := searchResp.Tracks.Items[bestIndex] - return &selected, nil - } - - if lastErr == nil { - lastErr = fmt.Errorf("track not found for ISRC: %s", isrc) - } - return nil, lastErr -} - -func (q *QobuzDownloader) DownloadFromWJHE(trackID int64, quality string) (string, error) { - apiURL := buildQobuzWJHEDownloadURL(trackID, quality) - client := newQobuzNoRedirectClient(q.client) - - req, err := NewRequestWithDefaultHeaders(http.MethodHead, apiURL, nil) - if err != nil { - return "", fmt.Errorf("failed to create WJHE request: %w", err) - } - - resp, err := client.Do(req) - if err != nil { - return "", fmt.Errorf("failed to reach WJHE: %w", err) - } - - if resp.StatusCode == http.StatusMethodNotAllowed || resp.StatusCode == http.StatusNotImplemented { - resp.Body.Close() - req, err = NewRequestWithDefaultHeaders(http.MethodGet, apiURL, nil) - if err != nil { - return "", fmt.Errorf("failed to create WJHE fallback request: %w", err) - } - resp, err = client.Do(req) - if err != nil { - return "", fmt.Errorf("failed to reach WJHE with GET fallback: %w", err) - } - } - defer resp.Body.Close() - - if location := strings.TrimSpace(resp.Header.Get("Location")); qobuzURLLooksStreamable(location) { - return location, nil - } - - body, err := io.ReadAll(io.LimitReader(resp.Body, 128*1024)) - if err != nil { - return "", fmt.Errorf("failed to read WJHE response: %w", err) - } - - if streamURL := extractQobuzStreamingURL(body); streamURL != "" { - return streamURL, nil - } - - if resp.Request != nil && resp.Request.URL != nil { - if streamURL := strings.TrimSpace(resp.Request.URL.String()); streamURL != "" && streamURL != apiURL && qobuzURLLooksStreamable(streamURL) { - return streamURL, nil - } - } - - if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusBadRequest { - return "", fmt.Errorf("WJHE returned status %d: %s", resp.StatusCode, previewQobuzResponseBody(body, 256)) - } - - return "", fmt.Errorf("WJHE response did not include a stream URL") -} - -func qobuzGDStudioPaddedVersion() string { - parts := strings.Split(GetQobuzGDStudioVersion(), ".") - for idx, part := range parts { - part = strings.TrimSpace(part) - if len(part) == 1 { - part = "0" + part - } - parts[idx] = part - } - return strings.Join(parts, "") -} - -func qobuzGDStudioEscapedValue(value string) string { - return strings.ReplaceAll(url.QueryEscape(strings.TrimSpace(value)), "+", "%20") -} - -func (q *QobuzDownloader) getQobuzGDStudioTS9(apiURL string) string { - fallback := strconv.FormatInt(time.Now().UnixMilli(), 10) - if len(fallback) >= 9 { - fallback = fallback[:9] - } - - client := q.client - if client == nil { - client = &http.Client{Timeout: 10 * time.Second} - } - - signatureHost := GetQobuzGDStudioSignatureHost(apiURL) - if signatureHost == "" { - return fallback - } - - req, err := NewRequestWithDefaultHeaders(http.MethodGet, fmt.Sprintf("https://%s/time", signatureHost), nil) - if err != nil { - return fallback - } - - resp, err := client.Do(req) - if err != nil { - return fallback - } - defer resp.Body.Close() - - body, err := io.ReadAll(io.LimitReader(resp.Body, 64)) - if err != nil { - return fallback - } - - timestamp := strings.TrimSpace(string(body)) - if len(timestamp) >= 9 { - return timestamp[:9] - } - - return fallback -} - -func buildQobuzGDStudioSignature(apiURL string, value string, ts9 string) string { - signatureHost := GetQobuzGDStudioSignatureHost(apiURL) - signatureBase := fmt.Sprintf("%s|%s|%s|%s", signatureHost, qobuzGDStudioPaddedVersion(), ts9, qobuzGDStudioEscapedValue(value)) - sum := md5.Sum([]byte(signatureBase)) - digest := hex.EncodeToString(sum[:]) - return strings.ToUpper(digest[len(digest)-8:]) -} - -func mapQobuzGDStudioBitrate(quality string) string { - switch strings.TrimSpace(quality) { - case "27", "7": - return "999" - case "", "6": - return "740" - default: - return "320" - } -} - -func (q *QobuzDownloader) DownloadFromGDStudio(trackID int64, quality string, apiURL string) (string, error) { - apiURL = strings.TrimSpace(apiURL) - if apiURL == "" { - apiURL = GetQobuzGDStudioPrimaryAPIURL() - } - - signatureHost := GetQobuzGDStudioSignatureHost(apiURL) - if signatureHost == "" { - return "", fmt.Errorf("GDStudio API URL is invalid: %s", apiURL) - } - - trackIDString := strconv.FormatInt(trackID, 10) - ts9 := q.getQobuzGDStudioTS9(apiURL) - payload := url.Values{ - "types": {"url"}, - "id": {trackIDString}, - "source": {"qobuz"}, - "br": {mapQobuzGDStudioBitrate(quality)}, - "s": {buildQobuzGDStudioSignature(apiURL, trackIDString, ts9)}, - } - - req, err := NewRequestWithDefaultHeaders(http.MethodPost, apiURL, strings.NewReader(payload.Encode())) - if err != nil { - return "", fmt.Errorf("failed to create GDStudio request: %w", err) - } - req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") - req.Header.Set("Origin", fmt.Sprintf("https://%s", signatureHost)) - req.Header.Set("Referer", fmt.Sprintf("https://%s/", signatureHost)) - - resp, err := q.client.Do(req) - if err != nil { - return "", fmt.Errorf("failed to reach GDStudio: %w", err) - } - defer resp.Body.Close() - - body, err := io.ReadAll(io.LimitReader(resp.Body, 256*1024)) - if err != nil { - return "", fmt.Errorf("failed to read GDStudio response: %w", err) - } - - if resp.StatusCode != http.StatusOK { - return "", fmt.Errorf("GDStudio returned status %d: %s", resp.StatusCode, previewQobuzResponseBody(body, 256)) - } - - streamURL := extractQobuzStreamingURL(body) - if streamURL == "" { - return "", fmt.Errorf("GDStudio response did not include a stream URL: %s", previewQobuzResponseBody(body, 256)) - } - - return streamURL, nil -} - -func (q *QobuzDownloader) DownloadFromMusicDL(trackID int64, quality string) (string, error) { - if strings.TrimSpace(quality) == "" { - quality = "6" - } - - debugKey, err := getQobuzMusicDLDebugKey() - if err != nil { - return "", fmt.Errorf("failed to decrypt MusicDL debug key: %w", err) - } - - payload, err := json.Marshal(qobuzMusicDLRequest{ - URL: buildQobuzOpenTrackURL(trackID), - Quality: strings.TrimSpace(quality), - }) - if err != nil { - return "", fmt.Errorf("failed to encode MusicDL request: %w", err) - } - - req, err := NewRequestWithDefaultHeaders(http.MethodPost, GetQobuzMusicDLDownloadAPIURL(), bytes.NewReader(payload)) - if err != nil { - return "", fmt.Errorf("failed to create MusicDL request: %w", err) - } - - req.Header.Set("Content-Type", "application/json") - req.Header.Set("X-Debug-Key", debugKey) - - resp, err := q.client.Do(req) - if err != nil { - return "", fmt.Errorf("failed to reach MusicDL: %w", err) - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("failed to read MusicDL response: %w", err) - } - - if resp.StatusCode != http.StatusOK { - return "", fmt.Errorf("MusicDL returned status %d: %s", resp.StatusCode, previewQobuzResponseBody(body, 256)) - } - - var downloadResp qobuzMusicDLResponse - if err := json.Unmarshal(body, &downloadResp); err != nil { - return "", fmt.Errorf("failed to decode MusicDL response: %w (%s)", err, previewQobuzResponseBody(body, 256)) - } - - if !downloadResp.Success { - message := strings.TrimSpace(downloadResp.Error) - if message == "" { - message = strings.TrimSpace(downloadResp.Message) - } - if message == "" { - message = "MusicDL reported failure" - } - return "", fmt.Errorf("%s", message) - } - - downloadURL := strings.TrimSpace(downloadResp.DownloadURL) - if downloadURL == "" { - return "", fmt.Errorf("MusicDL response did not include a download_url") - } - - return downloadURL, nil -} - -func CheckQobuzMusicDLStatusDetailed(client *http.Client) error { - if client == nil { - client = &http.Client{Timeout: 4 * time.Second} - } - - downloader := &QobuzDownloader{client: client} - _, err := downloader.DownloadFromMusicDL(qobuzProbeTrackID, "27") - return err -} - -func CheckQobuzMusicDLStatus(client *http.Client) bool { - return CheckQobuzMusicDLStatusDetailed(client) == nil -} - -func CheckQobuzWJHEStatusDetailed(client *http.Client) error { - if client == nil { - client = &http.Client{Timeout: 4 * time.Second} - } - - downloader := &QobuzDownloader{client: client} - _, err := downloader.DownloadFromWJHE(qobuzProbeTrackID, "27") - return err -} - -func CheckQobuzWJHEStatus(client *http.Client) bool { - return CheckQobuzWJHEStatusDetailed(client) == nil -} - -func CheckQobuzGDStudioAPIStatusDetailed(client *http.Client, apiURL string) error { - if client == nil { - client = &http.Client{Timeout: 4 * time.Second} - } - - downloader := &QobuzDownloader{client: client} - _, err := downloader.DownloadFromGDStudio(qobuzProbeTrackID, "27", apiURL) - return err -} - -func CheckQobuzGDStudioAPIStatus(client *http.Client, apiURL string) bool { - return CheckQobuzGDStudioAPIStatusDetailed(client, apiURL) == nil -} - -func (q *QobuzDownloader) GetDownloadURL(trackID int64, quality string, allowFallback bool) (string, error) { - qualityCode := quality - if qualityCode == "" || qualityCode == "5" { - qualityCode = "6" - } - - fmt.Printf("Getting download URL for track ID: %d with requested quality: %s\n", trackID, qualityCode) - - downloadFunc := func(qual string) (string, error) { - attemptMap := make(map[string]qobuzProviderAttempt) - attemptIDs := make([]string, 0, len(GetQobuzDownloadProviderURLs())) - for _, provider := range q.getQobuzDownloadProviders() { - for _, attempt := range provider.Attempts(trackID, qual) { - attemptMap[attempt.ID] = attempt - attemptIDs = append(attemptIDs, attempt.ID) - } - } - - orderedProviderIDs := prioritizeProviders("qobuz", attemptIDs) - orderedProviderIDs = moveQobuzAttemptIDsLast(orderedProviderIDs, GetQobuzMusicDLDownloadAPIURL()) - var lastErr error - for _, providerID := range orderedProviderIDs { - attempt, ok := attemptMap[providerID] - if !ok { - continue - } - - fmt.Printf("Trying Provider: %s (Quality: %s)...\n", attempt.Name, qual) - - url, err := attempt.Download() - if err == nil { - fmt.Printf("✓ Success\n") - recordProviderSuccess("qobuz", attempt.ID) - return url, nil - } - - fmt.Printf("Provider failed: %v\n", err) - recordProviderFailure("qobuz", attempt.ID) - lastErr = err - } - return "", lastErr - } - - url, err := downloadFunc(qualityCode) - if err == nil { - return url, nil - } - - currentQuality := qualityCode - - if currentQuality == "27" && allowFallback { - fmt.Printf("⚠ Download with quality 27 failed, trying fallback to 7 (24-bit Standard)...\n") - url, err := downloadFunc("7") - if err == nil { - fmt.Println("✓ Success with fallback quality 7") - return url, nil - } - - currentQuality = "7" - } - - if currentQuality == "7" && allowFallback { - fmt.Printf("⚠ Download with quality 7 failed, trying fallback to 6 (16-bit Lossless)...\n") - url, err := downloadFunc("6") - if err == nil { - fmt.Println("✓ Success with fallback quality 6") - return url, nil - } - } - - return "", fmt.Errorf("all APIs and fallbacks failed. Last error: %v", err) -} - -func (q *QobuzDownloader) DownloadFile(url, filepath string) error { - fmt.Println("Starting file download...") - - downloadClient := &http.Client{ - Timeout: 5 * time.Minute, - } - - req, err := NewRequestWithDefaultHeaders(http.MethodGet, url, nil) - if err != nil { - return fmt.Errorf("failed to create download request: %w", err) - } - - resp, err := downloadClient.Do(req) - if err != nil { - return fmt.Errorf("failed to download file: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("download failed with status %d", resp.StatusCode) - } - - fmt.Printf("Creating file: %s\n", filepath) - out, err := os.Create(filepath) - if err != nil { - return fmt.Errorf("failed to create file: %w", err) - } - defer out.Close() - - fmt.Println("Downloading...") - - pw := NewProgressWriter(out) - _, err = io.Copy(pw, resp.Body) - if err != nil { - return fmt.Errorf("failed to write file: %w", err) - } - - fmt.Printf("\rDownloaded: %.2f MB (Complete)\n", float64(pw.GetTotal())/(1024*1024)) - return nil -} - -func (q *QobuzDownloader) DownloadCoverArt(coverURL, filepath string) error { - if coverURL == "" { - return fmt.Errorf("no cover URL provided") - } - - req, err := NewRequestWithDefaultHeaders(http.MethodGet, coverURL, nil) - if err != nil { - return fmt.Errorf("failed to create cover request: %w", err) - } - - resp, err := q.client.Do(req) - if err != nil { - return fmt.Errorf("failed to download cover: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("cover download failed with status %d", resp.StatusCode) - } - - out, err := os.Create(filepath) - if err != nil { - return fmt.Errorf("failed to create cover file: %w", err) - } - defer out.Close() - - _, err = io.Copy(out, resp.Body) - return err -} - -func buildQobuzFilename(title, artist, album, albumArtist, releaseDate string, trackNumber, discNumber int, format string, includeTrackNumber bool, position int, useAlbumTrackNumber bool, extra ...string) string { - var filename string - isrc := "" - if len(extra) > 0 { - isrc = SanitizeOptionalFilename(extra[0]) - } - - numberToUse := position - if useAlbumTrackNumber && trackNumber > 0 { - numberToUse = trackNumber - } - - year := "" - if len(releaseDate) >= 4 { - year = releaseDate[:4] - } - - if strings.Contains(format, "{") { - filename = format - filename = strings.ReplaceAll(filename, "{title}", title) - filename = strings.ReplaceAll(filename, "{artist}", artist) - filename = strings.ReplaceAll(filename, "{album}", album) - filename = strings.ReplaceAll(filename, "{album_artist}", albumArtist) - filename = strings.ReplaceAll(filename, "{year}", year) - filename = strings.ReplaceAll(filename, "{date}", SanitizeFilename(releaseDate)) - filename = strings.ReplaceAll(filename, "{isrc}", isrc) - - if discNumber > 0 { - filename = strings.ReplaceAll(filename, "{disc}", fmt.Sprintf("%d", discNumber)) - } else { - filename = strings.ReplaceAll(filename, "{disc}", "") - } - - if numberToUse > 0 { - filename = strings.ReplaceAll(filename, "{track}", fmt.Sprintf("%02d", numberToUse)) - } else { - - filename = regexp.MustCompile(`\{track\}\.\s*`).ReplaceAllString(filename, "") - filename = regexp.MustCompile(`\{track\}\s*-\s*`).ReplaceAllString(filename, "") - filename = regexp.MustCompile(`\{track\}\s*`).ReplaceAllString(filename, "") - } - } else { - - switch format { - case "artist-title": - filename = fmt.Sprintf("%s - %s", artist, title) - case "title": - filename = title - default: - filename = fmt.Sprintf("%s - %s", title, artist) - } - - if includeTrackNumber && position > 0 { - filename = fmt.Sprintf("%02d. %s", numberToUse, filename) - } - } - - return filename + ".flac" -} - -func (q *QobuzDownloader) DownloadTrack(spotifyID, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, useAlbumTrackNumber bool, spotifyCoverURL string, embedMaxQualityCover bool, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, spotifyURL string, allowFallback bool, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) { - var isrc string - if spotifyID != "" { - linkClient := NewSongLinkClient() - resolvedISRC, err := linkClient.GetISRCDirect(spotifyID) - if err != nil { - return "", fmt.Errorf("failed to get ISRC: %v", err) - } - isrc = resolvedISRC - } else { - return "", fmt.Errorf("spotify ID is required for Qobuz download") - } - - return q.DownloadTrackWithISRC(isrc, outputDir, quality, filenameFormat, includeTrackNumber, position, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, useAlbumTrackNumber, spotifyCoverURL, embedMaxQualityCover, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks, spotifyTotalDiscs, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, spotifyURL, allowFallback, useFirstArtistOnly, useSingleGenre, embedGenre) -} - -func (q *QobuzDownloader) DownloadTrackWithISRC(isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, useAlbumTrackNumber bool, spotifyCoverURL string, embedMaxQualityCover bool, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, spotifyURL string, allowFallback bool, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) { - fmt.Printf("Fetching track info for ISRC: %s\n", isrc) - - metaChan := make(chan Metadata, 1) - if embedGenre && isrc != "" { - go func() { - if ShouldSkipMusicBrainzMetadataFetch() { - fmt.Println("Skipping MusicBrainz metadata fetch because status check is offline.") - metaChan <- Metadata{} - } else { - fmt.Println("Fetching MusicBrainz metadata...") - if fetchedMeta, err := FetchMusicBrainzMetadata(isrc, spotifyTrackName, spotifyArtistName, spotifyAlbumName, useSingleGenre, embedGenre); err == nil { - fmt.Println("✓ MusicBrainz metadata fetched") - metaChan <- fetchedMeta - } else { - fmt.Printf("Warning: Failed to fetch MusicBrainz metadata: %v\n", err) - metaChan <- Metadata{} - } - } - }() - } else { - close(metaChan) - } - - if outputDir != "." { - if err := os.MkdirAll(outputDir, 0755); err != nil { - return "", fmt.Errorf("failed to create output directory: %w", err) - } - } - - track, err := q.searchByISRC(isrc, spotifyTrackName, spotifyArtistName, spotifyAlbumName) - if err != nil { - return "", err - } - - artists := spotifyArtistName - trackTitle := spotifyTrackName - albumTitle := spotifyAlbumName - - fmt.Printf("Found track: %s - %s\n", artists, trackTitle) - fmt.Printf("Album: %s\n", albumTitle) - - qualityInfo := "Standard" - if track.Hires { - if track.MaximumBitDepth > 0 && track.MaximumSamplingRate > 0 { - qualityInfo = fmt.Sprintf("Hi-Res (%d-bit / %.1f kHz)", track.MaximumBitDepth, track.MaximumSamplingRate) - } else if track.MaximumBitDepth > 0 { - qualityInfo = fmt.Sprintf("Hi-Res available (%d-bit)", track.MaximumBitDepth) - } else { - qualityInfo = "Hi-Res available" - } - } - fmt.Printf("Quality: %s\n", qualityInfo) - - fmt.Println("Getting download URL...") - downloadURL, err := q.GetDownloadURL(track.ID, quality, allowFallback) - if err != nil { - return "", fmt.Errorf("failed to get download URL: %w", err) - } - - if downloadURL == "" { - return "", fmt.Errorf("received empty download URL") - } - - urlPreview := downloadURL - if len(downloadURL) > 60 { - urlPreview = downloadURL[:60] + "..." - } - fmt.Printf("Download URL obtained: %s\n", urlPreview) - - safeArtist := sanitizeFilename(artists) - safeAlbumArtist := sanitizeFilename(spotifyAlbumArtist) - - if useFirstArtistOnly { - safeArtist = sanitizeFilename(GetFirstArtist(artists)) - safeAlbumArtist = sanitizeFilename(GetFirstArtist(spotifyAlbumArtist)) - } - - safeTitle := sanitizeFilename(trackTitle) - safeAlbum := sanitizeFilename(albumTitle) - - filename := buildQobuzFilename(safeTitle, safeArtist, safeAlbum, safeAlbumArtist, spotifyReleaseDate, spotifyTrackNumber, spotifyDiscNumber, filenameFormat, includeTrackNumber, position, useAlbumTrackNumber, isrc) - filepath := filepath.Join(outputDir, filename) - filepath, alreadyExists := ResolveOutputPathForDownload(filepath, GetRedownloadWithSuffixSetting()) - if alreadyExists { - fmt.Printf("File already exists: %s (%.2f MB)\n", filepath, float64(mustFileSize(filepath))/(1024*1024)) - return "EXISTS:" + filepath, nil - } - - fmt.Printf("Downloading FLAC file to: %s\n", filepath) - if err := q.DownloadFile(downloadURL, filepath); err != nil { - return "", fmt.Errorf("failed to download file: %w", err) - } - - fmt.Printf("Downloaded: %s\n", filepath) - - coverPath := "" - - if spotifyCoverURL != "" { - coverPath = filepath + ".cover.jpg" - coverClient := NewCoverClient() - if err := coverClient.DownloadCoverToPath(spotifyCoverURL, coverPath, embedMaxQualityCover); err != nil { - fmt.Printf("Warning: Failed to download Spotify cover: %v\n", err) - coverPath = "" - } else { - defer os.Remove(coverPath) - fmt.Println("Spotify cover downloaded") - } - } - - var mbMeta Metadata - if isrc != "" { - mbMeta = <-metaChan - } - - fmt.Println("Embedding metadata and cover art...") - - trackNumberToEmbed := spotifyTrackNumber - if trackNumberToEmbed == 0 { - trackNumberToEmbed = 1 - } - - upc := "" - if identifiers, err := GetSpotifyTrackIdentifiersDirect(spotifyURL); err == nil || identifiers.ISRC != "" || identifiers.UPC != "" { - if strings.TrimSpace(isrc) == "" && strings.TrimSpace(identifiers.ISRC) != "" { - isrc = strings.TrimSpace(identifiers.ISRC) - } - upc = strings.TrimSpace(identifiers.UPC) - } - - metadata := Metadata{ - Title: trackTitle, - Artist: artists, - Album: albumTitle, - AlbumArtist: spotifyAlbumArtist, - Date: spotifyReleaseDate, - TrackNumber: trackNumberToEmbed, - TotalTracks: spotifyTotalTracks, - DiscNumber: spotifyDiscNumber, - TotalDiscs: spotifyTotalDiscs, - URL: spotifyURL, - Comment: spotifyURL, - Copyright: spotifyCopyright, - Publisher: spotifyPublisher, - Composer: spotifyComposer, - Separator: metadataSeparator, - Description: "https://github.com/spotbye/SpotiFLAC", - ISRC: isrc, - UPC: upc, - Genre: mbMeta.Genre, - } - - if err := EmbedMetadata(filepath, metadata, coverPath); err != nil { - return "", fmt.Errorf("failed to embed metadata: %w", err) - } - - fmt.Println("Metadata embedded successfully!") - return filepath, nil -} diff --git a/backend/qobuz_api.go b/backend/qobuz_api.go deleted file mode 100644 index 7815b8a..0000000 --- a/backend/qobuz_api.go +++ /dev/null @@ -1,407 +0,0 @@ -package backend - -import ( - "crypto/md5" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "os" - "path/filepath" - "regexp" - "sort" - "strings" - "sync" - "time" -) - -const ( - qobuzAPIBaseURL = "https://www.qobuz.com/api.json/0.2" - qobuzDefaultAPIAppID = "712109809" - qobuzDefaultAPIAppSecret = "589be88e4538daea11f509d29e4a23b1" - qobuzDefaultUA = DefaultDownloaderUserAgent - qobuzCredentialsCacheFile = "qobuz-api-credentials.json" - qobuzCredentialsCacheTTL = 24 * time.Hour - qobuzCredentialsProbeTrackISRC = "USUM71703861" - qobuzOpenTrackProbeURL = "https://open.qobuz.com/track/1" -) - -var ( - qobuzCredentialsMu sync.Mutex - qobuzCachedCredentials *qobuzAPICredentials - qobuzOpenBundleScriptPattern = regexp.MustCompile(`]+src="([^"]+/js/main\.js|/resources/[^"]+/js/main\.js)"`) - qobuzOpenAPIConfigPattern = regexp.MustCompile(`app_id:"(?P\d{9})",app_secret:"(?P[a-f0-9]{32})"`) -) - -type qobuzAPICredentials struct { - AppID string `json:"app_id"` - AppSecret string `json:"app_secret"` - Source string `json:"source,omitempty"` - FetchedAtUnix int64 `json:"fetched_at_unix"` -} - -type qobuzCredentialProbeResponse struct { - Tracks struct { - Total int `json:"total"` - } `json:"tracks"` -} - -func defaultQobuzAPICredentials() *qobuzAPICredentials { - return &qobuzAPICredentials{ - AppID: qobuzDefaultAPIAppID, - AppSecret: qobuzDefaultAPIAppSecret, - Source: "embedded-default", - FetchedAtUnix: time.Now().Unix(), - } -} - -func qobuzCredentialsCachePath() (string, error) { - appDir, err := GetFFmpegDir() - if err != nil { - return "", err - } - return filepath.Join(appDir, qobuzCredentialsCacheFile), nil -} - -func loadQobuzCachedCredentials() (*qobuzAPICredentials, error) { - cachePath, err := qobuzCredentialsCachePath() - if err != nil { - return nil, err - } - - body, err := os.ReadFile(cachePath) - if err != nil { - if os.IsNotExist(err) { - return nil, nil - } - return nil, fmt.Errorf("failed to read qobuz credentials cache: %w", err) - } - - var creds qobuzAPICredentials - if err := json.Unmarshal(body, &creds); err != nil { - return nil, fmt.Errorf("failed to parse qobuz credentials cache: %w", err) - } - - if strings.TrimSpace(creds.AppID) == "" || strings.TrimSpace(creds.AppSecret) == "" { - return nil, fmt.Errorf("qobuz credentials cache is incomplete") - } - - return &creds, nil -} - -func saveQobuzCachedCredentials(creds *qobuzAPICredentials) error { - if creds == nil { - return fmt.Errorf("qobuz credentials are required") - } - - cachePath, err := qobuzCredentialsCachePath() - if err != nil { - return err - } - - if err := os.MkdirAll(filepath.Dir(cachePath), 0o755); err != nil { - return fmt.Errorf("failed to create qobuz credentials cache directory: %w", err) - } - - body, err := json.MarshalIndent(creds, "", " ") - if err != nil { - return err - } - - if err := os.WriteFile(cachePath, body, 0o644); err != nil { - return fmt.Errorf("failed to write qobuz credentials cache: %w", err) - } - - return nil -} - -func qobuzCredentialsCacheIsFresh(creds *qobuzAPICredentials) bool { - if creds == nil || creds.FetchedAtUnix == 0 || strings.TrimSpace(creds.AppID) == "" || strings.TrimSpace(creds.AppSecret) == "" { - return false - } - return time.Since(time.Unix(creds.FetchedAtUnix, 0)) < qobuzCredentialsCacheTTL -} - -func scrapeQobuzOpenCredentials(client *http.Client) (*qobuzAPICredentials, error) { - req, err := http.NewRequest(http.MethodGet, qobuzOpenTrackProbeURL, nil) - if err != nil { - return nil, err - } - req.Header.Set("User-Agent", qobuzDefaultUA) - - resp, err := client.Do(req) - if err != nil { - return nil, fmt.Errorf("failed to fetch open.qobuz.com shell: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - preview, _ := io.ReadAll(io.LimitReader(resp.Body, 512)) - return nil, fmt.Errorf("open.qobuz.com returned status %d: %s", resp.StatusCode, strings.TrimSpace(string(preview))) - } - - htmlBody, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("failed to read open.qobuz.com shell: %w", err) - } - - scriptMatch := qobuzOpenBundleScriptPattern.FindStringSubmatch(string(htmlBody)) - if len(scriptMatch) < 2 { - return nil, fmt.Errorf("qobuz open bundle URL not found") - } - - bundleURL := strings.TrimSpace(scriptMatch[1]) - if strings.HasPrefix(bundleURL, "/") { - bundleURL = "https://open.qobuz.com" + bundleURL - } - if bundleURL == "" { - return nil, fmt.Errorf("qobuz open bundle URL is empty") - } - - bundleReq, err := http.NewRequest(http.MethodGet, bundleURL, nil) - if err != nil { - return nil, err - } - bundleReq.Header.Set("User-Agent", qobuzDefaultUA) - - bundleResp, err := client.Do(bundleReq) - if err != nil { - return nil, fmt.Errorf("failed to fetch qobuz open bundle: %w", err) - } - defer bundleResp.Body.Close() - - if bundleResp.StatusCode != http.StatusOK { - preview, _ := io.ReadAll(io.LimitReader(bundleResp.Body, 512)) - return nil, fmt.Errorf("qobuz open bundle returned status %d: %s", bundleResp.StatusCode, strings.TrimSpace(string(preview))) - } - - bundleBody, err := io.ReadAll(bundleResp.Body) - if err != nil { - return nil, fmt.Errorf("failed to read qobuz open bundle: %w", err) - } - - configMatch := qobuzOpenAPIConfigPattern.FindStringSubmatch(string(bundleBody)) - if len(configMatch) < 3 { - return nil, fmt.Errorf("qobuz api app_id/app_secret pair not found in open bundle") - } - - return &qobuzAPICredentials{ - AppID: strings.TrimSpace(configMatch[1]), - AppSecret: strings.TrimSpace(configMatch[2]), - Source: bundleURL, - FetchedAtUnix: time.Now().Unix(), - }, nil -} - -func qobuzNormalizedPath(path string) string { - return strings.Trim(strings.TrimSpace(path), "/") -} - -func qobuzSignaturePayload(path string, params url.Values, timestamp string, secret string) string { - normalizedPath := strings.ReplaceAll(qobuzNormalizedPath(path), "/", "") - keys := make([]string, 0, len(params)) - for key := range params { - switch key { - case "app_id", "request_ts", "request_sig": - continue - } - keys = append(keys, key) - } - sort.Strings(keys) - - var builder strings.Builder - builder.WriteString(normalizedPath) - for _, key := range keys { - values := params[key] - if len(values) == 0 { - builder.WriteString(key) - continue - } - for _, value := range values { - builder.WriteString(key) - builder.WriteString(value) - } - } - builder.WriteString(timestamp) - builder.WriteString(secret) - return builder.String() -} - -func qobuzRequestSignature(path string, params url.Values, timestamp string, secret string) string { - sum := md5.Sum([]byte(qobuzSignaturePayload(path, params, timestamp, secret))) - return hex.EncodeToString(sum[:]) -} - -func newQobuzSignedRequestWithCredentials(method string, path string, params url.Values, creds *qobuzAPICredentials) (*http.Request, error) { - normalizedPath := qobuzNormalizedPath(path) - if normalizedPath == "" { - return nil, fmt.Errorf("qobuz request path is empty") - } - if creds == nil || strings.TrimSpace(creds.AppID) == "" || strings.TrimSpace(creds.AppSecret) == "" { - return nil, fmt.Errorf("qobuz credentials are incomplete") - } - - clonedParams := url.Values{} - for key, values := range params { - for _, value := range values { - clonedParams.Add(key, value) - } - } - - timestamp := fmt.Sprintf("%d", time.Now().Unix()) - clonedParams.Set("app_id", creds.AppID) - clonedParams.Set("request_ts", timestamp) - clonedParams.Set("request_sig", qobuzRequestSignature(normalizedPath, params, timestamp, creds.AppSecret)) - - reqURL := fmt.Sprintf("%s/%s?%s", qobuzAPIBaseURL, normalizedPath, clonedParams.Encode()) - req, err := http.NewRequest(method, reqURL, nil) - if err != nil { - return nil, err - } - - req.Header.Set("User-Agent", qobuzDefaultUA) - req.Header.Set("Accept", "application/json") - req.Header.Set("X-App-Id", creds.AppID) - - return req, nil -} - -func qobuzCredentialsSupportSignedMetadata(client *http.Client, creds *qobuzAPICredentials) bool { - if creds == nil { - return false - } - - req, err := newQobuzSignedRequestWithCredentials(http.MethodGet, "track/search", url.Values{ - "query": {qobuzCredentialsProbeTrackISRC}, - "limit": {"1"}, - }, creds) - if err != nil { - return false - } - - resp, err := client.Do(req) - if err != nil { - return false - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return false - } - - var payload qobuzCredentialProbeResponse - if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil { - return false - } - - return payload.Tracks.Total > 0 -} - -func getQobuzAPICredentials(forceRefresh bool) (*qobuzAPICredentials, error) { - qobuzCredentialsMu.Lock() - defer qobuzCredentialsMu.Unlock() - - if !forceRefresh && qobuzCredentialsCacheIsFresh(qobuzCachedCredentials) { - return qobuzCachedCredentials, nil - } - - cachedFromDisk, diskErr := loadQobuzCachedCredentials() - if diskErr != nil { - fmt.Printf("Warning: failed to read Qobuz credentials cache: %v\n", diskErr) - } - if !forceRefresh && qobuzCredentialsCacheIsFresh(cachedFromDisk) { - qobuzCachedCredentials = cachedFromDisk - return qobuzCachedCredentials, nil - } - - client := &http.Client{Timeout: 30 * time.Second} - scrapedCreds, scrapeErr := scrapeQobuzOpenCredentials(client) - if scrapeErr == nil { - if qobuzCredentialsSupportSignedMetadata(client, scrapedCreds) { - qobuzCachedCredentials = scrapedCreds - if err := saveQobuzCachedCredentials(scrapedCreds); err != nil { - fmt.Printf("Warning: failed to write Qobuz credentials cache: %v\n", err) - } - fmt.Printf("Loaded fresh Qobuz credentials from %s (app_id=%s)\n", scrapedCreds.Source, scrapedCreds.AppID) - return qobuzCachedCredentials, nil - } - scrapeErr = fmt.Errorf("scraped qobuz credentials did not pass validation") - } - - if cachedFromDisk != nil { - qobuzCachedCredentials = cachedFromDisk - fmt.Printf("Warning: failed to refresh Qobuz credentials, using cached credentials: %v\n", scrapeErr) - return qobuzCachedCredentials, nil - } - - if qobuzCachedCredentials != nil { - fmt.Printf("Warning: failed to refresh Qobuz credentials, using in-memory credentials: %v\n", scrapeErr) - return qobuzCachedCredentials, nil - } - - fallback := defaultQobuzAPICredentials() - qobuzCachedCredentials = fallback - if scrapeErr != nil { - fmt.Printf("Warning: failed to refresh Qobuz credentials, using embedded fallback: %v\n", scrapeErr) - } - return qobuzCachedCredentials, nil -} - -func qobuzShouldRefreshCredentials(statusCode int) bool { - return statusCode == http.StatusBadRequest || statusCode == http.StatusUnauthorized -} - -func newQobuzSignedRequest(method string, path string, params url.Values) (*http.Request, error) { - creds, err := getQobuzAPICredentials(false) - if err != nil { - return nil, err - } - return newQobuzSignedRequestWithCredentials(method, path, params, creds) -} - -func doQobuzSignedRequest(method string, path string, params url.Values, client *http.Client) (*http.Response, error) { - if client == nil { - client = &http.Client{Timeout: 20 * time.Second} - } - - call := func(forceRefresh bool) (*http.Response, error) { - creds, err := getQobuzAPICredentials(forceRefresh) - if err != nil { - return nil, err - } - req, err := newQobuzSignedRequestWithCredentials(method, path, params, creds) - if err != nil { - return nil, err - } - return client.Do(req) - } - - resp, err := call(false) - if err != nil { - return nil, err - } - - if qobuzShouldRefreshCredentials(resp.StatusCode) { - resp.Body.Close() - return call(true) - } - - return resp, nil -} - -func doQobuzSignedJSONRequest(path string, params url.Values, target interface{}) error { - resp, err := doQobuzSignedRequest(http.MethodGet, path, params, &http.Client{Timeout: 20 * time.Second}) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - snippet, _ := io.ReadAll(io.LimitReader(resp.Body, 2048)) - return fmt.Errorf("qobuz request failed: HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(snippet))) - } - - return json.NewDecoder(resp.Body).Decode(target) -} diff --git a/backend/qobuz_providers.go b/backend/qobuz_providers.go deleted file mode 100644 index e00e835..0000000 --- a/backend/qobuz_providers.go +++ /dev/null @@ -1,106 +0,0 @@ -package backend - -type qobuzDownloadProvider interface { - Name() string - Attempts(trackID int64, quality string) []qobuzProviderAttempt -} - -type qobuzProviderAttempt struct { - Name string - ID string - Download func() (string, error) -} - -type QobuzProviderWJHE struct { - downloader *QobuzDownloader -} - -func (p QobuzProviderWJHE) Name() string { - return "QobuzProviderWJHE" -} - -func (p QobuzProviderWJHE) Attempts(trackID int64, quality string) []qobuzProviderAttempt { - return []qobuzProviderAttempt{ - { - Name: p.Name(), - ID: GetQobuzWJHEStreamAPIURL(), - Download: func() (string, error) { - return p.downloader.DownloadFromWJHE(trackID, quality) - }, - }, - } -} - -type QobuzProviderMusicDL struct { - downloader *QobuzDownloader -} - -func (p QobuzProviderMusicDL) Name() string { - return "QobuzProviderMusicDL" -} - -func (p QobuzProviderMusicDL) Attempts(trackID int64, quality string) []qobuzProviderAttempt { - return []qobuzProviderAttempt{ - { - Name: p.Name(), - ID: GetQobuzMusicDLDownloadAPIURL(), - Download: func() (string, error) { - return p.downloader.DownloadFromMusicDL(trackID, quality) - }, - }, - } -} - -type QobuzProviderGDStudio struct { - downloader *QobuzDownloader -} - -func (p QobuzProviderGDStudio) Name() string { - return "QobuzProviderGDStudio" -} - -func (p QobuzProviderGDStudio) Attempts(trackID int64, quality string) []qobuzProviderAttempt { - attempts := make([]qobuzProviderAttempt, 0, len(GetQobuzGDStudioAPIURLs())) - for _, apiURL := range GetQobuzGDStudioAPIURLs() { - currentAPIURL := apiURL - attempts = append(attempts, qobuzProviderAttempt{ - Name: p.Name(), - ID: currentAPIURL, - Download: func() (string, error) { - return p.downloader.DownloadFromGDStudio(trackID, quality, currentAPIURL) - }, - }) - } - return attempts -} - -func (q *QobuzDownloader) getQobuzDownloadProviders() []qobuzDownloadProvider { - return []qobuzDownloadProvider{ - QobuzProviderWJHE{downloader: q}, - QobuzProviderGDStudio{downloader: q}, - QobuzProviderMusicDL{downloader: q}, - } -} - -func moveQobuzAttemptIDsLast(providerIDs []string, lastIDs ...string) []string { - if len(providerIDs) == 0 || len(lastIDs) == 0 { - return append([]string(nil), providerIDs...) - } - - lastIDSet := make(map[string]struct{}, len(lastIDs)) - for _, providerID := range lastIDs { - lastIDSet[providerID] = struct{}{} - } - - ordered := make([]string, 0, len(providerIDs)) - trailing := make([]string, 0, len(providerIDs)) - for _, providerID := range providerIDs { - if _, ok := lastIDSet[providerID]; ok { - trailing = append(trailing, providerID) - continue - } - ordered = append(ordered, providerID) - } - - return append(ordered, trailing...) -} diff --git a/backend/recent_fetches.go b/backend/recent_fetches.go deleted file mode 100644 index 34d30fd..0000000 --- a/backend/recent_fetches.go +++ /dev/null @@ -1,91 +0,0 @@ -package backend - -import ( - "encoding/json" - "os" - "path/filepath" - "strings" - "sync" -) - -const recentFetchesFileName = "recent_fetches.json" - -type RecentFetchItem struct { - ID string `json:"id"` - URL string `json:"url"` - Type string `json:"type"` - Name string `json:"name"` - Artist string `json:"artist"` - Image string `json:"image"` - Timestamp int64 `json:"timestamp"` -} - -var ( - recentFetchesMu sync.Mutex - recentFetchesDirResolver = GetFFmpegDir -) - -func recentFetchesFilePath() (string, error) { - baseDir, err := recentFetchesDirResolver() - if err != nil { - return "", err - } - if err := os.MkdirAll(baseDir, 0o755); err != nil { - return "", err - } - return filepath.Join(baseDir, recentFetchesFileName), nil -} - -func LoadRecentFetches() ([]RecentFetchItem, error) { - recentFetchesMu.Lock() - defer recentFetchesMu.Unlock() - - filePath, err := recentFetchesFilePath() - if err != nil { - return nil, err - } - - data, err := os.ReadFile(filePath) - if err != nil { - if os.IsNotExist(err) { - return []RecentFetchItem{}, nil - } - return nil, err - } - - if strings.TrimSpace(string(data)) == "" { - return []RecentFetchItem{}, nil - } - - var items []RecentFetchItem - if err := json.Unmarshal(data, &items); err != nil { - return nil, err - } - - if items == nil { - return []RecentFetchItem{}, nil - } - - return items, nil -} - -func SaveRecentFetches(items []RecentFetchItem) error { - recentFetchesMu.Lock() - defer recentFetchesMu.Unlock() - - filePath, err := recentFetchesFilePath() - if err != nil { - return err - } - - if items == nil { - items = []RecentFetchItem{} - } - - data, err := json.MarshalIndent(items, "", " ") - if err != nil { - return err - } - - return os.WriteFile(filePath, data, 0o644) -} diff --git a/backend/resample.go b/backend/resample.go deleted file mode 100644 index 9d53ec1..0000000 --- a/backend/resample.go +++ /dev/null @@ -1,223 +0,0 @@ -package backend - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "strconv" - "strings" - "sync" -) - -type FlacInfo struct { - Path string `json:"path"` - SampleRate uint32 `json:"sample_rate"` - BitsPerSample uint8 `json:"bits_per_sample"` -} - -func GetFlacInfoBatch(paths []string) []FlacInfo { - results := make([]FlacInfo, len(paths)) - var wg sync.WaitGroup - - for i, path := range paths { - wg.Add(1) - go func(idx int, p string) { - defer wg.Done() - info := FlacInfo{Path: p} - - ffprobePath, err := GetFFprobePath() - if err != nil { - results[idx] = info - return - } - - args := []string{ - "-v", "error", - "-select_streams", "a:0", - "-show_entries", "stream=sample_rate,bits_per_raw_sample,bits_per_sample", - "-of", "default=noprint_wrappers=0", - p, - } - cmd := exec.Command(ffprobePath, args...) - setHideWindow(cmd) - out, err := cmd.CombinedOutput() - if err != nil { - results[idx] = info - return - } - - kvMap := make(map[string]string) - for _, line := range strings.Split(string(out), "\n") { - if parts := strings.SplitN(line, "=", 2); len(parts) == 2 { - kvMap[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) - } - } - - if v, ok := kvMap["sample_rate"]; ok { - if s, err := strconv.Atoi(v); err == nil { - info.SampleRate = uint32(s) - } - } - - bits := 0 - if v, ok := kvMap["bits_per_raw_sample"]; ok && v != "N/A" && v != "" { - bits, _ = strconv.Atoi(v) - } - if bits == 0 { - if v, ok := kvMap["bits_per_sample"]; ok && v != "N/A" && v != "" { - bits, _ = strconv.Atoi(v) - } - } - info.BitsPerSample = uint8(bits) - - results[idx] = info - }(i, path) - } - - wg.Wait() - return results -} - -type ResampleRequest struct { - InputFiles []string `json:"input_files"` - SampleRate string `json:"sample_rate"` - BitDepth string `json:"bit_depth"` -} - -type ResampleResult struct { - InputFile string `json:"input_file"` - OutputFile string `json:"output_file"` - Success bool `json:"success"` - Error string `json:"error,omitempty"` -} - -func buildFolderLabel(sampleRate, bitDepth string) string { - var parts []string - - if bitDepth != "" { - parts = append(parts, bitDepth+"bit") - } - - switch sampleRate { - case "44100": - parts = append(parts, "44.1kHz") - case "48000": - parts = append(parts, "48kHz") - case "96000": - parts = append(parts, "96kHz") - case "192000": - parts = append(parts, "192kHz") - default: - if sampleRate != "" { - parts = append(parts, sampleRate+"Hz") - } - } - - if len(parts) == 0 { - return "Resampled" - } - return strings.Join(parts, " ") -} - -func ResampleAudio(req ResampleRequest) ([]ResampleResult, error) { - ffmpegPath, err := GetFFmpegPath() - if err != nil { - return nil, fmt.Errorf("failed to get ffmpeg path: %w", err) - } - - if err := ValidateExecutable(ffmpegPath); err != nil { - return nil, fmt.Errorf("invalid ffmpeg executable: %w", err) - } - - installed, err := IsFFmpegInstalled() - if err != nil || !installed { - return nil, fmt.Errorf("ffmpeg is not installed") - } - - if req.SampleRate == "" && req.BitDepth == "" { - return nil, fmt.Errorf("at least one of sample rate or bit depth must be specified") - } - - results := make([]ResampleResult, len(req.InputFiles)) - var wg sync.WaitGroup - var mu sync.Mutex - - folderLabel := buildFolderLabel(req.SampleRate, req.BitDepth) - - for i, inputFile := range req.InputFiles { - wg.Add(1) - go func(idx int, inputFile string) { - defer wg.Done() - - result := ResampleResult{ - InputFile: inputFile, - } - - inputExt := strings.ToLower(filepath.Ext(inputFile)) - baseName := strings.TrimSuffix(filepath.Base(inputFile), inputExt) - inputDir := filepath.Dir(inputFile) - - outputDir := filepath.Join(inputDir, folderLabel) - if err := os.MkdirAll(outputDir, 0755); err != nil { - result.Error = fmt.Sprintf("failed to create output directory: %v", err) - result.Success = false - mu.Lock() - results[idx] = result - mu.Unlock() - return - } - - outputFile := filepath.Join(outputDir, baseName+".flac") - result.OutputFile = outputFile - - args := []string{ - "-i", inputFile, - "-y", - } - - if req.BitDepth != "" { - switch req.BitDepth { - case "16": - args = append(args, "-c:a", "flac", "-sample_fmt", "s16") - case "24": - args = append(args, "-c:a", "flac", "-sample_fmt", "s32", "-bits_per_raw_sample", "24") - default: - args = append(args, "-c:a", "flac") - } - } else { - args = append(args, "-c:a", "flac") - } - - if req.SampleRate != "" { - args = append(args, "-ar", req.SampleRate) - } - - args = append(args, "-map_metadata", "0") - args = append(args, outputFile) - - fmt.Printf("[Resample] %s -> %s\n", inputFile, outputFile) - - cmd := exec.Command(ffmpegPath, args...) - setHideWindow(cmd) - output, err := cmd.CombinedOutput() - if err != nil { - result.Error = fmt.Sprintf("resampling failed: %s - %s", err.Error(), string(output)) - result.Success = false - mu.Lock() - results[idx] = result - mu.Unlock() - return - } - - result.Success = true - fmt.Printf("[Resample] Done: %s\n", outputFile) - mu.Lock() - results[idx] = result - mu.Unlock() - }(i, inputFile) - } - - wg.Wait() - return results, nil -} diff --git a/backend/songlink.go b/backend/songlink.go deleted file mode 100644 index 8113a21..0000000 --- a/backend/songlink.go +++ /dev/null @@ -1,505 +0,0 @@ -package backend - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "regexp" - "strings" - "time" -) - -const songLinkUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36" - -var ( - isrcPattern = regexp.MustCompile(`\b([A-Z]{2}[A-Z0-9]{3}\d{7})\b`) - amazonAlbumTrackPath = regexp.MustCompile(`/albums/[A-Z0-9]{10}/(B[0-9A-Z]{9})`) - amazonTrackPath = regexp.MustCompile(`/tracks/(B[0-9A-Z]{9})`) -) - -type SongLinkClient struct { - client *http.Client -} - -type SongLinkURLs struct { - TidalURL string `json:"tidal_url"` - AmazonURL string `json:"amazon_url"` - ISRC string `json:"isrc"` -} - -type TrackAvailability struct { - SpotifyID string `json:"spotify_id"` - Tidal bool `json:"tidal"` - Amazon bool `json:"amazon"` - Qobuz bool `json:"qobuz"` - Deezer bool `json:"deezer"` - TidalURL string `json:"tidal_url,omitempty"` - AmazonURL string `json:"amazon_url,omitempty"` - QobuzURL string `json:"qobuz_url,omitempty"` - DeezerURL string `json:"deezer_url,omitempty"` -} - -type songLinkAPIResponse struct { - LinksByPlatform map[string]struct { - URL string `json:"url"` - } `json:"linksByPlatform"` -} - -type qobuzAvailabilityTrack struct { - ID int64 `json:"id"` - Album struct { - ID string `json:"id"` - Title string `json:"title"` - URL string `json:"url"` - RelativeURL string `json:"relative_url"` - } `json:"album"` -} - -func NewSongLinkClient() *SongLinkClient { - return &SongLinkClient{ - client: &http.Client{ - Timeout: 30 * time.Second, - }, - } -} - -func (s *SongLinkClient) GetAllURLsFromSpotify(spotifyTrackID string, region string) (*SongLinkURLs, error) { - links, err := s.resolveSpotifyTrackLinks(spotifyTrackID, region) - if err != nil && (links == nil || (links.TidalURL == "" && links.AmazonURL == "")) { - return nil, err - } - - urls := &SongLinkURLs{} - if links != nil { - urls.TidalURL = links.TidalURL - urls.AmazonURL = normalizeAmazonMusicURL(links.AmazonURL) - urls.ISRC = links.ISRC - } - - if urls.TidalURL == "" && urls.AmazonURL == "" { - if err != nil { - return nil, err - } - return nil, fmt.Errorf("no streaming URLs found") - } - - return urls, nil -} - -func (s *SongLinkClient) CheckTrackAvailability(spotifyTrackID string) (*TrackAvailability, error) { - links, err := s.resolveSpotifyTrackLinks(spotifyTrackID, "") - - availability := &TrackAvailability{ - SpotifyID: spotifyTrackID, - } - - if links != nil { - availability.TidalURL = links.TidalURL - availability.AmazonURL = normalizeAmazonMusicURL(links.AmazonURL) - availability.DeezerURL = normalizeDeezerTrackURL(links.DeezerURL) - availability.Tidal = availability.TidalURL != "" - availability.Amazon = availability.AmazonURL != "" - availability.Deezer = availability.DeezerURL != "" - } - - isrc := "" - if links != nil { - isrc = strings.TrimSpace(links.ISRC) - } - - if isrc == "" && availability.DeezerURL != "" { - if resolvedISRC, deezerErr := getDeezerISRC(availability.DeezerURL); deezerErr == nil { - isrc = resolvedISRC - } - } - - if isrc == "" { - if fallbackISRC, fallbackErr := s.lookupSpotifyISRC(spotifyTrackID); fallbackErr == nil { - isrc = fallbackISRC - } else if err == nil { - err = fallbackErr - } - } - - if isrc != "" { - availability.Qobuz, availability.QobuzURL = checkQobuzAvailability(isrc) - } - - if availability.Tidal || availability.Amazon || availability.Deezer || availability.Qobuz { - return availability, nil - } - - if err != nil { - return availability, err - } - - return availability, fmt.Errorf("no platforms found") -} - -func qobuzNormalizeRelativeURL(rawURL string) string { - rawURL = strings.TrimSpace(rawURL) - if rawURL == "" { - return "" - } - if strings.HasPrefix(rawURL, "http://") || strings.HasPrefix(rawURL, "https://") { - return rawURL - } - if strings.HasPrefix(rawURL, "/") { - return "https://www.qobuz.com" + rawURL - } - return "https://www.qobuz.com/" + rawURL -} - -func qobuzSlugifySegment(value string) string { - value = strings.ToLower(strings.TrimSpace(value)) - if value == "" { - return "" - } - - var builder strings.Builder - lastDash := false - for _, r := range value { - switch { - case r >= 'a' && r <= 'z', r >= '0' && r <= '9': - builder.WriteRune(r) - lastDash = false - default: - if !lastDash { - builder.WriteByte('-') - lastDash = true - } - } - } - - return strings.Trim(builder.String(), "-") -} - -func qobuzAlbumSlugURL(albumTitle string, albumID string) string { - albumID = strings.TrimSpace(albumID) - if albumID == "" { - return "" - } - - slug := qobuzSlugifySegment(albumTitle) - if slug == "" { - return fmt.Sprintf("https://www.qobuz.com/album/%s", albumID) - } - - return fmt.Sprintf("https://www.qobuz.com/album/%s/%s", slug, albumID) -} - -func checkQobuzAvailability(isrc string) (bool, string) { - var searchResp struct { - Tracks struct { - Total int `json:"total"` - Items []qobuzAvailabilityTrack `json:"items"` - } `json:"tracks"` - } - - if err := doQobuzSignedJSONRequest("track/search", url.Values{ - "query": {strings.TrimSpace(isrc)}, - "limit": {"1"}, - }, &searchResp); err != nil { - return false, "" - } - - if searchResp.Tracks.Total == 0 || len(searchResp.Tracks.Items) == 0 { - return false, "" - } - - item := searchResp.Tracks.Items[0] - qobuzURL := strings.TrimSpace(item.Album.URL) - if qobuzURL == "" { - qobuzURL = qobuzNormalizeRelativeURL(item.Album.RelativeURL) - } - if qobuzURL == "" { - qobuzURL = qobuzAlbumSlugURL(item.Album.Title, item.Album.ID) - } - if qobuzURL == "" && item.ID > 0 { - qobuzURL = fmt.Sprintf("https://www.qobuz.com/us-en/track/%d", item.ID) - } - - return true, qobuzURL -} - -func (s *SongLinkClient) GetDeezerURLFromSpotify(spotifyTrackID string) (string, error) { - links, err := s.resolveSpotifyTrackLinks(spotifyTrackID, "") - if links != nil && links.DeezerURL != "" { - deezerURL := normalizeDeezerTrackURL(links.DeezerURL) - fmt.Printf("Found Deezer URL: %s\n", deezerURL) - return deezerURL, nil - } - - isrc := "" - if links != nil { - isrc = strings.TrimSpace(links.ISRC) - } - if isrc == "" { - fallbackISRC, lookupErr := s.lookupSpotifyISRC(spotifyTrackID) - if lookupErr == nil { - isrc = fallbackISRC - } else if err == nil { - err = lookupErr - } - } - - if isrc != "" { - deezerURL, deezerErr := s.lookupDeezerTrackURLByISRC(isrc) - if deezerErr == nil { - fmt.Printf("Found Deezer URL: %s\n", deezerURL) - return deezerURL, nil - } - if err == nil { - err = deezerErr - } - } - - if err != nil { - return "", err - } - return "", fmt.Errorf("deezer link not found") -} - -func getDeezerISRC(deezerURL string) (string, error) { - trackID, err := extractDeezerTrackID(deezerURL) - if err != nil { - return "", err - } - - apiURL := fmt.Sprintf("https://api.deezer.com/track/%s", trackID) - - client := &http.Client{Timeout: 10 * time.Second} - resp, err := client.Get(apiURL) - if err != nil { - return "", fmt.Errorf("failed to call Deezer API: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return "", fmt.Errorf("Deezer API returned status %d", resp.StatusCode) - } - - var deezerTrack struct { - ID int64 `json:"id"` - ISRC string `json:"isrc"` - Title string `json:"title"` - } - if err := json.NewDecoder(resp.Body).Decode(&deezerTrack); err != nil { - return "", fmt.Errorf("failed to decode Deezer API response: %w", err) - } - - if deezerTrack.ISRC == "" { - return "", fmt.Errorf("ISRC not found in Deezer API response for track %s", trackID) - } - - fmt.Printf("Found ISRC from Deezer: %s (track: %s)\n", deezerTrack.ISRC, deezerTrack.Title) - return strings.ToUpper(strings.TrimSpace(deezerTrack.ISRC)), nil -} - -func (s *SongLinkClient) GetISRC(spotifyID string) (string, error) { - links, err := s.resolveSpotifyTrackLinks(spotifyID, "") - if links != nil && links.ISRC != "" { - return links.ISRC, nil - } - - if links != nil && links.DeezerURL != "" { - if isrc, deezerErr := getDeezerISRC(links.DeezerURL); deezerErr == nil { - return isrc, nil - } - } - - isrc, lookupErr := s.lookupSpotifyISRC(spotifyID) - if lookupErr == nil && isrc != "" { - return isrc, nil - } - - if err != nil && lookupErr != nil { - return "", fmt.Errorf("%v | %v", err, lookupErr) - } - if err != nil { - return "", err - } - if lookupErr != nil { - return "", lookupErr - } - - return "", fmt.Errorf("ISRC not found") -} - -func (s *SongLinkClient) GetISRCDirect(spotifyID string) (string, error) { - return s.lookupSpotifyISRC(spotifyID) -} - -func (s *SongLinkClient) fetchSongLinkLinksByURL(rawURL string, region string) (*songLinkAPIResponse, error) { - apiURL := fmt.Sprintf("https://api.song.link/v1-alpha.1/links?url=%s", url.QueryEscape(rawURL)) - if region != "" { - apiURL += fmt.Sprintf("&userCountry=%s", url.QueryEscape(region)) - } - - req, err := http.NewRequest(http.MethodGet, apiURL, nil) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - req.Header.Set("User-Agent", songLinkUserAgent) - - resp, err := s.client.Do(req) - if err != nil { - return nil, fmt.Errorf("failed to call song.link: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - bodyPreview, _ := io.ReadAll(io.LimitReader(resp.Body, 256)) - return nil, fmt.Errorf("song.link returned status %d (%s)", resp.StatusCode, strings.TrimSpace(string(bodyPreview))) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("failed to read song.link response: %w", err) - } - if len(body) == 0 { - return nil, fmt.Errorf("song.link returned empty response") - } - - var parsed songLinkAPIResponse - if err := json.Unmarshal(body, &parsed); err != nil { - bodyStr := string(body) - if len(bodyStr) > 200 { - bodyStr = bodyStr[:200] + "..." - } - return nil, fmt.Errorf("failed to decode song.link response: %w (response: %s)", err, bodyStr) - } - - return &parsed, nil -} - -func (s *SongLinkClient) lookupDeezerTrackURLByISRC(isrc string) (string, error) { - apiURL := fmt.Sprintf("https://api.deezer.com/track/isrc:%s", strings.ToUpper(strings.TrimSpace(isrc))) - - req, err := http.NewRequest(http.MethodGet, apiURL, nil) - if err != nil { - return "", fmt.Errorf("failed to create request: %w", err) - } - req.Header.Set("User-Agent", songLinkUserAgent) - - resp, err := s.client.Do(req) - if err != nil { - return "", fmt.Errorf("failed to call Deezer ISRC API: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return "", fmt.Errorf("Deezer ISRC API returned status %d", resp.StatusCode) - } - - var payload struct { - ID int64 `json:"id"` - ISRC string `json:"isrc"` - Link string `json:"link"` - } - if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil { - return "", fmt.Errorf("failed to decode Deezer ISRC response: %w", err) - } - - if payload.Link != "" { - return normalizeDeezerTrackURL(payload.Link), nil - } - if payload.ID > 0 { - return normalizeDeezerTrackURL(fmt.Sprintf("https://www.deezer.com/track/%d", payload.ID)), nil - } - - return "", fmt.Errorf("deezer track link not found for ISRC %s", isrc) -} - -func mergeSongLinkResponse(links *resolvedTrackLinks, resp *songLinkAPIResponse) { - if resp == nil { - return - } - - if link, ok := resp.LinksByPlatform["tidal"]; ok && link.URL != "" && links.TidalURL == "" { - links.TidalURL = strings.TrimSpace(link.URL) - fmt.Println("✓ Tidal URL found") - } - - if link, ok := resp.LinksByPlatform["amazonMusic"]; ok && link.URL != "" && links.AmazonURL == "" { - links.AmazonURL = normalizeAmazonMusicURL(link.URL) - fmt.Println("✓ Amazon URL found") - } - - if link, ok := resp.LinksByPlatform["deezer"]; ok && link.URL != "" && links.DeezerURL == "" { - links.DeezerURL = normalizeDeezerTrackURL(link.URL) - fmt.Println("✓ Deezer URL found") - } -} - -func normalizeAmazonMusicURL(rawURL string) string { - amazonURL := strings.TrimSpace(rawURL) - if amazonURL == "" { - return "" - } - - if strings.Contains(amazonURL, "trackAsin=") { - parts := strings.Split(amazonURL, "trackAsin=") - if len(parts) > 1 { - trackAsin := strings.Split(parts[1], "&")[0] - if trackAsin != "" { - return fmt.Sprintf("https://music.amazon.com/tracks/%s?musicTerritory=US", trackAsin) - } - } - } - - if match := amazonAlbumTrackPath.FindStringSubmatch(amazonURL); len(match) > 1 { - return fmt.Sprintf("https://music.amazon.com/tracks/%s?musicTerritory=US", match[1]) - } - - if match := amazonTrackPath.FindStringSubmatch(amazonURL); len(match) > 1 { - return fmt.Sprintf("https://music.amazon.com/tracks/%s?musicTerritory=US", match[1]) - } - - return "" -} - -func normalizeDeezerTrackURL(rawURL string) string { - trackID, err := extractDeezerTrackID(rawURL) - if err != nil { - return strings.TrimSpace(rawURL) - } - return fmt.Sprintf("https://www.deezer.com/track/%s", trackID) -} - -func extractDeezerTrackID(rawURL string) (string, error) { - cleanURL := strings.TrimSpace(rawURL) - if cleanURL == "" { - return "", fmt.Errorf("empty Deezer URL") - } - - parts := strings.Split(cleanURL, "/track/") - if len(parts) < 2 { - return "", fmt.Errorf("could not extract track ID from Deezer URL: %s", rawURL) - } - - trackID := strings.Split(parts[1], "?")[0] - trackID = strings.Trim(trackID, "/ ") - if trackID == "" { - return "", fmt.Errorf("could not extract track ID from Deezer URL: %s", rawURL) - } - - return trackID, nil -} - -func hasAnySongLinkData(links *resolvedTrackLinks) bool { - if links == nil { - return false - } - return links.TidalURL != "" || links.AmazonURL != "" || links.DeezerURL != "" -} - -func firstISRCMatch(body string) string { - match := isrcPattern.FindStringSubmatch(strings.ToUpper(body)) - if len(match) < 2 { - return "" - } - return strings.TrimSpace(match[1]) -} diff --git a/backend/songstats.go b/backend/songstats.go deleted file mode 100644 index 7c16b8b..0000000 --- a/backend/songstats.go +++ /dev/null @@ -1,128 +0,0 @@ -package backend - -import ( - "encoding/json" - "fmt" - "html" - "io" - "net/http" - "regexp" - "strings" -) - -var songstatsScriptPattern = regexp.MustCompile(`(?is)]+type=["']application/ld\+json["'][^>]*>(.*?)`) - -func (s *SongLinkClient) populateLinksFromSongstats(links *resolvedTrackLinks, isrc string) error { - pageURL := fmt.Sprintf("https://songstats.com/%s?ref=ISRCFinder", strings.ToUpper(strings.TrimSpace(isrc))) - - req, err := http.NewRequest(http.MethodGet, pageURL, nil) - if err != nil { - return fmt.Errorf("failed to create request: %w", err) - } - req.Header.Set("User-Agent", songLinkUserAgent) - - resp, err := s.client.Do(req) - if err != nil { - return fmt.Errorf("failed to fetch Songstats page: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("Songstats returned status %d", resp.StatusCode) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("failed to read Songstats response: %w", err) - } - - matches := songstatsScriptPattern.FindAllStringSubmatch(string(body), -1) - if len(matches) == 0 { - return fmt.Errorf("Songstats JSON-LD not found") - } - - found := false - for _, match := range matches { - if len(match) < 2 { - continue - } - - scriptBody := strings.TrimSpace(html.UnescapeString(match[1])) - if scriptBody == "" { - continue - } - - var payload interface{} - if err := json.Unmarshal([]byte(scriptBody), &payload); err != nil { - continue - } - - before := *links - collectSongstatsLinks(payload, links) - if *links != before { - found = true - } - } - - if !found && !hasAnySongLinkData(links) { - return fmt.Errorf("no platform links found in Songstats") - } - - return nil -} - -func collectSongstatsLinks(value interface{}, links *resolvedTrackLinks) { - switch typed := value.(type) { - case map[string]interface{}: - if sameAs, ok := typed["sameAs"]; ok { - applySongstatsSameAs(sameAs, links) - } - for _, nested := range typed { - collectSongstatsLinks(nested, links) - } - case []interface{}: - for _, nested := range typed { - collectSongstatsLinks(nested, links) - } - } -} - -func applySongstatsSameAs(value interface{}, links *resolvedTrackLinks) { - switch typed := value.(type) { - case string: - assignSongstatsLink(typed, links) - case []interface{}: - for _, item := range typed { - if link, ok := item.(string); ok { - assignSongstatsLink(link, links) - } - } - } -} - -func assignSongstatsLink(rawLink string, links *resolvedTrackLinks) { - link := strings.TrimSpace(rawLink) - if link == "" { - return - } - - switch { - case strings.Contains(link, "listen.tidal.com/track"): - if links.TidalURL == "" { - links.TidalURL = link - fmt.Println("✓ Tidal URL found via Songstats") - } - case strings.Contains(link, "music.amazon.com"): - if links.AmazonURL == "" { - if normalized := normalizeAmazonMusicURL(link); normalized != "" { - links.AmazonURL = normalized - fmt.Println("✓ Amazon URL found via Songstats") - } - } - case strings.Contains(link, "deezer.com"): - if links.DeezerURL == "" { - links.DeezerURL = normalizeDeezerTrackURL(link) - fmt.Println("✓ Deezer URL found via Songstats") - } - } -} diff --git a/backend/soundplate.go b/backend/soundplate.go deleted file mode 100644 index bce9c94..0000000 --- a/backend/soundplate.go +++ /dev/null @@ -1,95 +0,0 @@ -package backend - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "strings" -) - -const ( - soundplateSpotifyAPIURL = "https://phpstack-822472-6184058.cloudwaysapps.com/api/spotify.php" - soundplateRefererURL = "https://phpstack-822472-6184058.cloudwaysapps.com/?" - soundplateUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36" -) - -type soundplateSpotifyResponse struct { - Name string `json:"name"` - Artist string `json:"artist"` - Album string `json:"album"` - AlbumType string `json:"album_type"` - ArtworkURL string `json:"artwork_url"` - ISRC string `json:"isrc"` - Year string `json:"year"` - SpotifyURL string `json:"spotify_url"` -} - -func (s *SongLinkClient) lookupSpotifyISRCViaSoundplate(spotifyTrackID string) (string, string, error) { - normalizedTrackID, err := extractSpotifyTrackID(spotifyTrackID) - if err != nil { - return "", "", err - } - - spotifyTrackURL := fmt.Sprintf("https://open.spotify.com/track/%s", normalizedTrackID) - query := url.Values{} - query.Set("q", spotifyTrackURL) - - req, err := http.NewRequest(http.MethodGet, soundplateSpotifyAPIURL+"?"+query.Encode(), nil) - if err != nil { - return "", "", fmt.Errorf("failed to create Soundplate ISRC request: %w", err) - } - req.Header.Set("User-Agent", soundplateUserAgent) - req.Header.Set("Accept", "*/*") - req.Header.Set("Referer", soundplateRefererURL) - req.Header.Set("Accept-Language", "en-US,en;q=0.9,id;q=0.8") - req.Header.Set("Sec-CH-UA", "\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Google Chrome\";v=\"146\"") - req.Header.Set("Sec-CH-UA-Mobile", "?0") - req.Header.Set("Sec-CH-UA-Platform", "\"Windows\"") - req.Header.Set("Sec-Fetch-Dest", "empty") - req.Header.Set("Sec-Fetch-Mode", "cors") - req.Header.Set("Sec-Fetch-Site", "same-origin") - req.Header.Set("Priority", "u=1, i") - - resp, err := s.client.Do(req) - if err != nil { - return "", "", fmt.Errorf("Soundplate ISRC request failed: %w", err) - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", "", fmt.Errorf("failed to read Soundplate ISRC response: %w", err) - } - - if resp.StatusCode != http.StatusOK { - bodyPreview := strings.TrimSpace(string(body)) - if len(bodyPreview) > 256 { - bodyPreview = bodyPreview[:256] - } - return "", "", fmt.Errorf("Soundplate ISRC returned status %d (%s)", resp.StatusCode, bodyPreview) - } - - var payload soundplateSpotifyResponse - if err := json.Unmarshal(body, &payload); err != nil { - return "", "", fmt.Errorf("failed to decode Soundplate ISRC response: %w", err) - } - - isrc := firstISRCMatch(payload.ISRC) - if isrc == "" { - isrc = firstISRCMatch(string(body)) - } - if isrc == "" { - return "", "", fmt.Errorf("ISRC missing in Soundplate response") - } - - resolvedTrackID := "" - if payload.SpotifyURL != "" { - if trackID, err := extractSpotifyTrackID(payload.SpotifyURL); err == nil { - resolvedTrackID = trackID - } - } - - return isrc, resolvedTrackID, nil -} diff --git a/backend/spotfetch.go b/backend/spotfetch.go deleted file mode 100644 index f168005..0000000 --- a/backend/spotfetch.go +++ /dev/null @@ -1,1753 +0,0 @@ -package backend - -import ( - "bytes" - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "html" - "io" - "net/http" - "regexp" - "strconv" - "strings" - "time" - - "sort" -) - -var SpotifyError = errors.New("spotify error") - -type SpotifyClient struct { - client *http.Client - accessToken string - clientToken string - clientID string - deviceID string - clientVersion string - cookies map[string]string -} - -func NewSpotifyClient() *SpotifyClient { - return &SpotifyClient{ - client: &http.Client{Timeout: 30 * time.Second}, - cookies: make(map[string]string), - } -} - -func (c *SpotifyClient) generateTOTP() (string, int, error) { - return generateSpotifyTOTP(time.Now()) -} - -func (c *SpotifyClient) getAccessToken() error { - totpCode, version, err := c.generateTOTP() - if err != nil { - return err - } - - req, err := http.NewRequest("GET", "https://open.spotify.com/api/token", nil) - if err != nil { - return err - } - - q := req.URL.Query() - q.Add("reason", "init") - q.Add("productType", "web-player") - q.Add("totp", totpCode) - q.Add("totpVer", strconv.Itoa(version)) - q.Add("totpServer", totpCode) - req.URL.RawQuery = q.Encode() - - req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36") - req.Header.Set("Content-Type", "application/json;charset=UTF-8") - - resp, err := c.client.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("%w: access token request failed: HTTP %d", SpotifyError, resp.StatusCode) - } - - var data map[string]interface{} - if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { - return err - } - - c.accessToken = getString(data, "accessToken") - c.clientID = getString(data, "clientId") - - for _, cookie := range resp.Cookies() { - if cookie.Name == "sp_t" { - c.deviceID = cookie.Value - } - c.cookies[cookie.Name] = cookie.Value - } - - return nil -} - -func (c *SpotifyClient) getSessionInfo() error { - req, err := http.NewRequest("GET", "https://open.spotify.com", nil) - if err != nil { - return err - } - - req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36") - - for name, value := range c.cookies { - req.AddCookie(&http.Cookie{Name: name, Value: value}) - } - - resp, err := c.client.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("%w: session initialization failed: HTTP %d", SpotifyError, resp.StatusCode) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - - re := regexp.MustCompile(``) - matches := re.FindStringSubmatch(string(body)) - if len(matches) > 1 { - decoded, err := base64.StdEncoding.DecodeString(matches[1]) - if err == nil { - var cfg map[string]interface{} - if json.Unmarshal(decoded, &cfg) == nil { - c.clientVersion = getString(cfg, "clientVersion") - } - } - } - - for _, cookie := range resp.Cookies() { - if cookie.Name == "sp_t" { - c.deviceID = cookie.Value - } - c.cookies[cookie.Name] = cookie.Value - } - - return nil -} - -func (c *SpotifyClient) getClientToken() error { - if c.clientID == "" || c.deviceID == "" || c.clientVersion == "" { - if err := c.getSessionInfo(); err != nil { - return err - } - if err := c.getAccessToken(); err != nil { - return err - } - } - - payload := map[string]interface{}{ - "client_data": map[string]interface{}{ - "client_version": c.clientVersion, - "client_id": c.clientID, - "js_sdk_data": map[string]interface{}{ - "device_brand": "unknown", - "device_model": "unknown", - "os": "windows", - "os_version": "NT 10.0", - "device_id": c.deviceID, - "device_type": "computer", - }, - }, - } - - jsonData, err := json.Marshal(payload) - if err != nil { - return err - } - - req, err := http.NewRequest("POST", "https://clienttoken.spotify.com/v1/clienttoken", bytes.NewBuffer(jsonData)) - if err != nil { - return err - } - - req.Header.Set("Authority", "clienttoken.spotify.com") - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Accept", "application/json") - req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36") - - resp, err := c.client.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("%w: client token request failed: HTTP %d", SpotifyError, resp.StatusCode) - } - - var data map[string]interface{} - if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { - return err - } - - if getString(data, "response_type") != "RESPONSE_GRANTED_TOKEN_RESPONSE" { - return fmt.Errorf("%w: invalid client token response type", SpotifyError) - } - - grantedToken := getMap(data, "granted_token") - c.clientToken = getString(grantedToken, "token") - - return nil -} - -func (c *SpotifyClient) Initialize() error { - if err := c.getSessionInfo(); err != nil { - return err - } - if err := c.getAccessToken(); err != nil { - return err - } - return c.getClientToken() -} - -func (c *SpotifyClient) Query(payload map[string]interface{}) (map[string]interface{}, error) { - if c.accessToken == "" || c.clientToken == "" { - if err := c.Initialize(); err != nil { - return nil, err - } - } - - jsonData, err := json.Marshal(payload) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", "https://api-partner.spotify.com/pathfinder/v2/query", bytes.NewBuffer(jsonData)) - if err != nil { - return nil, err - } - - req.Header.Set("Authorization", "Bearer "+c.accessToken) - req.Header.Set("Client-Token", c.clientToken) - req.Header.Set("Spotify-App-Version", c.clientVersion) - req.Header.Set("Content-Type", "application/json") - req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36") - - resp, err := c.client.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - if resp.StatusCode != 200 { - errorText := string(body) - if len(errorText) > 200 { - errorText = errorText[:200] - } - return nil, fmt.Errorf("%w: API query failed: HTTP %d | %s", SpotifyError, resp.StatusCode, errorText) - } - - var result map[string]interface{} - if err := json.Unmarshal(body, &result); err != nil { - return nil, err - } - - return result, nil -} - -func getString(m map[string]interface{}, key string) string { - if val, ok := m[key].(string); ok { - return val - } - return "" -} - -func getMap(m map[string]interface{}, key string) map[string]interface{} { - if val, ok := m[key].(map[string]interface{}); ok { - return val - } - return make(map[string]interface{}) -} - -func getSlice(m map[string]interface{}, key string) []interface{} { - if val, ok := m[key].([]interface{}); ok { - return val - } - return nil -} - -func getFloat64(m map[string]interface{}, key string) float64 { - if val, ok := m[key].(float64); ok { - return val - } - return 0 -} - -func getInt(m map[string]interface{}, key string) int { - if val, ok := m[key].(int); ok { - return val - } - if val, ok := m[key].(float64); ok { - return int(val) - } - return 0 -} - -func getBool(m map[string]interface{}, key string) bool { - if val, ok := m[key].(bool); ok { - return val - } - return false -} - -func extractArtists(artistsData map[string]interface{}) []map[string]interface{} { - items := getSlice(artistsData, "items") - - artists := []map[string]interface{}{} - for _, item := range items { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - profile := getMap(itemMap, "profile") - artistInfo := map[string]interface{}{ - "name": getString(profile, "name"), - } - artists = append(artists, artistInfo) - } - return artists -} - -func extractCoverImage(coverData map[string]interface{}) map[string]interface{} { - if len(coverData) == 0 { - return nil - } - - var sources []interface{} - if srcs, ok := coverData["sources"].([]interface{}); ok { - sources = srcs - } else if squareImg, ok := coverData["squareCoverImage"].(map[string]interface{}); ok { - if img, ok := squareImg["image"].(map[string]interface{}); ok { - if data, ok := img["data"].(map[string]interface{}); ok { - if srcs, ok := data["sources"].([]interface{}); ok { - sources = srcs - } - } - } - } - - if len(sources) == 0 { - return nil - } - - type sourceInfo struct { - url string - width float64 - height float64 - } - - filteredSources := []sourceInfo{} - for _, s := range sources { - sMap, ok := s.(map[string]interface{}) - if !ok { - continue - } - url := getString(sMap, "url") - if url == "" { - continue - } - - width := getFloat64(sMap, "width") - if width == 0 { - width = getFloat64(sMap, "maxWidth") - } - height := getFloat64(sMap, "height") - if height == 0 { - height = getFloat64(sMap, "maxHeight") - } - - if (width > 64 && height > 64) || (width == 0 && height == 0 && url != "") { - filteredSources = append(filteredSources, sourceInfo{url: url, width: width, height: height}) - } - } - - if len(filteredSources) == 0 { - return nil - } - - sort.Slice(filteredSources, func(i, j int) bool { - return filteredSources[i].width < filteredSources[j].width - }) - - var smallURL, mediumURL, imageID, fallbackURL string - - for _, source := range filteredSources { - if source.width == 300 { - smallURL = source.url - } else if source.width == 640 { - mediumURL = source.url - } else if source.width == 0 { - fallbackURL = source.url - } - - if imageID == "" && source.url != "" { - if strings.Contains(source.url, "ab67616d0000b273") { - parts := strings.Split(source.url, "ab67616d0000b273") - if len(parts) > 1 { - imageID = parts[len(parts)-1] - } - } else if strings.Contains(source.url, "ab67616d00001e02") { - parts := strings.Split(source.url, "ab67616d00001e02") - if len(parts) > 1 { - imageID = parts[len(parts)-1] - } - } else if strings.Contains(source.url, "/image/") { - parts := strings.Split(source.url, "/image/") - if len(parts) > 1 { - imagePart := strings.Split(parts[len(parts)-1], "?")[0] - if len(imagePart) > 20 { - prefixes := []string{"ab67616d0000b273", "ab67616d00001e02", "ab67616d00004851"} - for _, prefix := range prefixes { - if strings.Contains(imagePart, prefix) { - subParts := strings.Split(imagePart, prefix) - if len(subParts) > 1 { - imageID = subParts[len(subParts)-1] - break - } - } - } - } - } - } - } - } - - largeURL := "" - if imageID != "" { - largeURL = "https://i.scdn.co/image/ab67616d000082c1" + imageID - } - - result := map[string]interface{}{} - if smallURL != "" { - result["small"] = smallURL - } - if mediumURL != "" { - result["medium"] = mediumURL - } - if largeURL != "" { - result["large"] = largeURL - } - - if len(result) == 0 && fallbackURL != "" { - result["small"] = fallbackURL - result["medium"] = fallbackURL - result["large"] = fallbackURL - } - - if len(result) == 0 { - return nil - } - return result -} - -func extractDuration(ms float64) map[string]interface{} { - totalSeconds := int(ms) / 1000 - minutes := totalSeconds / 60 - seconds := totalSeconds % 60 - return map[string]interface{}{ - "formatted": fmt.Sprintf("%d:%02d", minutes, seconds), - } -} - -func FilterTrack(data map[string]interface{}, separator string, albumFetchData ...map[string]interface{}) map[string]interface{} { - dataMap := getMap(data, "data") - trackData := getMap(dataMap, "trackUnion") - if len(trackData) == 0 { - return make(map[string]interface{}) - } - - var albumFetchDataMap map[string]interface{} - if len(albumFetchData) > 0 { - albumFetchDataMap = albumFetchData[0] - } - - artists := extractArtists(getMap(trackData, "artists")) - - if len(artists) == 0 { - artists = []map[string]interface{}{} - firstArtistItems := getSlice(getMap(trackData, "firstArtist"), "items") - for _, item := range firstArtistItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - if profile, exists := itemMap["profile"]; exists { - profileMap, ok := profile.(map[string]interface{}) - if ok { - artistInfo := map[string]interface{}{ - "name": getString(profileMap, "name"), - } - artists = append(artists, artistInfo) - } - } - } - - otherArtistItems := getSlice(getMap(trackData, "otherArtists"), "items") - for _, item := range otherArtistItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - if profile, exists := itemMap["profile"]; exists { - profileMap, ok := profile.(map[string]interface{}) - if ok { - artistInfo := map[string]interface{}{ - "name": getString(profileMap, "name"), - } - artists = append(artists, artistInfo) - } - } - } - } - - if len(artists) == 0 { - albumData := getMap(trackData, "albumOfTrack") - if len(albumData) > 0 { - artists = extractArtists(getMap(albumData, "artists")) - } - } - - albumData := getMap(trackData, "albumOfTrack") - var albumInfo map[string]interface{} - copyrightInfo := []map[string]interface{}{} - discInfo := map[string]interface{}{ - "discNumber": getFloat64(trackData, "discNumber"), - "totalDiscs": nil, - } - - if len(albumData) > 0 { - copyrightData := getMap(albumData, "copyright") - if len(copyrightData) > 0 { - copyrightItems := getSlice(copyrightData, "items") - if len(copyrightItems) > 0 { - for _, item := range copyrightItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - if getString(itemMap, "type") != "P" { - copyrightInfo = append(copyrightInfo, map[string]interface{}{ - "text": getString(itemMap, "text"), - }) - } - } - } - } - - tracksData := getMap(albumData, "tracks") - if len(tracksData) > 0 { - discNumbers := make(map[int]bool) - trackItems := getSlice(tracksData, "items") - if len(trackItems) > 0 { - for _, item := range trackItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - trackItem := getMap(itemMap, "track") - if len(trackItem) > 0 { - discNum := int(getFloat64(trackItem, "discNumber")) - if discNum == 0 { - discNum = 1 - } - discNumbers[discNum] = true - } - } - } - if len(discNumbers) > 0 { - maxDisc := 1 - for discNum := range discNumbers { - if discNum > maxDisc { - maxDisc = discNum - } - } - discInfo["totalDiscs"] = maxDisc - } - } - - dateInfo := getMap(albumData, "date") - releaseDate := getString(dateInfo, "isoString") - var releaseYear interface{} - if releaseDate == "" && len(dateInfo) > 0 { - yearStr := getString(dateInfo, "year") - monthStr := getString(dateInfo, "month") - dayStr := getString(dateInfo, "day") - if yearStr != "" { - year, err := strconv.Atoi(yearStr) - if err == nil { - releaseYear = year - if monthStr != "" && dayStr != "" { - month, _ := strconv.Atoi(monthStr) - day, _ := strconv.Atoi(dayStr) - releaseDate = fmt.Sprintf("%s-%02d-%02d", yearStr, month, day) - } else { - releaseDate = yearStr - } - } - } - } else if releaseDate != "" { - parts := strings.Split(releaseDate, "T") - if len(parts) > 0 { - releaseDate = parts[0] - } else { - parts = strings.Split(releaseDate, " ") - if len(parts) > 0 { - releaseDate = parts[0] - } - } - dateParts := strings.Split(releaseDate, "-") - if len(dateParts) > 0 && dateParts[0] != "" { - year, err := strconv.Atoi(dateParts[0]) - if err == nil { - releaseYear = year - } - } - } - - tracksTotalCount := float64(0) - if len(tracksData) > 0 { - tracksTotalCount = getFloat64(tracksData, "totalCount") - } - - albumID := getString(albumData, "id") - if albumID == "" { - albumURI := getString(albumData, "uri") - if strings.Contains(albumURI, ":") { - parts := strings.Split(albumURI, ":") - albumID = parts[len(parts)-1] - } - } - - albumArtistsString := "" - albumLabel := "" - if len(albumFetchDataMap) > 0 { - albumUnionData := getMap(getMap(albumFetchDataMap, "data"), "albumUnion") - if len(albumUnionData) > 0 { - albumArtists := extractArtists(getMap(albumUnionData, "artists")) - if len(albumArtists) > 0 { - albumArtistNames := []string{} - for _, artist := range albumArtists { - albumArtistNames = append(albumArtistNames, getString(artist, "name")) - } - albumArtistsString = strings.Join(albumArtistNames, separator) - } - if albumArtistsString == "" { - albumArtistsString = getString(albumUnionData, "artists") - } - albumLabel = getString(albumUnionData, "label") - } - } - - if albumArtistsString == "" { - albumArtists := extractArtists(getMap(albumData, "artists")) - if len(albumArtists) > 0 { - albumArtistNames := []string{} - for _, artist := range albumArtists { - albumArtistNames = append(albumArtistNames, getString(artist, "name")) - } - albumArtistsString = strings.Join(albumArtistNames, separator) - } - } - - albumInfo = map[string]interface{}{ - "id": albumID, - "name": getString(albumData, "name"), - "released": releaseDate, - "year": releaseYear, - "tracks": int(tracksTotalCount), - } - - if albumArtistsString != "" { - albumInfo["artists"] = albumArtistsString - } - - if albumLabel != "" { - albumInfo["label"] = albumLabel - } - } - - cover := extractCoverImage(getMap(trackData, "visualIdentity")) - if cover == nil && len(albumData) > 0 { - cover = extractCoverImage(getMap(albumData, "coverArt")) - } - - durationMs := getFloat64(getMap(trackData, "duration"), "totalMilliseconds") - durationObj := extractDuration(durationMs) - durationString := getString(durationObj, "formatted") - - artistNames := []string{} - for _, artist := range artists { - artistNames = append(artistNames, getString(artist, "name")) - } - artistsString := strings.Join(artistNames, separator) - - copyrightTexts := []string{} - for _, item := range copyrightInfo { - copyrightTexts = append(copyrightTexts, getString(item, "text")) - } - copyrightString := strings.Join(copyrightTexts, GetSeparator()) - - discNumber := int(getFloat64(trackData, "discNumber")) - if discNumber == 0 { - discNumber = 1 - } - - maxDiscFromAlbum := 0 - totalDiscsFromAlbum := 0 - - if len(albumFetchData) > 0 && albumFetchData[0] != nil { - albumUnion := getMap(getMap(albumFetchData[0], "data"), "albumUnion") - if len(albumUnion) > 0 { - discsData := getMap(albumUnion, "discs") - if len(discsData) > 0 { - totalDiscsFromAlbum = int(getFloat64(discsData, "totalCount")) - } - - albumTracks := getMap(albumUnion, "tracks") - if len(albumTracks) > 0 { - albumTrackItems := getSlice(albumTracks, "items") - currentTrackID := getString(trackData, "id") - for idx, item := range albumTrackItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - trackItem := getMap(itemMap, "track") - if len(trackItem) > 0 { - dNum := int(getFloat64(trackItem, "discNumber")) - if dNum > maxDiscFromAlbum { - maxDiscFromAlbum = dNum - } - - trackURI := getString(trackItem, "uri") - if strings.Contains(trackURI, currentTrackID) || getString(trackItem, "id") == currentTrackID { - if dNum > 0 { - discNumber = dNum - } - } - - trackNum := int(getFloat64(trackData, "trackNumber")) - itemTrackNum := idx + 1 - if trackNum == itemTrackNum && dNum > 0 { - } - } - } - } - } - } - - totalDiscs := 1 - if totalDiscsFromAlbum > 0 { - totalDiscs = totalDiscsFromAlbum - } else if maxDiscFromAlbum > 0 { - totalDiscs = maxDiscFromAlbum - } else if discInfo["totalDiscs"] != nil { - totalDiscs = discInfo["totalDiscs"].(int) - } - - contentRating := getMap(trackData, "contentRating") - isExplicit := getString(contentRating, "label") == "EXPLICIT" - - filtered := map[string]interface{}{ - "id": getString(trackData, "id"), - "name": getString(trackData, "name"), - "artists": artistsString, - "album": albumInfo, - "duration": durationString, - "track": int(getFloat64(trackData, "trackNumber")), - "disc": discNumber, - "discs": totalDiscs, - "copyright": copyrightString, - "plays": getString(trackData, "playcount"), - "cover": cover, - "is_explicit": isExplicit, - } - - return filtered -} - -func FilterAlbum(data map[string]interface{}, separator string) map[string]interface{} { - dataMap := getMap(data, "data") - albumData := getMap(dataMap, "albumUnion") - if len(albumData) == 0 { - return make(map[string]interface{}) - } - - artists := extractArtists(getMap(albumData, "artists")) - artistNames := []string{} - for _, artist := range artists { - artistNames = append(artistNames, getString(artist, "name")) - } - albumArtistsString := strings.Join(artistNames, separator) - - coverObj := extractCoverImage(getMap(albumData, "coverArt")) - var cover interface{} - if coverObj != nil { - - cover = getString(coverObj, "small") - if cover == "" { - cover = getString(coverObj, "medium") - } - if cover == "" { - cover = getString(coverObj, "large") - } - } - - tracks := []map[string]interface{}{} - tracksData := getMap(albumData, "tracksV2") - trackItems := getSlice(tracksData, "items") - if trackItems != nil { - for _, item := range trackItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - track := getMap(itemMap, "track") - if len(track) == 0 { - continue - } - - artistsData := getMap(track, "artists") - trackArtists := extractArtists(artistsData) - trackDurationMs := getFloat64(getMap(track, "duration"), "totalMilliseconds") - durationObj := extractDuration(trackDurationMs) - durationString := getString(durationObj, "formatted") - - trackArtistNames := []string{} - artistIDs := []string{} - - artistItems := getSlice(artistsData, "items") - if artistItems != nil { - for _, artistItem := range artistItems { - artistItemMap, ok := artistItem.(map[string]interface{}) - if !ok { - continue - } - artistURI := getString(artistItemMap, "uri") - if artistURI != "" && strings.Contains(artistURI, ":") { - parts := strings.Split(artistURI, ":") - if len(parts) > 0 { - artistID := parts[len(parts)-1] - if artistID != "" { - artistIDs = append(artistIDs, artistID) - } - } - } - } - } - - for _, artist := range trackArtists { - trackArtistNames = append(trackArtistNames, getString(artist, "name")) - } - trackArtistsString := strings.Join(trackArtistNames, separator) - - trackURI := getString(track, "uri") - trackID := "" - if strings.Contains(trackURI, ":") { - parts := strings.Split(trackURI, ":") - trackID = parts[len(parts)-1] - } - - contentRating := getMap(track, "contentRating") - isExplicit := getString(contentRating, "label") == "EXPLICIT" - - discNumber := int(getFloat64(track, "discNumber")) - if discNumber == 0 { - discNumber = 1 - } - - trackInfo := map[string]interface{}{ - "id": trackID, - "name": getString(track, "name"), - "artists": trackArtistsString, - "artistIds": artistIDs, - "duration": durationString, - "plays": getString(track, "playcount"), - "is_explicit": isExplicit, - "disc_number": discNumber, - } - tracks = append(tracks, trackInfo) - } - } - - dateInfo := getMap(albumData, "date") - releaseDate := getString(dateInfo, "isoString") - if releaseDate != "" && strings.Contains(releaseDate, "T") { - parts := strings.Split(releaseDate, "T") - releaseDate = parts[0] - } - - albumURI := getString(albumData, "uri") - albumID := "" - if strings.Contains(albumURI, ":") { - parts := strings.Split(albumURI, ":") - albumID = parts[len(parts)-1] - } - - totalDiscs := 1 - discsData := getMap(albumData, "discs") - if len(discsData) > 0 { - totalDiscs = int(getFloat64(discsData, "totalCount")) - } - - filtered := map[string]interface{}{ - "id": albumID, - "name": getString(albumData, "name"), - "artists": albumArtistsString, - "cover": cover, - "releaseDate": releaseDate, - "count": len(tracks), - "tracks": tracks, - "discs": map[string]interface{}{ - "totalCount": totalDiscs, - }, - "label": getString(albumData, "label"), - } - - return filtered -} - -func FilterPlaylist(data map[string]interface{}, separator string) map[string]interface{} { - dataMap := getMap(data, "data") - playlistData := getMap(dataMap, "playlistV2") - if len(playlistData) == 0 { - return make(map[string]interface{}) - } - - ownerData := getMap(getMap(playlistData, "ownerV2"), "data") - var ownerInfo map[string]interface{} - if len(ownerData) > 0 { - var avatarURL interface{} - avatarData := getMap(ownerData, "avatar") - if len(avatarData) > 0 { - sources := getSlice(avatarData, "sources") - if len(sources) > 0 { - if firstSource, ok := sources[0].(map[string]interface{}); ok { - avatarURL = getString(firstSource, "url") - } - } - } - - ownerInfo = map[string]interface{}{ - "name": getString(ownerData, "name"), - "avatar": avatarURL, - } - } - - imagesData := getMap(playlistData, "images") - if len(imagesData) == 0 { - imagesData = getMap(playlistData, "imagesV2") - } - var cover interface{} - if len(imagesData) > 0 { - imageItems := getSlice(imagesData, "items") - if imageItems != nil && len(imageItems) > 0 { - if firstImage, ok := imageItems[0].(map[string]interface{}); ok { - firstSources := getSlice(firstImage, "sources") - if firstSources != nil && len(firstSources) > 0 { - if firstSource, ok := firstSources[0].(map[string]interface{}); ok { - sourceURL := getString(firstSource, "url") - if sourceURL != "" { - cover = sourceURL - } - } - } - } - } - if cover == nil { - imageSources := getSlice(imagesData, "sources") - if imageSources != nil && len(imageSources) > 0 { - if firstSource, ok := imageSources[0].(map[string]interface{}); ok { - sourceURL := getString(firstSource, "url") - if sourceURL != "" { - cover = sourceURL - } - } - } - } - } - - tracks := []map[string]interface{}{} - content := getMap(playlistData, "content") - contentItems := getSlice(content, "items") - if contentItems != nil { - for _, item := range contentItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - trackData := getMap(getMap(itemMap, "itemV2"), "data") - if len(trackData) == 0 { - continue - } - - var rank interface{} - var status interface{} - attributes := getSlice(itemMap, "attributes") - if attributes != nil { - for _, attr := range attributes { - attrMap, ok := attr.(map[string]interface{}) - if !ok { - continue - } - key := getString(attrMap, "key") - if key == "rank" { - rank = getString(attrMap, "value") - } else if key == "status" { - status = getString(attrMap, "value") - } - } - } - - artistsData := getMap(trackData, "artists") - trackArtists := extractArtists(artistsData) - trackArtistNames := []string{} - artistIDs := []string{} - - artistItems := getSlice(artistsData, "items") - if artistItems != nil { - for _, artistItem := range artistItems { - artistItemMap, ok := artistItem.(map[string]interface{}) - if !ok { - continue - } - artistURI := getString(artistItemMap, "uri") - if artistURI != "" && strings.Contains(artistURI, ":") { - parts := strings.Split(artistURI, ":") - if len(parts) > 0 { - artistID := parts[len(parts)-1] - if artistID != "" { - artistIDs = append(artistIDs, artistID) - } - } - } - } - } - - for _, artist := range trackArtists { - trackArtistNames = append(trackArtistNames, getString(artist, "name")) - } - artistsString := strings.Join(trackArtistNames, separator) - - trackDurationMs := getFloat64(getMap(trackData, "trackDuration"), "totalMilliseconds") - durationObj := extractDuration(trackDurationMs) - durationString := getString(durationObj, "formatted") - - trackURI := getString(trackData, "uri") - trackID := getString(trackData, "id") - if trackID == "" { - if strings.Contains(trackURI, ":") { - parts := strings.Split(trackURI, ":") - trackID = parts[len(parts)-1] - } - } - - albumData := getMap(trackData, "albumOfTrack") - albumName := "" - albumID := "" - albumArtistsString := "" - var trackCover interface{} - - if len(albumData) > 0 { - albumName = getString(albumData, "name") - albumURI := getString(albumData, "uri") - if strings.Contains(albumURI, ":") { - parts := strings.Split(albumURI, ":") - albumID = parts[len(parts)-1] - } - coverObj := extractCoverImage(getMap(albumData, "coverArt")) - if coverObj != nil { - - trackCover = getString(coverObj, "small") - if trackCover == "" { - trackCover = getString(coverObj, "medium") - } - if trackCover == "" { - trackCover = getString(coverObj, "large") - } - } - - albumArtists := extractArtists(getMap(albumData, "artists")) - if len(albumArtists) > 0 { - albumArtistNames := []string{} - for _, artist := range albumArtists { - albumArtistNames = append(albumArtistNames, getString(artist, "name")) - } - albumArtistsString = strings.Join(albumArtistNames, separator) - } - } - - contentRating := getMap(trackData, "contentRating") - isExplicit := getString(contentRating, "label") == "EXPLICIT" - - trackName := getString(trackData, "name") - if trackName == "" { - continue - } - - trackInfo := map[string]interface{}{ - "id": trackID, - "cover": trackCover, - "title": trackName, - "artist": artistsString, - "artistIds": artistIDs, - "plays": rank, - "status": status, - "album": albumName, - "albumArtist": albumArtistsString, - "albumId": albumID, - "duration": durationString, - "is_explicit": isExplicit, - "disc_number": int(getFloat64(trackData, "discNumber")), - } - tracks = append(tracks, trackInfo) - } - } - - followersData, exists := playlistData["followers"] - var followersCount interface{} - if exists { - if followersMap, ok := followersData.(map[string]interface{}); ok { - followersCount = getFloat64(followersMap, "totalCount") - } else if count, ok := followersData.(float64); ok { - followersCount = count - } else if count, ok := followersData.(int); ok { - followersCount = float64(count) - } else { - followersCount = float64(0) - } - } else { - followersCount = float64(0) - } - - playlistURI := getString(playlistData, "uri") - playlistID := "" - if strings.Contains(playlistURI, ":") { - parts := strings.Split(playlistURI, ":") - playlistID = parts[len(parts)-1] - } - - totalCount := getFloat64(content, "totalCount") - count := len(tracks) - if totalCount > 0 { - count = int(totalCount) - } - - filtered := map[string]interface{}{ - "id": playlistID, - "name": getString(playlistData, "name"), - "description": getString(playlistData, "description"), - "owner": ownerInfo, - "cover": cover, - "count": count, - "tracks": tracks, - "followers": followersCount, - } - - return filtered -} - -func extractRelease(release map[string]interface{}) map[string]interface{} { - if len(release) == 0 { - return nil - } - - dateInfo := getMap(release, "date") - releaseDate := getString(dateInfo, "isoString") - if releaseDate == "" && len(dateInfo) > 0 { - yearStr := getString(dateInfo, "year") - monthStr := getString(dateInfo, "month") - dayStr := getString(dateInfo, "day") - if yearStr != "" { - if monthStr != "" && dayStr != "" { - month, _ := strconv.Atoi(monthStr) - day, _ := strconv.Atoi(dayStr) - releaseDate = fmt.Sprintf("%s-%02d-%02d", yearStr, month, day) - } else { - releaseDate = yearStr - } - } - } else if releaseDate != "" && strings.Contains(releaseDate, "T") { - parts := strings.Split(releaseDate, "T") - releaseDate = parts[0] - } - - coverObj := extractCoverImage(getMap(release, "coverArt")) - var cover interface{} - if coverObj != nil { - cover = getString(coverObj, "medium") - } - - releaseID := getString(release, "id") - if releaseID == "" { - releaseURI := getString(release, "uri") - if strings.Contains(releaseURI, ":") { - parts := strings.Split(releaseURI, ":") - releaseID = parts[len(parts)-1] - } - } - - var year interface{} - if yearVal, exists := dateInfo["year"]; exists { - year = yearVal - } - - var totalTracks int - tracksInfo := getMap(release, "tracks") - if tracksInfo != nil { - totalTracks = int(getFloat64(tracksInfo, "totalCount")) - } - - return map[string]interface{}{ - "id": releaseID, - "name": getString(release, "name"), - "cover": cover, - "date": releaseDate, - "year": year, - "total_tracks": totalTracks, - "type": getString(release, "type"), - } -} - -func extractDiscographyItems(itemsData map[string]interface{}) []map[string]interface{} { - items := []map[string]interface{}{} - dataItems := getSlice(itemsData, "items") - if dataItems != nil { - for _, item := range dataItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - releases := getMap(itemMap, "releases") - var release map[string]interface{} - if len(releases) > 0 { - releaseItems := getSlice(releases, "items") - if releaseItems != nil && len(releaseItems) > 0 { - if releaseMap, ok := releaseItems[0].(map[string]interface{}); ok { - release = releaseMap - } - } - } else { - release = getMap(itemMap, "album") - } - - if len(release) > 0 { - extracted := extractRelease(release) - if extracted != nil { - items = append(items, extracted) - } - } - } - } - return items -} - -func stripHTMLTags(s string) string { - re := regexp.MustCompile(`(?s)<[^>]*>`) - return re.ReplaceAllString(s, "") -} - -func FilterArtist(data map[string]interface{}, separator string) map[string]interface{} { - dataMap := getMap(data, "data") - artistData := getMap(dataMap, "artistUnion") - if len(artistData) == 0 { - return make(map[string]interface{}) - } - - profileRaw := getMap(artistData, "profile") - profile := make(map[string]interface{}) - if len(profileRaw) > 0 { - if biography, exists := profileRaw["biography"]; exists { - biographyMap, ok := biography.(map[string]interface{}) - if ok { - biographyText := getString(biographyMap, "text") - if biographyText != "" { - profile["biography"] = html.UnescapeString(stripHTMLTags(biographyText)) - } - } - } - if _, exists := profileRaw["name"]; exists { - profile["name"] = getString(profileRaw, "name") - } - if _, exists := profileRaw["verified"]; exists { - profile["verified"] = getBool(profileRaw, "verified") - } - } - - headerImageData := getMap(artistData, "headerImage") - var headerImage interface{} - if len(headerImageData) > 0 { - headerData := getMap(headerImageData, "data") - if len(headerData) > 0 { - sources := getSlice(headerData, "sources") - if sources != nil && len(sources) > 0 { - if firstSource, ok := sources[0].(map[string]interface{}); ok { - headerImage = getString(firstSource, "url") - } - } - } - } - - statsRaw := getMap(artistData, "stats") - stats := make(map[string]interface{}) - if len(statsRaw) > 0 { - if _, exists := statsRaw["followers"]; exists { - stats["followers"] = getFloat64(statsRaw, "followers") - } - if _, exists := statsRaw["monthlyListeners"]; exists { - stats["listeners"] = getFloat64(statsRaw, "monthlyListeners") - } - if _, exists := statsRaw["worldRank"]; exists { - stats["rank"] = getFloat64(statsRaw, "worldRank") - } - } - - discography := getMap(artistData, "discography") - discographyResult := make(map[string]interface{}) - - allData := getMap(discography, "all") - if len(allData) > 0 { - discographyResult["all"] = extractDiscographyItems(allData) - if totalCount, exists := allData["totalCount"]; exists { - var total float64 - if tc, ok := totalCount.(float64); ok { - total = tc - } else if tc, ok := totalCount.(int); ok { - total = float64(tc) - } else if tc, ok := totalCount.(int64); ok { - total = float64(tc) - } - discographyResult["total"] = total - } - } - - visualsData := getMap(artistData, "visuals") - galleryData := getMap(visualsData, "gallery") - gallery := []interface{}{} - if len(galleryData) > 0 { - galleryItems := getSlice(galleryData, "items") - if galleryItems != nil { - for _, item := range galleryItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - sources := getSlice(itemMap, "sources") - if sources != nil && len(sources) > 0 { - if firstSource, ok := sources[0].(map[string]interface{}); ok { - galleryURL := getString(firstSource, "url") - if galleryURL != "" { - gallery = append(gallery, galleryURL) - } - } - } - } - } - } - - avatarObj := extractCoverImage(getMap(visualsData, "avatarImage")) - var avatar interface{} - if avatarObj != nil { - if mediumURL, ok := avatarObj["medium"].(string); ok && mediumURL != "" { - avatar = mediumURL - } else if smallURL, ok := avatarObj["small"].(string); ok && smallURL != "" { - avatar = smallURL - } - } - - artistURI := getString(artistData, "uri") - artistID := "" - if strings.Contains(artistURI, ":") { - parts := strings.Split(artistURI, ":") - artistID = parts[len(parts)-1] - } - - filtered := map[string]interface{}{ - "id": artistID, - "name": getString(profile, "name"), - "profile": profile, - "avatar": avatar, - "header": headerImage, - "stats": stats, - "gallery": gallery, - "discography": discographyResult, - } - - return filtered -} - -func FilterSearch(data map[string]interface{}, separator string) map[string]interface{} { - dataMap := getMap(data, "data") - searchData := getMap(dataMap, "searchV2") - if len(searchData) == 0 { - return make(map[string]interface{}) - } - - results := map[string]interface{}{ - "tracks": []map[string]interface{}{}, - "albums": []map[string]interface{}{}, - "artists": []map[string]interface{}{}, - "playlists": []map[string]interface{}{}, - } - - tracksData := getMap(searchData, "tracksV2") - if len(tracksData) == 0 { - tracksData = getMap(searchData, "tracks") - } - trackItems := getSlice(tracksData, "items") - if trackItems != nil { - for _, item := range trackItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - var track map[string]interface{} - if itemData, exists := itemMap["item"]; exists { - itemDataMap, ok := itemData.(map[string]interface{}) - if ok { - track = getMap(itemDataMap, "data") - } - } else if trackData, exists := itemMap["track"]; exists { - if trackMap, ok := trackData.(map[string]interface{}); ok { - track = trackMap - } - } - - if len(track) == 0 { - continue - } - - trackArtists := extractArtists(getMap(track, "artists")) - trackDurationMs := getFloat64(getMap(track, "duration"), "totalMilliseconds") - if trackDurationMs == 0 { - trackDurationMs = getFloat64(getMap(track, "trackDuration"), "totalMilliseconds") - } - trackDuration := extractDuration(trackDurationMs) - - albumData := getMap(track, "albumOfTrack") - var albumInfo map[string]interface{} - if len(albumData) > 0 { - albumURI := getString(albumData, "uri") - albumID := getString(albumData, "id") - if albumID == "" { - if strings.Contains(albumURI, ":") { - parts := strings.Split(albumURI, ":") - albumID = parts[len(parts)-1] - } - } - albumInfo = map[string]interface{}{ - "name": getString(albumData, "name"), - "uri": albumURI, - "id": albumID, - } - } - - trackURI := getString(track, "uri") - trackID := getString(track, "id") - if trackID == "" { - if strings.Contains(trackURI, ":") { - parts := strings.Split(trackURI, ":") - trackID = parts[len(parts)-1] - } - } - - coverObj := extractCoverImage(getMap(albumData, "coverArt")) - var cover interface{} - if coverObj != nil { - cover = getString(coverObj, "medium") - } - - trackName := getString(track, "name") - if trackName == "" { - continue - } - - trackArtistNames := []string{} - for _, artist := range trackArtists { - trackArtistNames = append(trackArtistNames, getString(artist, "name")) - } - trackArtistsString := strings.Join(trackArtistNames, separator) - - durationString := getString(trackDuration, "formatted") - - albumName := "" - if albumInfo != nil { - albumName = getString(albumInfo, "name") - } - - contentRating := getMap(track, "contentRating") - isExplicit := getString(contentRating, "label") == "EXPLICIT" - - trackResults := results["tracks"].([]map[string]interface{}) - trackResults = append(trackResults, map[string]interface{}{ - "id": trackID, - "name": trackName, - "artists": trackArtistsString, - "album": albumName, - "duration": durationString, - "cover": cover, - "is_explicit": isExplicit, - }) - results["tracks"] = trackResults - } - } - - albumsData := getMap(searchData, "albumsV2") - if len(albumsData) == 0 { - albumsData = getMap(searchData, "albums") - } - albumItems := getSlice(albumsData, "items") - if albumItems != nil { - for _, item := range albumItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - var album map[string]interface{} - if itemData, exists := itemMap["data"]; exists { - if albumMap, ok := itemData.(map[string]interface{}); ok { - album = albumMap - } - } else if albumData, exists := itemMap["album"]; exists { - if albumMap, ok := albumData.(map[string]interface{}); ok { - album = albumMap - } - } - - if len(album) == 0 { - continue - } - - albumArtists := extractArtists(getMap(album, "artists")) - albumURI := getString(album, "uri") - albumID := getString(album, "id") - if albumID == "" { - if strings.Contains(albumURI, ":") { - parts := strings.Split(albumURI, ":") - albumID = parts[len(parts)-1] - } - } - - coverObj := extractCoverImage(getMap(album, "coverArt")) - var cover interface{} - if coverObj != nil { - cover = getString(coverObj, "medium") - } - - albumArtistNames := []string{} - for _, artist := range albumArtists { - albumArtistNames = append(albumArtistNames, getString(artist, "name")) - } - albumArtistsString := strings.Join(albumArtistNames, separator) - - dateInfo := getMap(album, "date") - var year interface{} - if len(dateInfo) > 0 { - if yearVal, exists := dateInfo["year"]; exists { - year = yearVal - } - } - - albumName := getString(album, "name") - if albumName == "" || albumArtistsString == "" { - continue - } - - albumResult := map[string]interface{}{ - "id": albumID, - "name": albumName, - "artists": albumArtistsString, - "cover": cover, - } - - if year != nil { - albumResult["year"] = year - } - - albumResults := results["albums"].([]map[string]interface{}) - albumResults = append(albumResults, albumResult) - results["albums"] = albumResults - } - } - - artistsData := getMap(searchData, "artistsV2") - if len(artistsData) == 0 { - artistsData = getMap(searchData, "artists") - } - artistItems := getSlice(artistsData, "items") - if artistItems != nil { - for _, item := range artistItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - var artist map[string]interface{} - if itemData, exists := itemMap["data"]; exists { - if artistMap, ok := itemData.(map[string]interface{}); ok { - artist = artistMap - } - } else if artistData, exists := itemMap["artist"]; exists { - if artistMap, ok := artistData.(map[string]interface{}); ok { - artist = artistMap - } - } - - if len(artist) == 0 { - continue - } - - artistURI := getString(artist, "uri") - artistID := "" - if strings.Contains(artistURI, ":") { - parts := strings.Split(artistURI, ":") - artistID = parts[len(parts)-1] - } - - coverObj := extractCoverImage(getMap(artist, "visualIdentity")) - if coverObj == nil { - visuals := getMap(artist, "visuals") - if len(visuals) > 0 { - coverObj = extractCoverImage(getMap(visuals, "avatarImage")) - } - } - - var cover interface{} - if coverObj != nil { - cover = getString(coverObj, "medium") - } - - artistName := getString(getMap(artist, "profile"), "name") - if artistName == "" { - artistName = getString(artist, "name") - } - - if artistName == "" { - continue - } - - artistResults := results["artists"].([]map[string]interface{}) - artistResults = append(artistResults, map[string]interface{}{ - "id": artistID, - "name": artistName, - "cover": cover, - }) - results["artists"] = artistResults - } - } - - playlistsData := getMap(searchData, "playlistsV2") - if len(playlistsData) == 0 { - playlistsData = getMap(searchData, "playlists") - } - playlistItems := getSlice(playlistsData, "items") - if playlistItems != nil { - for _, item := range playlistItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - var playlist map[string]interface{} - if itemData, exists := itemMap["data"]; exists { - if playlistMap, ok := itemData.(map[string]interface{}); ok { - playlist = playlistMap - } - } else if playlistData, exists := itemMap["playlist"]; exists { - if playlistMap, ok := playlistData.(map[string]interface{}); ok { - playlist = playlistMap - } - } - - if len(playlist) == 0 { - continue - } - - playlistURI := getString(playlist, "uri") - playlistID := "" - if strings.Contains(playlistURI, ":") { - parts := strings.Split(playlistURI, ":") - playlistID = parts[len(parts)-1] - } - - playlistImages := getMap(playlist, "images") - if len(playlistImages) == 0 { - playlistImages = getMap(playlist, "imagesV2") - } - var playlistCoverObj map[string]interface{} - if len(playlistImages) > 0 { - imageItems := getSlice(playlistImages, "items") - if imageItems != nil && len(imageItems) > 0 { - if firstImage, ok := imageItems[0].(map[string]interface{}); ok { - firstSources := getSlice(firstImage, "sources") - if firstSources != nil { - playlistCoverObj = extractCoverImage(map[string]interface{}{"sources": firstSources}) - } - } - } - if playlistCoverObj == nil { - playlistCoverObj = extractCoverImage(playlistImages) - } - } - - var playlistCover interface{} - if playlistCoverObj != nil { - playlistCover = getString(playlistCoverObj, "medium") - } - - ownerData := getMap(getMap(playlist, "ownerV2"), "data") - ownerName := getString(ownerData, "name") - - playlistName := getString(playlist, "name") - if playlistName == "" { - continue - } - - playlistResult := map[string]interface{}{ - "id": playlistID, - "name": playlistName, - "cover": playlistCover, - } - - if ownerName != "" { - playlistResult["owner"] = ownerName - } - - playlistResults := results["playlists"].([]map[string]interface{}) - playlistResults = append(playlistResults, playlistResult) - results["playlists"] = playlistResults - } - } - - tracks := results["tracks"].([]map[string]interface{}) - albums := results["albums"].([]map[string]interface{}) - artists := results["artists"].([]map[string]interface{}) - playlists := results["playlists"].([]map[string]interface{}) - - return map[string]interface{}{ - "results": results, - "totalResults": map[string]interface{}{ - "tracks": len(tracks), - "albums": len(albums), - "artists": len(artists), - "playlists": len(playlists), - }, - } -} diff --git a/backend/spotify_metadata.go b/backend/spotify_metadata.go deleted file mode 100644 index 35129ef..0000000 --- a/backend/spotify_metadata.go +++ /dev/null @@ -1,1774 +0,0 @@ -package backend - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "net/url" - "regexp" - "strconv" - "strings" - "time" -) - -var ( - errInvalidSpotifyURL = errors.New("invalid or unsupported Spotify URL") -) - -type MetadataCallback func(data interface{}) - -type SpotifyMetadataClient struct { - httpClient *http.Client - Separator string -} - -func NewSpotifyMetadataClient() *SpotifyMetadataClient { - return &SpotifyMetadataClient{ - httpClient: &http.Client{Timeout: 30 * time.Second}, - Separator: ", ", - } -} - -type TrackMetadata struct { - SpotifyID string `json:"spotify_id,omitempty"` - Artists string `json:"artists"` - Name string `json:"name"` - AlbumName string `json:"album_name"` - AlbumArtist string `json:"album_artist,omitempty"` - DurationMS int `json:"duration_ms"` - Images string `json:"images"` - ReleaseDate string `json:"release_date"` - TrackNumber int `json:"track_number"` - TotalTracks int `json:"total_tracks,omitempty"` - DiscNumber int `json:"disc_number,omitempty"` - TotalDiscs int `json:"total_discs,omitempty"` - ExternalURL string `json:"external_urls"` - AlbumID string `json:"album_id,omitempty"` - AlbumURL string `json:"album_url,omitempty"` - ArtistID string `json:"artist_id,omitempty"` - ArtistURL string `json:"artist_url,omitempty"` - ArtistsData []ArtistSimple `json:"artists_data,omitempty"` - UPC string `json:"upc,omitempty"` - Copyright string `json:"copyright,omitempty"` - Publisher string `json:"publisher,omitempty"` - Composer string `json:"composer,omitempty"` - Plays string `json:"plays,omitempty"` - PreviewURL string `json:"preview_url,omitempty"` - IsExplicit bool `json:"is_explicit,omitempty"` -} - -type ArtistSimple struct { - ID string `json:"id"` - Name string `json:"name"` - ExternalURL string `json:"external_urls"` -} - -type AlbumTrackMetadata struct { - SpotifyID string `json:"spotify_id,omitempty"` - Artists string `json:"artists"` - Name string `json:"name"` - AlbumName string `json:"album_name"` - AlbumArtist string `json:"album_artist,omitempty"` - DurationMS int `json:"duration_ms"` - Images string `json:"images"` - ReleaseDate string `json:"release_date"` - TrackNumber int `json:"track_number"` - TotalTracks int `json:"total_tracks,omitempty"` - DiscNumber int `json:"disc_number,omitempty"` - TotalDiscs int `json:"total_discs,omitempty"` - ExternalURL string `json:"external_urls"` - AlbumType string `json:"album_type,omitempty"` - AlbumID string `json:"album_id,omitempty"` - AlbumURL string `json:"album_url,omitempty"` - ArtistID string `json:"artist_id,omitempty"` - ArtistURL string `json:"artist_url,omitempty"` - ArtistsData []ArtistSimple `json:"artists_data,omitempty"` - UPC string `json:"upc,omitempty"` - Plays string `json:"plays,omitempty"` - Status string `json:"status,omitempty"` - PreviewURL string `json:"preview_url,omitempty"` - IsExplicit bool `json:"is_explicit,omitempty"` -} - -type TrackResponse struct { - Track TrackMetadata `json:"track"` -} - -type AlbumInfoMetadata struct { - TotalTracks int `json:"total_tracks"` - Name string `json:"name"` - ReleaseDate string `json:"release_date"` - Artists string `json:"artists"` - Images string `json:"images"` - UPC string `json:"upc,omitempty"` - Batch string `json:"batch,omitempty"` - ArtistID string `json:"artist_id,omitempty"` - ArtistURL string `json:"artist_url,omitempty"` -} - -type AlbumResponsePayload struct { - AlbumInfo AlbumInfoMetadata `json:"album_info"` - TrackList []AlbumTrackMetadata `json:"track_list"` -} - -type PlaylistInfoMetadata struct { - Tracks struct { - Total int `json:"total"` - } `json:"tracks"` - Followers struct { - Total int `json:"total"` - } `json:"followers"` - Owner struct { - DisplayName string `json:"display_name"` - Name string `json:"name"` - Images string `json:"images"` - } `json:"owner"` - Cover string `json:"cover,omitempty"` - Description string `json:"description,omitempty"` - Batch string `json:"batch,omitempty"` -} - -type PlaylistResponsePayload struct { - PlaylistInfo PlaylistInfoMetadata `json:"playlist_info"` - TrackList []AlbumTrackMetadata `json:"track_list"` -} - -type ArtistInfoMetadata struct { - Name string `json:"name"` - Followers int `json:"followers"` - Genres []string `json:"genres"` - Images string `json:"images"` - Header string `json:"header,omitempty"` - Gallery []string `json:"gallery,omitempty"` - ExternalURL string `json:"external_urls"` - DiscographyType string `json:"discography_type"` - TotalAlbums int `json:"total_albums"` - Biography string `json:"biography,omitempty"` - Verified bool `json:"verified,omitempty"` - Listeners int `json:"listeners,omitempty"` - Rank int `json:"rank,omitempty"` - Batch string `json:"batch,omitempty"` -} - -type DiscographyAlbumMetadata struct { - ID string `json:"id"` - Name string `json:"name"` - AlbumType string `json:"album_type"` - ReleaseDate string `json:"release_date"` - TotalTracks int `json:"total_tracks"` - Artists string `json:"artists"` - Images string `json:"images"` - ExternalURL string `json:"external_urls"` -} - -type ArtistDiscographyPayload struct { - ArtistInfo ArtistInfoMetadata `json:"artist_info"` - AlbumList []DiscographyAlbumMetadata `json:"album_list"` - TrackList []AlbumTrackMetadata `json:"track_list"` -} - -type ArtistResponsePayload struct { - Artist struct { - Name string `json:"name"` - Followers int `json:"followers"` - Genres []string `json:"genres"` - Images string `json:"images"` - ExternalURL string `json:"external_urls"` - Popularity int `json:"popularity"` - } `json:"artist"` -} - -type spotifyURI struct { - Type string - ID string - DiscographyGroup string -} - -type apiTrackResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Artists string `json:"artists"` - ArtistIds []string `json:"artistIds,omitempty"` - UPC string `json:"upc,omitempty"` - Duration string `json:"duration"` - Track int `json:"track"` - Disc int `json:"disc"` - Discs int `json:"discs"` - Copyright string `json:"copyright"` - Composer string `json:"composer,omitempty"` - Plays string `json:"plays"` - Album struct { - ID string `json:"id"` - Name string `json:"name"` - Released string `json:"released"` - Year int `json:"year"` - Tracks int `json:"tracks"` - Artists string `json:"artists"` - Label string `json:"label"` - } `json:"album"` - Cover struct { - Small string `json:"small"` - Medium string `json:"medium"` - Large string `json:"large"` - } `json:"cover"` - IsExplicit bool `json:"is_explicit"` -} - -type apiAlbumResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Artists string `json:"artists"` - Cover string `json:"cover"` - ReleaseDate string `json:"releaseDate"` - UPC string `json:"upc,omitempty"` - Count int `json:"count"` - Label string `json:"label"` - Discs struct { - TotalCount int `json:"totalCount"` - } `json:"discs"` - Tracks []struct { - ID string `json:"id"` - Name string `json:"name"` - Artists string `json:"artists"` - ArtistIds []string `json:"artistIds"` - Duration string `json:"duration"` - Plays string `json:"plays"` - UPC string `json:"upc,omitempty"` - IsExplicit bool `json:"is_explicit"` - DiscNumber int `json:"disc_number"` - } `json:"tracks"` -} - -type apiPlaylistResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Owner struct { - Name string `json:"name"` - Avatar string `json:"avatar"` - } `json:"owner"` - Cover string `json:"cover"` - Count int `json:"count"` - Followers int `json:"followers"` - Tracks []struct { - ID string `json:"id"` - Cover string `json:"cover"` - Title string `json:"title"` - Artist string `json:"artist"` - ArtistIds []string `json:"artistIds"` - Plays string `json:"plays"` - Status string `json:"status"` - Album string `json:"album"` - AlbumArtist string `json:"albumArtist"` - AlbumID string `json:"albumId"` - UPC string `json:"upc,omitempty"` - Duration string `json:"duration"` - IsExplicit bool `json:"is_explicit"` - DiscNumber int `json:"disc_number"` - } `json:"tracks"` -} - -type apiArtistResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Profile struct { - Biography string `json:"biography"` - Name string `json:"name"` - Verified bool `json:"verified"` - } `json:"profile"` - Avatar string `json:"avatar"` - Header string `json:"header"` - Stats struct { - Followers int `json:"followers"` - Listeners int `json:"listeners"` - Rank int `json:"rank"` - } `json:"stats"` - Gallery []string `json:"gallery"` - Discography struct { - All []struct { - ID string `json:"id"` - Name string `json:"name"` - Cover string `json:"cover"` - Date string `json:"date"` - Year int `json:"year"` - TotalTracks int `json:"total_tracks"` - Type string `json:"type"` - } `json:"all"` - Total int `json:"total"` - } `json:"discography"` -} - -type apiSearchResponse struct { - Results struct { - Tracks []struct { - ID string `json:"id"` - Name string `json:"name"` - Artists string `json:"artists"` - Album string `json:"album"` - Duration string `json:"duration"` - Cover string `json:"cover"` - IsExplicit bool `json:"is_explicit"` - } `json:"tracks"` - Albums []struct { - ID string `json:"id"` - Name string `json:"name"` - Artists string `json:"artists"` - Cover string `json:"cover"` - Year int `json:"year"` - } `json:"albums"` - Artists []struct { - ID string `json:"id"` - Name string `json:"name"` - Cover string `json:"cover"` - } `json:"artists"` - Playlists []struct { - ID string `json:"id"` - Name string `json:"name"` - Cover string `json:"cover"` - Owner string `json:"owner"` - } `json:"playlists"` - } `json:"results"` - TotalResults struct { - Tracks int `json:"tracks"` - Albums int `json:"albums"` - Artists int `json:"artists"` - Playlists int `json:"playlists"` - } `json:"totalResults"` -} - -type SearchResult struct { - ID string `json:"id"` - Name string `json:"name"` - Type string `json:"type"` - Artists string `json:"artists,omitempty"` - AlbumName string `json:"album_name,omitempty"` - Images string `json:"images"` - ReleaseDate string `json:"release_date,omitempty"` - ExternalURL string `json:"external_urls"` - Duration int `json:"duration_ms,omitempty"` - TotalTracks int `json:"total_tracks,omitempty"` - Owner string `json:"owner,omitempty"` - IsExplicit bool `json:"is_explicit,omitempty"` -} - -type SearchResponse struct { - Tracks []SearchResult `json:"tracks"` - Albums []SearchResult `json:"albums"` - Artists []SearchResult `json:"artists"` - Playlists []SearchResult `json:"playlists"` -} - -func GetFilteredSpotifyData(ctx context.Context, spotifyURL string, batch bool, delay time.Duration, separator string, callback MetadataCallback) (interface{}, error) { - client := NewSpotifyMetadataClient() - if separator != "" { - client.Separator = separator - } - return client.GetFilteredData(ctx, spotifyURL, batch, delay, callback) -} - -func (c *SpotifyMetadataClient) GetFilteredData(ctx context.Context, spotifyURL string, batch bool, delay time.Duration, callback MetadataCallback) (interface{}, error) { - parsed, err := parseSpotifyURI(spotifyURL) - if err != nil { - return nil, err - } - - raw, err := c.getRawSpotifyData(ctx, parsed, batch, delay, callback) - if err != nil { - return nil, err - } - - return c.processSpotifyData(ctx, raw, callback) -} - -func (c *SpotifyMetadataClient) getRawSpotifyData(ctx context.Context, parsed spotifyURI, batch bool, delay time.Duration, callback MetadataCallback) (interface{}, error) { - switch parsed.Type { - case "playlist": - return c.fetchPlaylist(ctx, parsed.ID, callback) - case "album": - return c.fetchAlbum(ctx, parsed.ID, callback) - case "track": - return c.fetchTrack(ctx, parsed.ID) - case "artist_discography": - return c.fetchArtistDiscography(ctx, parsed, callback) - case "artist": - - discographyParsed := spotifyURI{Type: "artist_discography", ID: parsed.ID, DiscographyGroup: "all"} - return c.fetchArtistDiscography(ctx, discographyParsed, callback) - default: - return nil, fmt.Errorf("unsupported Spotify type: %s", parsed.Type) - } -} - -func (c *SpotifyMetadataClient) processSpotifyData(ctx context.Context, raw interface{}, callback MetadataCallback) (interface{}, error) { - switch payload := raw.(type) { - case *apiPlaylistResponse: - return c.formatPlaylistData(payload, callback), nil - case *apiAlbumResponse: - return c.formatAlbumData(payload, callback) - case *apiTrackResponse: - return c.formatTrackData(payload), nil - case *apiArtistResponse: - return c.formatArtistDiscographyData(ctx, payload, callback) - default: - return nil, errors.New("unknown raw payload type") - } -} - -func (c *SpotifyMetadataClient) fetchTrack(ctx context.Context, trackID string) (*apiTrackResponse, error) { - client := NewSpotifyClient() - if err := client.Initialize(); err != nil { - return nil, fmt.Errorf("failed to initialize spotify client: %w", err) - } - - payload := map[string]interface{}{ - "variables": map[string]interface{}{ - "uri": fmt.Sprintf("spotify:track:%s", trackID), - }, - "operationName": "getTrack", - "extensions": map[string]interface{}{ - "persistedQuery": map[string]interface{}{ - "version": 1, - "sha256Hash": "612585ae06ba435ad26369870deaae23b5c8800a256cd8a57e08eddc25a37294", - }, - }, - } - - data, err := client.Query(payload) - if err != nil { - return nil, fmt.Errorf("failed to query track: %w", err) - } - - var albumFetchData map[string]interface{} - if trackData, ok := data["data"].(map[string]interface{}); ok { - if trackUnion, ok := trackData["trackUnion"].(map[string]interface{}); ok { - if albumOfTrack, ok := trackUnion["albumOfTrack"].(map[string]interface{}); ok { - albumID := "" - if id, ok := albumOfTrack["id"].(string); ok && id != "" { - albumID = id - } else if uri, ok := albumOfTrack["uri"].(string); ok && uri != "" { - if strings.Contains(uri, ":") { - parts := strings.Split(uri, ":") - if len(parts) > 0 { - albumID = parts[len(parts)-1] - } - } - } - - if albumID != "" { - - albumResponse, err := c.fetchAlbumWithClient(ctx, client, albumID, nil) - if err == nil && albumResponse != nil { - - albumJSON, _ := json.Marshal(albumResponse) - var albumMap map[string]interface{} - json.Unmarshal(albumJSON, &albumMap) - - tracksItems := []interface{}{} - if albumMap["tracks"] != nil { - if trackList, ok := albumMap["tracks"].([]interface{}); ok { - for _, t := range trackList { - if trackMap, ok := t.(map[string]interface{}); ok { - tracksItems = append(tracksItems, map[string]interface{}{ - "track": map[string]interface{}{ - "discNumber": trackMap["disc_number"], - "id": trackMap["id"], - "uri": fmt.Sprintf("spotify:track:%s", trackMap["id"]), - }, - }) - } - } - } - } - - albumFetchData = map[string]interface{}{ - "data": map[string]interface{}{ - "albumUnion": map[string]interface{}{ - "discs": map[string]interface{}{ - "totalCount": albumResponse.Discs.TotalCount, - }, - "tracks": map[string]interface{}{ - "items": tracksItems, - "totalCount": albumResponse.Count, - }, - "artists": albumResponse.Artists, - "label": albumResponse.Label, - }, - }, - } - } - } - } - } - } - - filteredData := FilterTrack(data, c.Separator, albumFetchData) - composer, composerErr := c.fetchTrackComposerWithClient(ctx, client, trackID) - if composerErr == nil && composer != "" { - filteredData["composer"] = composer - } - - jsonData, err := json.Marshal(filteredData) - if err != nil { - return nil, fmt.Errorf("failed to marshal filtered data: %w", err) - } - - var result apiTrackResponse - if err := json.Unmarshal(jsonData, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal to apiTrackResponse: %w", err) - } - - if result.ID != "" { - if identifiers, err := GetSpotifyTrackIdentifiersDirect(result.ID); err == nil || identifiers.UPC != "" { - if identifiers.UPC != "" { - result.UPC = identifiers.UPC - } - } - } - - return &result, nil -} - -func collectTrackCreditNamesByRole(items []interface{}, role string) []string { - role = strings.TrimSpace(role) - if role == "" || len(items) == 0 { - return nil - } - - seen := make(map[string]struct{}, len(items)) - names := make([]string, 0, len(items)) - for _, item := range items { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - - if !strings.EqualFold(strings.TrimSpace(getString(itemMap, "role")), role) { - continue - } - - name := strings.TrimSpace(getString(itemMap, "name")) - if name == "" { - continue - } - if _, exists := seen[name]; exists { - continue - } - - seen[name] = struct{}{} - names = append(names, name) - } - - return names -} - -func (c *SpotifyMetadataClient) fetchTrackComposerWithClient(ctx context.Context, client *SpotifyClient, trackID string) (string, error) { - _ = ctx - - payload := map[string]interface{}{ - "variables": map[string]interface{}{ - "trackUri": fmt.Sprintf("spotify:track:%s", trackID), - "contributorsLimit": 100, - "contributorsOffset": 0, - }, - "operationName": "queryTrackCreditsModal", - "extensions": map[string]interface{}{ - "persistedQuery": map[string]interface{}{ - "version": 1, - "sha256Hash": "e2ca40d46cf1fde36562261ccec754f23fb31b561877252e9fe0d6834aabb84b", - }, - }, - } - - data, err := client.Query(payload) - if err != nil { - return "", fmt.Errorf("failed to query track credits: %w", err) - } - - creditItems := getSlice( - getMap( - getMap( - getMap( - getMap(data, "data"), - "trackUnion", - ), - "creditsTrait", - ), - "contributors", - ), - "items", - ) - - composerNames := collectTrackCreditNamesByRole(creditItems, "Composer") - if len(composerNames) == 0 { - return "", nil - } - - separator := strings.TrimSpace(c.Separator) - if separator == "" { - separator = ", " - } - - return strings.Join(composerNames, separator), nil -} - -func (c *SpotifyMetadataClient) fetchAlbum(ctx context.Context, albumID string, callback MetadataCallback) (*apiAlbumResponse, error) { - client := NewSpotifyClient() - if err := client.Initialize(); err != nil { - return nil, fmt.Errorf("failed to initialize spotify client: %w", err) - } - return c.fetchAlbumWithClient(ctx, client, albumID, callback) -} - -func (c *SpotifyMetadataClient) fetchAlbumWithClient(ctx context.Context, client *SpotifyClient, albumID string, callback MetadataCallback) (*apiAlbumResponse, error) { - - allItems := []interface{}{} - offset := 0 - limit := 1000 - var totalCount interface{} - var data map[string]interface{} - - for { - payload := map[string]interface{}{ - "variables": map[string]interface{}{ - "uri": fmt.Sprintf("spotify:album:%s", albumID), - "locale": "", - "offset": offset, - "limit": limit, - }, - "operationName": "getAlbum", - "extensions": map[string]interface{}{ - "persistedQuery": map[string]interface{}{ - "version": 1, - "sha256Hash": "b9bfabef66ed756e5e13f68a942deb60bd4125ec1f1be8cc42769dc0259b4b10", - }, - }, - } - - response, err := client.Query(payload) - if err != nil { - return nil, fmt.Errorf("failed to query album: %w", err) - } - - if data == nil { - data = response - if callback != nil { - filtered := FilterAlbum(data, c.Separator) - jsonData, _ := json.Marshal(filtered) - var result apiAlbumResponse - if json.Unmarshal(jsonData, &result) == nil { - formatted, _ := c.formatAlbumData(&result, nil) - callback(formatted) - } - } - } - - albumData := getMap(getMap(response, "data"), "albumUnion") - tracksData := getMap(albumData, "tracksV2") - items := getSlice(tracksData, "items") - - if items == nil || len(items) == 0 { - break - } - - allItems = append(allItems, items...) - - if totalCount == nil { - if tc, ok := tracksData["totalCount"].(float64); ok { - totalCount = int(tc) - } else { - totalCount = len(items) - } - } - - tcInt := 0 - if tc, ok := totalCount.(int); ok { - tcInt = tc - } else if tc, ok := totalCount.(float64); ok { - tcInt = int(tc) - } - - if len(allItems) >= tcInt || len(items) < limit { - break - } - - offset += limit - } - - if data != nil && len(allItems) > 0 { - dataMap := getMap(data, "data") - albumUnion := getMap(dataMap, "albumUnion") - tracksV2 := getMap(albumUnion, "tracksV2") - tracksV2["items"] = allItems - tracksV2["totalCount"] = len(allItems) - } - - filteredData := FilterAlbum(data, c.Separator) - - jsonData, err := json.Marshal(filteredData) - if err != nil { - return nil, fmt.Errorf("failed to marshal filtered data: %w", err) - } - - var result apiAlbumResponse - if err := json.Unmarshal(jsonData, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal to apiAlbumResponse: %w", err) - } - - if result.ID != "" { - if upc, err := lookupSpotifyAlbumUPC(result.ID); err == nil && strings.TrimSpace(upc) != "" { - result.UPC = upc - for i := range result.Tracks { - if strings.TrimSpace(result.Tracks[i].UPC) == "" { - result.Tracks[i].UPC = upc - } - } - } - } - - return &result, nil -} - -func (c *SpotifyMetadataClient) fetchPlaylist(ctx context.Context, playlistID string, callback MetadataCallback) (*apiPlaylistResponse, error) { - client := NewSpotifyClient() - if err := client.Initialize(); err != nil { - return nil, fmt.Errorf("failed to initialize spotify client: %w", err) - } - - allItems := []interface{}{} - offset := 0 - limit := 1000 - var totalCount interface{} - var data map[string]interface{} - - for { - payload := map[string]interface{}{ - "variables": map[string]interface{}{ - "uri": fmt.Sprintf("spotify:playlist:%s", playlistID), - "offset": offset, - "limit": limit, - "enableWatchFeedEntrypoint": false, - }, - "operationName": "fetchPlaylist", - "extensions": map[string]interface{}{ - "persistedQuery": map[string]interface{}{ - "version": 1, - "sha256Hash": "bb67e0af06e8d6f52b531f97468ee4acd44cd0f82b988e15c2ea47b1148efc77", - }, - }, - } - - response, err := client.Query(payload) - if err != nil { - return nil, fmt.Errorf("failed to query playlist: %w", err) - } - - if data == nil { - data = response - if callback != nil { - filtered := FilterPlaylist(data, c.Separator) - jsonData, _ := json.Marshal(filtered) - var result apiPlaylistResponse - if json.Unmarshal(jsonData, &result) == nil { - formatted := c.formatPlaylistData(&result, nil) - callback(formatted) - } - } - } - - playlistData := getMap(getMap(response, "data"), "playlistV2") - content := getMap(playlistData, "content") - items := getSlice(content, "items") - - if items == nil || len(items) == 0 { - break - } - - allItems = append(allItems, items...) - - if totalCount == nil { - if tc, ok := content["totalCount"].(float64); ok { - totalCount = int(tc) - } else { - totalCount = len(items) - } - } - - tcInt := 0 - if tc, ok := totalCount.(int); ok { - tcInt = tc - } else if tc, ok := totalCount.(float64); ok { - tcInt = int(tc) - } - - if len(allItems) >= tcInt || len(items) < limit { - break - } - - offset += limit - } - - if data != nil && len(allItems) > 0 { - dataMap := getMap(data, "data") - playlistV2 := getMap(dataMap, "playlistV2") - content := getMap(playlistV2, "content") - content["items"] = allItems - content["totalCount"] = len(allItems) - } - - filteredData := FilterPlaylist(data, c.Separator) - - jsonData, err := json.Marshal(filteredData) - if err != nil { - return nil, fmt.Errorf("failed to marshal filtered data: %w", err) - } - - var result apiPlaylistResponse - if err := json.Unmarshal(jsonData, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal to apiPlaylistResponse: %w", err) - } - - return &result, nil -} - -func (c *SpotifyMetadataClient) fetchArtistDiscography(ctx context.Context, parsed spotifyURI, callback MetadataCallback) (*apiArtistResponse, error) { - client := NewSpotifyClient() - if err := client.Initialize(); err != nil { - return nil, fmt.Errorf("failed to initialize spotify client: %w", err) - } - - overviewPayload := map[string]interface{}{ - "variables": map[string]interface{}{ - "uri": fmt.Sprintf("spotify:artist:%s", parsed.ID), - "locale": "", - }, - "operationName": "queryArtistOverview", - "extensions": map[string]interface{}{ - "persistedQuery": map[string]interface{}{ - "version": 1, - "sha256Hash": "446130b4a0aa6522a686aafccddb0ae849165b5e0436fd802f96e0243617b5d8", - }, - }, - } - - data, err := client.Query(overviewPayload) - if err != nil { - return nil, fmt.Errorf("failed to query artist overview: %w", err) - } - - if callback != nil { - filtered := FilterArtist(data, c.Separator) - jsonData, _ := json.Marshal(filtered) - var result apiArtistResponse - if json.Unmarshal(jsonData, &result) == nil { - formatted, _ := c.formatArtistDiscographyData(ctx, &result, nil) - callback(formatted) - } - } - - allDiscographyItems := []interface{}{} - offset := 0 - limit := 50 - var totalCount interface{} - - for { - discographyPayload := map[string]interface{}{ - "variables": map[string]interface{}{ - "uri": fmt.Sprintf("spotify:artist:%s", parsed.ID), - "offset": offset, - "limit": limit, - "order": "DATE_DESC", - }, - "operationName": "queryArtistDiscographyAll", - "extensions": map[string]interface{}{ - "persistedQuery": map[string]interface{}{ - "version": 1, - "sha256Hash": "5e07d323febb57b4a56a42abbf781490e58764aa45feb6e3dc0591564fc56599", - }, - }, - } - - response, err := client.Query(discographyPayload) - if err != nil { - break - } - - discographyData := getMap(getMap(getMap(response, "data"), "artistUnion"), "discography") - allData := getMap(discographyData, "all") - items := getSlice(allData, "items") - - if items == nil || len(items) == 0 { - break - } - - allDiscographyItems = append(allDiscographyItems, items...) - - if totalCount == nil { - if tc, ok := allData["totalCount"].(float64); ok { - totalCount = int(tc) - } else { - totalCount = len(items) - } - } - - tcInt := 0 - if tc, ok := totalCount.(int); ok { - tcInt = tc - } else if tc, ok := totalCount.(float64); ok { - tcInt = int(tc) - } - - if len(allDiscographyItems) >= tcInt || len(items) < limit { - break - } - - offset += limit - - select { - case <-ctx.Done(): - return nil, ctx.Err() - default: - } - } - - albumsItems := []interface{}{} - compilationsItems := []interface{}{} - singlesItems := []interface{}{} - - for _, item := range allDiscographyItems { - itemMap, ok := item.(map[string]interface{}) - if !ok { - continue - } - - releases := getMap(itemMap, "releases") - releaseItems := getSlice(releases, "items") - var release map[string]interface{} - if len(releaseItems) > 0 { - if r, ok := releaseItems[0].(map[string]interface{}); ok { - release = r - } - } - - if release != nil { - releaseType := getString(release, "type") - switch releaseType { - case "ALBUM": - albumsItems = append(albumsItems, item) - case "COMPILATION": - compilationsItems = append(compilationsItems, item) - case "SINGLE": - singlesItems = append(singlesItems, item) - default: - singlesItems = append(singlesItems, item) - } - } - } - - if len(allDiscographyItems) > 0 { - dataMap := getMap(data, "data") - artistUnion := getMap(dataMap, "artistUnion") - discographyMap := getMap(artistUnion, "discography") - - if len(albumsItems) > 0 { - discographyMap["albums"] = map[string]interface{}{ - "items": albumsItems, - "totalCount": len(albumsItems), - } - } - if len(compilationsItems) > 0 { - discographyMap["compilations"] = map[string]interface{}{ - "items": compilationsItems, - "totalCount": len(compilationsItems), - } - } - if len(singlesItems) > 0 { - discographyMap["singles"] = map[string]interface{}{ - "items": singlesItems, - "totalCount": len(singlesItems), - } - } - - discographyMap["all"] = map[string]interface{}{ - "items": allDiscographyItems, - "totalCount": len(allDiscographyItems), - } - } - - filteredData := FilterArtist(data, c.Separator) - - jsonData, err := json.Marshal(filteredData) - if err != nil { - return nil, fmt.Errorf("failed to marshal filtered data: %w", err) - } - - var result apiArtistResponse - if err := json.Unmarshal(jsonData, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal to apiArtistResponse: %w", err) - } - - return &result, nil -} - -func (c *SpotifyMetadataClient) formatTrackData(raw *apiTrackResponse) TrackResponse { - durationMS := parseDuration(raw.Duration) - - externalURL := fmt.Sprintf("https://open.spotify.com/track/%s", raw.ID) - albumID := strings.TrimSpace(raw.Album.ID) - albumURL := "" - if albumID != "" { - albumURL = fmt.Sprintf("https://open.spotify.com/album/%s", albumID) - } - artistID := "" - artistURL := "" - artistsData := make([]ArtistSimple, 0, len(raw.ArtistIds)) - for index, id := range raw.ArtistIds { - trimmedID := strings.TrimSpace(id) - if trimmedID == "" { - continue - } - if artistID == "" { - artistID = trimmedID - artistURL = fmt.Sprintf("https://open.spotify.com/artist/%s", trimmedID) - } - artistName := "" - artistNames := splitAndCleanArtists(raw.Artists) - if index < len(artistNames) { - artistName = artistNames[index] - } - artistsData = append(artistsData, ArtistSimple{ - ID: trimmedID, - Name: artistName, - ExternalURL: fmt.Sprintf("https://open.spotify.com/artist/%s", trimmedID), - }) - } - - coverURL := raw.Cover.Small - if coverURL == "" { - coverURL = raw.Cover.Medium - } - if coverURL == "" { - coverURL = raw.Cover.Large - } - - releaseDate := raw.Album.Released - if releaseDate == "" && raw.Album.Year > 0 { - releaseDate = fmt.Sprintf("%d", raw.Album.Year) - } - trackMetadata := TrackMetadata{ - SpotifyID: raw.ID, - Artists: raw.Artists, - Name: raw.Name, - AlbumName: raw.Album.Name, - AlbumArtist: raw.Album.Artists, - DurationMS: durationMS, - Images: coverURL, - ReleaseDate: releaseDate, - TrackNumber: raw.Track, - TotalTracks: raw.Album.Tracks, - DiscNumber: raw.Disc, - TotalDiscs: raw.Discs, - ExternalURL: externalURL, - AlbumID: albumID, - AlbumURL: albumURL, - ArtistID: artistID, - ArtistURL: artistURL, - ArtistsData: artistsData, - UPC: raw.UPC, - Copyright: raw.Copyright, - Publisher: raw.Album.Label, - Composer: raw.Composer, - Plays: raw.Plays, - IsExplicit: raw.IsExplicit, - } - - return TrackResponse{ - Track: trackMetadata, - } -} - -func (c *SpotifyMetadataClient) formatAlbumData(raw *apiAlbumResponse, callback MetadataCallback) (*AlbumResponsePayload, error) { - var artistID, artistURL string - for _, item := range raw.Tracks { - if len(item.ArtistIds) == 0 { - continue - } - candidate := strings.TrimSpace(item.ArtistIds[0]) - if candidate == "" { - continue - } - artistID = candidate - artistURL = fmt.Sprintf("https://open.spotify.com/artist/%s", candidate) - break - } - - info := AlbumInfoMetadata{ - TotalTracks: raw.Count, - Name: raw.Name, - ReleaseDate: raw.ReleaseDate, - Artists: raw.Artists, - Images: raw.Cover, - UPC: raw.UPC, - ArtistID: artistID, - ArtistURL: artistURL, - } - - if callback != nil { - callback(AlbumResponsePayload{ - AlbumInfo: info, - TrackList: []AlbumTrackMetadata{}, - }) - } - - tracks := make([]AlbumTrackMetadata, 0, len(raw.Tracks)) - for idx, item := range raw.Tracks { - durationMS := parseDuration(item.Duration) - trackNumber := idx + 1 - trackUPC := strings.TrimSpace(item.UPC) - if trackUPC == "" { - trackUPC = strings.TrimSpace(raw.UPC) - } - - var artistID, artistURL string - if len(item.ArtistIds) > 0 { - artistID = item.ArtistIds[0] - artistURL = fmt.Sprintf("https://open.spotify.com/artist/%s", artistID) - } - - artistsData := make([]ArtistSimple, 0, len(item.ArtistIds)) - for _, id := range item.ArtistIds { - artistsData = append(artistsData, ArtistSimple{ - ID: id, - Name: "", - ExternalURL: fmt.Sprintf("https://open.spotify.com/artist/%s", id), - }) - } - - tracks = append(tracks, AlbumTrackMetadata{ - SpotifyID: item.ID, - Artists: item.Artists, - Name: item.Name, - AlbumName: raw.Name, - AlbumArtist: raw.Artists, - DurationMS: durationMS, - Images: raw.Cover, - ReleaseDate: raw.ReleaseDate, - TrackNumber: trackNumber, - TotalTracks: raw.Count, - DiscNumber: item.DiscNumber, - TotalDiscs: raw.Discs.TotalCount, - ExternalURL: fmt.Sprintf("https://open.spotify.com/track/%s", item.ID), - AlbumID: raw.ID, - AlbumURL: fmt.Sprintf("https://open.spotify.com/album/%s", raw.ID), - ArtistID: artistID, - ArtistURL: artistURL, - ArtistsData: artistsData, - UPC: trackUPC, - Plays: item.Plays, - IsExplicit: item.IsExplicit, - }) - } - - if callback != nil { - callback(tracks) - } - - return &AlbumResponsePayload{ - AlbumInfo: info, - TrackList: tracks, - }, nil -} - -func (c *SpotifyMetadataClient) formatPlaylistData(raw *apiPlaylistResponse, callback MetadataCallback) PlaylistResponsePayload { - var info PlaylistInfoMetadata - info.Tracks.Total = raw.Count - info.Followers.Total = raw.Followers - info.Owner.DisplayName = raw.Owner.Name - info.Owner.Name = raw.Name - info.Owner.Images = raw.Owner.Avatar - info.Cover = raw.Cover - info.Description = raw.Description - - if callback != nil { - callback(PlaylistResponsePayload{ - PlaylistInfo: info, - TrackList: []AlbumTrackMetadata{}, - }) - } - - tracks := make([]AlbumTrackMetadata, 0, len(raw.Tracks)) - for _, item := range raw.Tracks { - durationMS := parseDuration(item.Duration) - - var artistID, artistURL string - if len(item.ArtistIds) > 0 { - artistID = item.ArtistIds[0] - artistURL = fmt.Sprintf("https://open.spotify.com/artist/%s", artistID) - } - - artistsData := make([]ArtistSimple, 0, len(item.ArtistIds)) - for _, id := range item.ArtistIds { - artistsData = append(artistsData, ArtistSimple{ - ID: id, - Name: "", - ExternalURL: fmt.Sprintf("https://open.spotify.com/artist/%s", id), - }) - } - - tracks = append(tracks, AlbumTrackMetadata{ - SpotifyID: item.ID, - Artists: item.Artist, - Name: item.Title, - AlbumName: item.Album, - AlbumArtist: item.AlbumArtist, - DurationMS: durationMS, - Images: item.Cover, - ReleaseDate: "", - TrackNumber: 0, - TotalTracks: 0, - DiscNumber: item.DiscNumber, - TotalDiscs: 0, - ExternalURL: fmt.Sprintf("https://open.spotify.com/track/%s", item.ID), - AlbumID: item.AlbumID, - AlbumURL: fmt.Sprintf("https://open.spotify.com/album/%s", item.AlbumID), - ArtistID: artistID, - ArtistURL: artistURL, - ArtistsData: artistsData, - UPC: item.UPC, - Plays: item.Plays, - Status: item.Status, - IsExplicit: item.IsExplicit, - }) - } - - if callback != nil { - callback(tracks) - } - - return PlaylistResponsePayload{ - PlaylistInfo: info, - TrackList: tracks, - } -} - -func (c *SpotifyMetadataClient) formatArtistDiscographyData(ctx context.Context, raw *apiArtistResponse, callback MetadataCallback) (*ArtistDiscographyPayload, error) { - discType := "all" - - info := ArtistInfoMetadata{ - Name: raw.Name, - Followers: raw.Stats.Followers, - Genres: []string{}, - Images: raw.Avatar, - Header: raw.Header, - Gallery: raw.Gallery, - ExternalURL: fmt.Sprintf("https://open.spotify.com/artist/%s", raw.ID), - DiscographyType: discType, - TotalAlbums: raw.Discography.Total, - Biography: raw.Profile.Biography, - Verified: raw.Profile.Verified, - Listeners: raw.Stats.Listeners, - Rank: raw.Stats.Rank, - } - - albumList := make([]DiscographyAlbumMetadata, 0, len(raw.Discography.All)) - allTracks := make([]AlbumTrackMetadata, 0) - - type fetchResult struct { - tracks []AlbumTrackMetadata - err error - } - - resultsChan := make(chan fetchResult, len(raw.Discography.All)) - sem := make(chan struct{}, 5) - - sharedClient := NewSpotifyClient() - if err := sharedClient.Initialize(); err != nil { - return nil, fmt.Errorf("failed to initialize shared spotify client: %w", err) - } - - for _, alb := range raw.Discography.All { - albumList = append(albumList, DiscographyAlbumMetadata{ - ID: alb.ID, - Name: alb.Name, - AlbumType: alb.Type, - ReleaseDate: alb.Date, - TotalTracks: alb.TotalTracks, - Artists: raw.Name, - Images: alb.Cover, - ExternalURL: fmt.Sprintf("https://open.spotify.com/album/%s", alb.ID), - }) - } - - if callback != nil { - callback(ArtistDiscographyPayload{ - ArtistInfo: info, - AlbumList: albumList, - TrackList: []AlbumTrackMetadata{}, - }) - } - - for _, alb := range raw.Discography.All { - go func(albumID string, albumName string) { - sem <- struct{}{} - - time.Sleep(100 * time.Millisecond) - defer func() { <-sem }() - - select { - case <-ctx.Done(): - resultsChan <- fetchResult{err: ctx.Err()} - return - default: - } - - albumData, err := c.fetchAlbumWithClient(ctx, sharedClient, albumID, nil) - if err != nil { - fmt.Printf("Error getting tracks for album %s: %v\n", albumName, err) - resultsChan <- fetchResult{tracks: []AlbumTrackMetadata{}} - return - } - - tracks := make([]AlbumTrackMetadata, 0, len(albumData.Tracks)) - for idx, tr := range albumData.Tracks { - durationMS := parseDuration(tr.Duration) - trackNumber := idx + 1 - - var artistID, artistURL string - if len(tr.ArtistIds) > 0 { - artistID = tr.ArtistIds[0] - artistURL = fmt.Sprintf("https://open.spotify.com/artist/%s", artistID) - } - - artistsData := make([]ArtistSimple, 0, len(tr.ArtistIds)) - for _, id := range tr.ArtistIds { - artistsData = append(artistsData, ArtistSimple{ - ID: id, - Name: "", - ExternalURL: fmt.Sprintf("https://open.spotify.com/artist/%s", id), - }) - } - - tracks = append(tracks, AlbumTrackMetadata{ - SpotifyID: tr.ID, - Artists: tr.Artists, - Name: tr.Name, - AlbumName: albumData.Name, - AlbumArtist: raw.Name, - AlbumType: "album", - DurationMS: durationMS, - Images: albumData.Cover, - ReleaseDate: albumData.ReleaseDate, - TrackNumber: trackNumber, - TotalTracks: albumData.Count, - DiscNumber: tr.DiscNumber, - UPC: tr.UPC, - ExternalURL: fmt.Sprintf("https://open.spotify.com/track/%s", tr.ID), - AlbumID: albumID, - AlbumURL: fmt.Sprintf("https://open.spotify.com/album/%s", albumID), - ArtistID: artistID, - ArtistURL: artistURL, - ArtistsData: artistsData, - Plays: tr.Plays, - IsExplicit: tr.IsExplicit, - }) - } - if callback != nil { - callback(tracks) - } - resultsChan <- fetchResult{tracks: tracks} - }(alb.ID, alb.Name) - } - - for i := 0; i < len(raw.Discography.All); i++ { - res := <-resultsChan - if res.err != nil { - return nil, res.err - } - allTracks = append(allTracks, res.tracks...) - } - - return &ArtistDiscographyPayload{ - ArtistInfo: info, - AlbumList: albumList, - TrackList: allTracks, - }, nil -} - -func parseDuration(durationStr string) int { - if durationStr == "" { - return 0 - } - - parts := strings.Split(durationStr, ":") - if len(parts) != 2 { - return 0 - } - - minutes, err1 := strconv.Atoi(parts[0]) - seconds, err2 := strconv.Atoi(parts[1]) - if err1 != nil || err2 != nil { - return 0 - } - - return (minutes*60 + seconds) * 1000 -} - -func parseSpotifyURI(input string) (spotifyURI, error) { - trimmed := strings.TrimSpace(input) - if trimmed == "" { - return spotifyURI{}, errInvalidSpotifyURL - } - - if strings.HasPrefix(trimmed, "spotify:") { - parts := strings.Split(trimmed, ":") - if len(parts) == 3 { - switch parts[1] { - case "album", "track", "playlist", "artist": - return spotifyURI{Type: parts[1], ID: parts[2]}, nil - } - } - } - - parsed, err := url.Parse(trimmed) - if err != nil { - return spotifyURI{}, err - } - - if parsed.Host != "open.spotify.com" && parsed.Host != "play.spotify.com" { - return spotifyURI{}, errInvalidSpotifyURL - } - - parts := cleanPathParts(parsed.Path) - if len(parts) == 0 { - return spotifyURI{}, errInvalidSpotifyURL - } - - if parts[0] == "embed" { - parts = parts[1:] - } - if len(parts) == 0 { - return spotifyURI{}, errInvalidSpotifyURL - } - if strings.HasPrefix(parts[0], "intl-") { - parts = parts[1:] - } - if len(parts) == 0 { - return spotifyURI{}, errInvalidSpotifyURL - } - - if len(parts) == 2 { - switch parts[0] { - case "album", "track", "playlist", "artist": - return spotifyURI{Type: parts[0], ID: parts[1]}, nil - } - } - - if len(parts) >= 3 && parts[0] == "artist" { - if len(parts) >= 3 && parts[2] == "discography" { - discType := "all" - if len(parts) >= 4 { - candidate := parts[3] - if candidate == "all" || candidate == "album" || candidate == "single" || candidate == "compilation" { - discType = candidate - } - } - return spotifyURI{Type: "artist_discography", ID: parts[1], DiscographyGroup: discType}, nil - } - return spotifyURI{Type: "artist", ID: parts[1]}, nil - } - - return spotifyURI{}, errInvalidSpotifyURL -} - -func cleanPathParts(path string) []string { - raw := strings.Split(path, "/") - parts := make([]string, 0, len(raw)) - for _, part := range raw { - if part != "" { - parts = append(parts, part) - } - } - return parts -} - -func parseArtistIDsFromString(artists string) []string { - return []string{} -} - -func splitAndCleanArtists(artists string) []string { - raw := regexp.MustCompile(`\s*[;,]\s*`).Split(strings.TrimSpace(artists), -1) - parts := make([]string, 0, len(raw)) - for _, part := range raw { - part = strings.TrimSpace(part) - if part != "" { - parts = append(parts, part) - } - } - return parts -} - -func (c *SpotifyMetadataClient) Search(ctx context.Context, query string, limit int) (*SearchResponse, error) { - if query == "" { - return nil, errors.New("search query cannot be empty") - } - - if limit <= 0 || limit > 50 { - limit = 50 - } - - client := NewSpotifyClient() - if err := client.Initialize(); err != nil { - return nil, fmt.Errorf("failed to initialize spotify client: %w", err) - } - - payload := map[string]interface{}{ - "variables": map[string]interface{}{ - "searchTerm": query, - "offset": 0, - "limit": limit, - "numberOfTopResults": 5, - "includeAudiobooks": true, - "includeArtistHasConcertsField": false, - "includePreReleases": true, - "includeAuthors": false, - }, - "operationName": "searchDesktop", - "extensions": map[string]interface{}{ - "persistedQuery": map[string]interface{}{ - "version": 1, - "sha256Hash": "fcad5a3e0d5af727fb76966f06971c19cfa2275e6ff7671196753e008611873c", - }, - }, - } - - data, err := client.Query(payload) - if err != nil { - return nil, fmt.Errorf("failed to query search: %w", err) - } - - filteredData := FilterSearch(data, c.Separator) - - jsonData, err := json.Marshal(filteredData) - if err != nil { - return nil, fmt.Errorf("failed to marshal filtered data: %w", err) - } - - var apiResp apiSearchResponse - if err := json.Unmarshal(jsonData, &apiResp); err != nil { - return nil, fmt.Errorf("failed to unmarshal to apiSearchResponse: %w", err) - } - - response := &SearchResponse{ - Tracks: make([]SearchResult, 0), - Albums: make([]SearchResult, 0), - Artists: make([]SearchResult, 0), - Playlists: make([]SearchResult, 0), - } - - for _, item := range apiResp.Results.Tracks { - response.Tracks = append(response.Tracks, SearchResult{ - ID: item.ID, - Name: item.Name, - Type: "track", - Artists: item.Artists, - AlbumName: item.Album, - Images: item.Cover, - ExternalURL: fmt.Sprintf("https://open.spotify.com/track/%s", item.ID), - Duration: parseDuration(item.Duration), - IsExplicit: item.IsExplicit, - }) - } - - for _, item := range apiResp.Results.Albums { - response.Albums = append(response.Albums, SearchResult{ - ID: item.ID, - Name: item.Name, - Type: "album", - Artists: item.Artists, - Images: item.Cover, - ReleaseDate: fmt.Sprintf("%d", item.Year), - ExternalURL: fmt.Sprintf("https://open.spotify.com/album/%s", item.ID), - }) - } - - for _, item := range apiResp.Results.Artists { - response.Artists = append(response.Artists, SearchResult{ - ID: item.ID, - Name: item.Name, - Type: "artist", - Images: item.Cover, - ExternalURL: fmt.Sprintf("https://open.spotify.com/artist/%s", item.ID), - }) - } - - for _, item := range apiResp.Results.Playlists { - response.Playlists = append(response.Playlists, SearchResult{ - ID: item.ID, - Name: item.Name, - Type: "playlist", - Images: item.Cover, - Owner: item.Owner, - ExternalURL: fmt.Sprintf("https://open.spotify.com/playlist/%s", item.ID), - }) - } - - return response, nil -} - -func SearchSpotify(ctx context.Context, query string, limit int) (*SearchResponse, error) { - client := NewSpotifyMetadataClient() - return client.Search(ctx, query, limit) -} - -func (c *SpotifyMetadataClient) SearchByType(ctx context.Context, query string, searchType string, limit int, offset int) ([]SearchResult, error) { - if query == "" { - return nil, errors.New("search query cannot be empty") - } - - if limit <= 0 || limit > 50 { - limit = 50 - } - - if offset < 0 { - offset = 0 - } - - client := NewSpotifyClient() - if err := client.Initialize(); err != nil { - return nil, fmt.Errorf("failed to initialize spotify client: %w", err) - } - - payload := map[string]interface{}{ - "variables": map[string]interface{}{ - "searchTerm": query, - "offset": offset, - "limit": limit, - "numberOfTopResults": 5, - "includeAudiobooks": true, - "includeArtistHasConcertsField": false, - "includePreReleases": true, - "includeAuthors": false, - }, - "operationName": "searchDesktop", - "extensions": map[string]interface{}{ - "persistedQuery": map[string]interface{}{ - "version": 1, - "sha256Hash": "fcad5a3e0d5af727fb76966f06971c19cfa2275e6ff7671196753e008611873c", - }, - }, - } - - data, err := client.Query(payload) - if err != nil { - return nil, fmt.Errorf("failed to query search: %w", err) - } - - filteredData := FilterSearch(data, c.Separator) - - jsonData, err := json.Marshal(filteredData) - if err != nil { - return nil, fmt.Errorf("failed to marshal filtered data: %w", err) - } - - var apiResp apiSearchResponse - if err := json.Unmarshal(jsonData, &apiResp); err != nil { - return nil, fmt.Errorf("failed to unmarshal to apiSearchResponse: %w", err) - } - - results := make([]SearchResult, 0) - - switch searchType { - case "track": - for _, item := range apiResp.Results.Tracks { - results = append(results, SearchResult{ - ID: item.ID, - Name: item.Name, - Type: "track", - Artists: item.Artists, - AlbumName: item.Album, - Images: item.Cover, - ExternalURL: fmt.Sprintf("https://open.spotify.com/track/%s", item.ID), - Duration: parseDuration(item.Duration), - IsExplicit: item.IsExplicit, - }) - } - case "album": - for _, item := range apiResp.Results.Albums { - results = append(results, SearchResult{ - ID: item.ID, - Name: item.Name, - Type: "album", - Artists: item.Artists, - Images: item.Cover, - ReleaseDate: fmt.Sprintf("%d", item.Year), - ExternalURL: fmt.Sprintf("https://open.spotify.com/album/%s", item.ID), - }) - } - case "artist": - for _, item := range apiResp.Results.Artists { - results = append(results, SearchResult{ - ID: item.ID, - Name: item.Name, - Type: "artist", - Images: item.Cover, - ExternalURL: fmt.Sprintf("https://open.spotify.com/artist/%s", item.ID), - }) - } - case "playlist": - for _, item := range apiResp.Results.Playlists { - results = append(results, SearchResult{ - ID: item.ID, - Name: item.Name, - Type: "playlist", - Images: item.Cover, - Owner: item.Owner, - ExternalURL: fmt.Sprintf("https://open.spotify.com/playlist/%s", item.ID), - }) - } - default: - return nil, fmt.Errorf("invalid search type: %s", searchType) - } - - return results, nil -} - -func SearchSpotifyByType(ctx context.Context, query string, searchType string, limit int, offset int) ([]SearchResult, error) { - client := NewSpotifyMetadataClient() - return client.SearchByType(ctx, query, searchType, limit, offset) -} - -func GetPreviewURL(trackID string) (string, error) { - if trackID == "" { - return "", errors.New("track ID cannot be empty") - } - - embedURL := fmt.Sprintf("https://open.spotify.com/embed/track/%s", trackID) - - client := &http.Client{Timeout: 15 * time.Second} - resp, err := client.Get(embedURL) - if err != nil { - return "", fmt.Errorf("failed to fetch embed page: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return "", fmt.Errorf("embed page returned status %d", resp.StatusCode) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("failed to read response body: %w", err) - } - - html := string(body) - re := regexp.MustCompile(`https://p\.scdn\.co/mp3-preview/[a-zA-Z0-9]+`) - match := re.FindString(html) - - if match == "" { - return "", errors.New("preview URL not found") - } - - return match, nil -} diff --git a/backend/spotify_totp.go b/backend/spotify_totp.go deleted file mode 100644 index 3f5faa5..0000000 --- a/backend/spotify_totp.go +++ /dev/null @@ -1,28 +0,0 @@ -package backend - -import ( - "fmt" - "time" - - "github.com/pquerna/otp" - "github.com/pquerna/otp/totp" -) - -const ( - spotifyTOTPSecret = "GM3TMMJTGYZTQNZVGM4DINJZHA4TGOBYGMZTCMRTGEYDSMJRHE4TEOBUG4YTCMRUGQ4DQOJUGQYTAMRRGA2TCMJSHE3TCMBY" - spotifyTOTPVersion = 61 -) - -func generateSpotifyTOTP(now time.Time) (string, int, error) { - key, err := otp.NewKeyFromURL(fmt.Sprintf("otpauth://totp/secret?secret=%s", spotifyTOTPSecret)) - if err != nil { - return "", 0, err - } - - code, err := totp.GenerateCode(key.Secret(), now) - if err != nil { - return "", 0, err - } - - return code, spotifyTOTPVersion, nil -} diff --git a/backend/tidal.go b/backend/tidal.go deleted file mode 100644 index fec2b64..0000000 --- a/backend/tidal.go +++ /dev/null @@ -1,956 +0,0 @@ -package backend - -import ( - "encoding/base64" - "encoding/json" - "encoding/xml" - "fmt" - "io" - "net/http" - "os" - "os/exec" - "path/filepath" - "regexp" - "strings" - "time" -) - -type TidalDownloader struct { - client *http.Client - timeout time.Duration - maxRetries int - apiURL string -} - -type TidalAPIResponse struct { - OriginalTrackURL string `json:"OriginalTrackUrl"` -} - -type TidalAPIResponseV2 struct { - Version string `json:"version"` - Data struct { - TrackID int64 `json:"trackId"` - AssetPresentation string `json:"assetPresentation"` - AudioMode string `json:"audioMode"` - AudioQuality string `json:"audioQuality"` - ManifestMimeType string `json:"manifestMimeType"` - ManifestHash string `json:"manifestHash"` - Manifest string `json:"manifest"` - BitDepth int `json:"bitDepth"` - SampleRate int `json:"sampleRate"` - } `json:"data"` -} - -type TidalBTSManifest struct { - MimeType string `json:"mimeType"` - Codecs string `json:"codecs"` - EncryptionType string `json:"encryptionType"` - URLs []string `json:"urls"` -} - -func getConfiguredTidalAPIAttemptList() ([]string, error) { - customAPI := GetCustomTidalAPISetting() - if customAPI == "" { - return nil, fmt.Errorf("no configured custom tidal api instance") - } - return []string{customAPI}, nil -} - -func buildTidalOutputPath(outputDir, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, useAlbumTrackNumber bool, spotifyTrackNumber, spotifyDiscNumber int, isrcOverride string, useFirstArtistOnly bool) (string, bool, error) { - if outputDir != "." { - if err := os.MkdirAll(outputDir, 0755); err != nil { - return "", false, fmt.Errorf("directory error: %w", err) - } - } - - artistNameForFile := sanitizeFilename(spotifyArtistName) - albumArtistForFile := sanitizeFilename(spotifyAlbumArtist) - if useFirstArtistOnly { - artistNameForFile = sanitizeFilename(GetFirstArtist(spotifyArtistName)) - albumArtistForFile = sanitizeFilename(GetFirstArtist(spotifyAlbumArtist)) - } - - trackTitleForFile := sanitizeFilename(spotifyTrackName) - albumTitleForFile := sanitizeFilename(spotifyAlbumName) - - filename := buildTidalFilename(trackTitleForFile, artistNameForFile, albumTitleForFile, albumArtistForFile, spotifyReleaseDate, spotifyTrackNumber, spotifyDiscNumber, filenameFormat, includeTrackNumber, position, useAlbumTrackNumber, isrcOverride) - outputFilename := filepath.Join(outputDir, filename) - - outputFilename, alreadyExists := ResolveOutputPathForDownload(outputFilename, GetRedownloadWithSuffixSetting()) - return outputFilename, alreadyExists, nil -} - -func finalizeTidalDownload(outputFilename, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, spotifyCoverURL string, embedMaxQualityCover bool, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL string, useSingleGenre bool, embedGenre bool) { - trackTitle := spotifyTrackName - artistName := spotifyArtistName - albumTitle := spotifyAlbumName - - type mbResult struct { - ISRC string - Metadata Metadata - } - - metaChan := make(chan mbResult, 1) - if embedGenre && spotifyURL != "" { - go func() { - res := mbResult{} - var isrc string - parts := strings.Split(spotifyURL, "/") - if len(parts) > 0 { - sID := strings.Split(parts[len(parts)-1], "?")[0] - if sID != "" { - client := NewSongLinkClient() - if val, err := client.GetISRC(sID); err == nil { - isrc = val - } - } - } - res.ISRC = isrc - if isrc != "" { - if ShouldSkipMusicBrainzMetadataFetch() { - fmt.Println("Skipping MusicBrainz metadata fetch because status check is offline.") - } else { - fmt.Println("Fetching MusicBrainz metadata...") - if fetchedMeta, err := FetchMusicBrainzMetadata(isrc, trackTitle, artistName, albumTitle, useSingleGenre, embedGenre); err == nil { - res.Metadata = fetchedMeta - fmt.Println("✓ MusicBrainz metadata fetched") - } else { - fmt.Printf("Warning: Failed to fetch MusicBrainz metadata: %v\n", err) - } - } - } - metaChan <- res - }() - } else { - close(metaChan) - } - - isrc := strings.TrimSpace(isrcOverride) - var mbMeta Metadata - if spotifyURL != "" { - result := <-metaChan - if isrc == "" { - isrc = result.ISRC - } - mbMeta = result.Metadata - } - - upc := "" - if spotifyURL != "" { - if identifiers, err := GetSpotifyTrackIdentifiersDirect(spotifyURL); err == nil || identifiers.ISRC != "" || identifiers.UPC != "" { - if strings.TrimSpace(isrc) == "" && strings.TrimSpace(identifiers.ISRC) != "" { - isrc = strings.TrimSpace(identifiers.ISRC) - } - upc = strings.TrimSpace(identifiers.UPC) - } - } - - fmt.Println("Adding metadata...") - - coverPath := "" - if spotifyCoverURL != "" { - coverPath = outputFilename + ".cover.jpg" - coverClient := NewCoverClient() - if err := coverClient.DownloadCoverToPath(spotifyCoverURL, coverPath, embedMaxQualityCover); err != nil { - fmt.Printf("Warning: Failed to download Spotify cover: %v\n", err) - coverPath = "" - } else { - defer os.Remove(coverPath) - fmt.Println("Spotify cover downloaded") - } - } - - trackNumberToEmbed := spotifyTrackNumber - if trackNumberToEmbed == 0 { - trackNumberToEmbed = 1 - } - - metadata := Metadata{ - Title: trackTitle, - Artist: artistName, - Album: albumTitle, - AlbumArtist: spotifyAlbumArtist, - Date: spotifyReleaseDate, - TrackNumber: trackNumberToEmbed, - TotalTracks: spotifyTotalTracks, - DiscNumber: spotifyDiscNumber, - TotalDiscs: spotifyTotalDiscs, - URL: spotifyURL, - Comment: spotifyURL, - Copyright: spotifyCopyright, - Publisher: spotifyPublisher, - Composer: spotifyComposer, - Separator: metadataSeparator, - Description: "https://github.com/spotbye/SpotiFLAC", - ISRC: isrc, - UPC: upc, - Genre: mbMeta.Genre, - } - - if err := EmbedMetadata(outputFilename, metadata, coverPath); err != nil { - fmt.Printf("Tagging failed: %v\n", err) - } else { - fmt.Println("Metadata saved") - } -} - -func NewTidalDownloader(apiURL string) *TidalDownloader { - apiURL = strings.TrimRight(strings.TrimSpace(apiURL), "/") - return &TidalDownloader{ - client: &http.Client{ - Timeout: 5 * time.Second, - }, - timeout: 5 * time.Second, - maxRetries: 3, - apiURL: apiURL, - } -} - -func (t *TidalDownloader) GetAvailableAPIs() ([]string, error) { - apis, err := getConfiguredTidalAPIAttemptList() - if err == nil && len(apis) > 0 { - return apis, nil - } - - return nil, err -} - -func (t *TidalDownloader) GetTidalURLFromSpotify(spotifyTrackID string) (string, error) { - fmt.Println("Getting Tidal URL...") - client := NewSongLinkClient() - urls, err := client.GetAllURLsFromSpotify(spotifyTrackID, "") - if err != nil { - return "", fmt.Errorf("failed to get Tidal URL: %w", err) - } - - tidalURL := urls.TidalURL - if tidalURL == "" { - return "", fmt.Errorf("tidal link not found") - } - fmt.Printf("Found Tidal URL: %s\n", tidalURL) - return tidalURL, nil -} - -func (t *TidalDownloader) GetTrackIDFromURL(tidalURL string) (int64, error) { - - parts := strings.Split(tidalURL, "/track/") - if len(parts) < 2 { - return 0, fmt.Errorf("invalid tidal URL format") - } - - trackIDStr := strings.Split(parts[1], "?")[0] - trackIDStr = strings.TrimSpace(trackIDStr) - - var trackID int64 - _, err := fmt.Sscanf(trackIDStr, "%d", &trackID) - if err != nil { - return 0, fmt.Errorf("failed to parse track ID: %w", err) - } - - return trackID, nil -} - -func (t *TidalDownloader) GetDownloadURL(trackID int64, quality string) (string, error) { - fmt.Println("Fetching URL...") - if strings.TrimSpace(t.apiURL) == "" { - return "", fmt.Errorf("no configured custom tidal api instance") - } - - url := fmt.Sprintf("%s/track/?id=%d&quality=%s", t.apiURL, trackID, quality) - fmt.Printf("Tidal API URL: %s\n", url) - - req, err := NewRequestWithDefaultHeaders(http.MethodGet, url, nil) - if err != nil { - fmt.Printf("✗ failed to create request: %v\n", err) - return "", fmt.Errorf("failed to create request: %w", err) - } - - resp, err := t.client.Do(req) - if err != nil { - fmt.Printf("✗ Tidal API request failed: %v\n", err) - return "", fmt.Errorf("failed to get download URL: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - fmt.Printf("✗ Tidal API returned status code: %d\n", resp.StatusCode) - return "", fmt.Errorf("API returned status code: %d", resp.StatusCode) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - fmt.Printf("✗ Failed to read response body: %v\n", err) - return "", fmt.Errorf("failed to read response: %w", err) - } - - var v2Response TidalAPIResponseV2 - if err := json.Unmarshal(body, &v2Response); err == nil && v2Response.Data.Manifest != "" { - fmt.Println("✓ Tidal manifest found (v2 API)") - return "MANIFEST:" + v2Response.Data.Manifest, nil - } - - var apiResponses []TidalAPIResponse - if err := json.Unmarshal(body, &apiResponses); err != nil { - - bodyStr := string(body) - if len(bodyStr) > 200 { - bodyStr = bodyStr[:200] + "..." - } - fmt.Printf("✗ Failed to decode Tidal API response: %v (response: %s)\n", err, bodyStr) - return "", fmt.Errorf("failed to decode response: %w (response: %s)", err, bodyStr) - } - - if len(apiResponses) == 0 { - fmt.Println("✗ Tidal API returned empty response") - return "", fmt.Errorf("no download URL in response") - } - - for _, item := range apiResponses { - if item.OriginalTrackURL != "" { - fmt.Println("✓ Tidal download URL found") - return item.OriginalTrackURL, nil - } - } - - fmt.Println("✗ No valid download URL in Tidal API response") - return "", fmt.Errorf("download URL not found in response") -} - -func (t *TidalDownloader) DownloadFile(url, filepath string, quality string) error { - - if strings.HasPrefix(url, "MANIFEST:") { - return t.DownloadFromManifest(strings.TrimPrefix(url, "MANIFEST:"), filepath, quality) - } - - req, err := NewRequestWithDefaultHeaders(http.MethodGet, url, nil) - if err != nil { - return fmt.Errorf("failed to create request: %w", err) - } - - resp, err := t.client.Do(req) - - if err != nil { - return fmt.Errorf("failed to download file: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("download failed with status %d", resp.StatusCode) - } - - out, err := os.Create(filepath) - if err != nil { - return fmt.Errorf("failed to create file: %w", err) - } - defer out.Close() - - pw := NewProgressWriter(out) - _, err = io.Copy(pw, resp.Body) - if err != nil { - return fmt.Errorf("failed to write file: %w", err) - } - - fmt.Printf("\rDownloaded: %.2f MB (Complete)\n", float64(pw.GetTotal())/(1024*1024)) - - fmt.Println("Download complete") - return nil -} - -func (t *TidalDownloader) DownloadFromManifest(manifestB64, outputPath string, quality string) error { - directURL, initURL, mediaURLs, mimeType, err := parseManifest(manifestB64) - if err != nil { - return fmt.Errorf("failed to parse manifest: %w", err) - } - - isLosslessRequested := quality == "LOSSLESS" || quality == "HI_RES" || quality == "HI_RES_LOSSLESS" - isActualLossless := strings.Contains(strings.ToLower(mimeType), "flac") || mimeType == "" - if isLosslessRequested && !isActualLossless { - return fmt.Errorf("requested %s quality but Tidal provided lossy format (%s). Aborting download", quality, mimeType) - } - - client := &http.Client{ - Timeout: 120 * time.Second, - } - - doRequest := func(url string) (*http.Response, error) { - req, err := NewRequestWithDefaultHeaders(http.MethodGet, url, nil) - if err != nil { - return nil, err - } - return client.Do(req) - } - - if directURL != "" && (strings.Contains(strings.ToLower(mimeType), "flac") || mimeType == "") { - fmt.Println("Downloading file...") - - resp, err := doRequest(directURL) - if err != nil { - return fmt.Errorf("failed to download file: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("download failed with status %d", resp.StatusCode) - } - - out, err := os.Create(outputPath) - if err != nil { - return fmt.Errorf("failed to create file: %w", err) - } - defer out.Close() - - pw := NewProgressWriter(out) - _, err = io.Copy(pw, resp.Body) - if err != nil { - return fmt.Errorf("failed to write file: %w", err) - } - - fmt.Printf("\rDownloaded: %.2f MB (Complete)\n", float64(pw.GetTotal())/(1024*1024)) - fmt.Println("Download complete") - return nil - } - - tempPath := outputPath + ".m4a.tmp" - - if directURL != "" { - fmt.Printf("Downloading non-FLAC file (%s)...\n", mimeType) - - resp, err := doRequest(directURL) - if err != nil { - return fmt.Errorf("failed to download file: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("download failed with status %d", resp.StatusCode) - } - - out, err := os.Create(tempPath) - if err != nil { - return fmt.Errorf("failed to create temp file: %w", err) - } - - pw := NewProgressWriter(out) - _, err = io.Copy(pw, resp.Body) - out.Close() - - if err != nil { - os.Remove(tempPath) - return fmt.Errorf("failed to write temp file: %w", err) - } - - fmt.Printf("\rDownloaded: %.2f MB (Complete)\n", float64(pw.GetTotal())/(1024*1024)) - - } else { - - fmt.Printf("Downloading %d segments...\n", len(mediaURLs)+1) - - out, err := os.Create(tempPath) - if err != nil { - return fmt.Errorf("failed to create temp file: %w", err) - } - - fmt.Print("Downloading init segment... ") - resp, err := doRequest(initURL) - if err != nil { - out.Close() - os.Remove(tempPath) - return fmt.Errorf("failed to download init segment: %w", err) - } - if resp.StatusCode != 200 { - resp.Body.Close() - out.Close() - os.Remove(tempPath) - return fmt.Errorf("init segment download failed with status %d", resp.StatusCode) - } - _, err = io.Copy(out, resp.Body) - resp.Body.Close() - if err != nil { - out.Close() - os.Remove(tempPath) - return fmt.Errorf("failed to write init segment: %w", err) - } - fmt.Println("OK") - - totalSegments := len(mediaURLs) - var totalBytes int64 - lastTime := time.Now() - var lastBytes int64 - for i, mediaURL := range mediaURLs { - resp, err := doRequest(mediaURL) - if err != nil { - out.Close() - os.Remove(tempPath) - return fmt.Errorf("failed to download segment %d: %w", i+1, err) - } - if resp.StatusCode != 200 { - resp.Body.Close() - out.Close() - os.Remove(tempPath) - return fmt.Errorf("segment %d download failed with status %d", i+1, resp.StatusCode) - } - n, err := io.Copy(out, resp.Body) - totalBytes += n - resp.Body.Close() - if err != nil { - out.Close() - os.Remove(tempPath) - return fmt.Errorf("failed to write segment %d: %w", i+1, err) - } - - mbDownloaded := float64(totalBytes) / (1024 * 1024) - now := time.Now() - timeDiff := now.Sub(lastTime).Seconds() - var speedMBps float64 - if timeDiff > 0.1 { - bytesDiff := float64(totalBytes - lastBytes) - speedMBps = (bytesDiff / (1024 * 1024)) / timeDiff - SetDownloadSpeed(speedMBps) - lastTime = now - lastBytes = totalBytes - } - SetDownloadProgress(mbDownloaded) - - fmt.Printf("\rDownloading: %.2f MB (%d/%d segments)", mbDownloaded, i+1, totalSegments) - } - - out.Close() - - tempInfo, _ := os.Stat(tempPath) - fmt.Printf("\rDownloaded: %.2f MB (Complete) \n", float64(tempInfo.Size())/(1024*1024)) - } - - fmt.Println("Converting to FLAC...") - ffmpegPath, err := GetFFmpegPath() - if err != nil { - return fmt.Errorf("ffmpeg not found: %w", err) - } - - if err := ValidateExecutable(ffmpegPath); err != nil { - return fmt.Errorf("invalid ffmpeg executable: %w", err) - } - - cmd := exec.Command(ffmpegPath, "-y", "-i", tempPath, "-vn", "-c:a", "flac", outputPath) - setHideWindow(cmd) - var stderr strings.Builder - cmd.Stderr = &stderr - if err := cmd.Run(); err != nil { - - m4aPath := strings.TrimSuffix(outputPath, ".flac") + ".m4a" - os.Rename(tempPath, m4aPath) - return fmt.Errorf("ffmpeg conversion failed (M4A saved as %s): %w - %s", m4aPath, err, stderr.String()) - } - - os.Remove(tempPath) - fmt.Println("Download complete") - - return nil -} - -func (t *TidalDownloader) DownloadByURL(tidalURL, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, useAlbumTrackNumber bool, spotifyCoverURL string, embedMaxQualityCover bool, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL string, allowFallback bool, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) { - fmt.Printf("Using Tidal URL: %s\n", tidalURL) - - trackID, err := t.GetTrackIDFromURL(tidalURL) - if err != nil { - return "", err - } - - if trackID == 0 { - return "", fmt.Errorf("no track ID found") - } - - outputFilename, alreadyExists, err := buildTidalOutputPath(outputDir, filenameFormat, includeTrackNumber, position, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, useAlbumTrackNumber, spotifyTrackNumber, spotifyDiscNumber, isrcOverride, useFirstArtistOnly) - if err != nil { - return "", err - } - if alreadyExists { - fmt.Printf("File already exists: %s (%.2f MB)\n", outputFilename, float64(mustFileSize(outputFilename))/(1024*1024)) - return "EXISTS:" + outputFilename, nil - } - - downloadURL, err := t.GetDownloadURL(trackID, quality) - if err != nil { - if isTidalHiResQuality(quality) && allowFallback { - fmt.Println("⚠ HI_RES unavailable/failed, falling back to LOSSLESS...") - downloadURL, err = t.GetDownloadURL(trackID, "LOSSLESS") - if err != nil { - return outputFilename, fmt.Errorf("failed to get download URL (HI_RES & LOSSLESS both failed): %w", err) - } - } else { - return outputFilename, err - } - } - - fmt.Printf("Downloading to: %s\n", outputFilename) - if err := t.DownloadFile(downloadURL, outputFilename, quality); err != nil { - cleanupTidalDownloadArtifacts(outputFilename) - return outputFilename, err - } - - finalizeTidalDownload(outputFilename, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, spotifyCoverURL, embedMaxQualityCover, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks, spotifyTotalDiscs, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL, useSingleGenre, embedGenre) - - fmt.Println("Done") - fmt.Println("✓ Downloaded successfully from Tidal") - return outputFilename, nil -} - -func (t *TidalDownloader) DownloadByURLWithFallback(tidalURL, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, useAlbumTrackNumber bool, spotifyCoverURL string, embedMaxQualityCover bool, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL string, allowFallback bool, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) { - fmt.Printf("Using Tidal URL: %s\n", tidalURL) - - trackID, err := t.GetTrackIDFromURL(tidalURL) - if err != nil { - return "", err - } - - if trackID == 0 { - return "", fmt.Errorf("no track ID found") - } - - outputFilename, alreadyExists, err := buildTidalOutputPath(outputDir, filenameFormat, includeTrackNumber, position, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, useAlbumTrackNumber, spotifyTrackNumber, spotifyDiscNumber, isrcOverride, useFirstArtistOnly) - if err != nil { - return "", err - } - if alreadyExists { - fmt.Printf("File already exists: %s (%.2f MB)\n", outputFilename, float64(mustFileSize(outputFilename))/(1024*1024)) - return "EXISTS:" + outputFilename, nil - } - - fmt.Printf("Downloading to: %s\n", outputFilename) - successAPI, err := t.downloadWithRotatingAPIs(trackID, outputFilename, quality, allowFallback) - if err != nil { - cleanupTidalDownloadArtifacts(outputFilename) - return outputFilename, err - } - fmt.Printf("✓ Downloaded using API: %s\n", successAPI) - - finalizeTidalDownload(outputFilename, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, spotifyCoverURL, embedMaxQualityCover, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks, spotifyTotalDiscs, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL, useSingleGenre, embedGenre) - - fmt.Println("Done") - fmt.Println("✓ Downloaded successfully from Tidal") - return outputFilename, nil -} - -func (t *TidalDownloader) Download(spotifyTrackID, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, useAlbumTrackNumber bool, spotifyCoverURL string, embedMaxQualityCover bool, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL string, allowFallback bool, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) { - - tidalURL, err := t.GetTidalURLFromSpotify(spotifyTrackID) - if err != nil { - return "", fmt.Errorf("songlink/songstats couldn't find Tidal URL: %w", err) - } - - if t.apiURL == "" { - return "", fmt.Errorf("no configured custom tidal api instance") - } - return t.DownloadByURL(tidalURL, outputDir, quality, filenameFormat, includeTrackNumber, position, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, useAlbumTrackNumber, spotifyCoverURL, embedMaxQualityCover, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks, spotifyTotalDiscs, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL, allowFallback, useFirstArtistOnly, useSingleGenre, embedGenre) -} - -type SegmentTemplate struct { - Initialization string `xml:"initialization,attr"` - Media string `xml:"media,attr"` - Timeline struct { - Segments []struct { - Duration int64 `xml:"d,attr"` - Repeat int `xml:"r,attr"` - } `xml:"S"` - } `xml:"SegmentTimeline"` -} - -type MPD struct { - XMLName xml.Name `xml:"MPD"` - Period struct { - AdaptationSets []struct { - MimeType string `xml:"mimeType,attr"` - Codecs string `xml:"codecs,attr"` - Representations []struct { - ID string `xml:"id,attr"` - Codecs string `xml:"codecs,attr"` - Bandwidth int `xml:"bandwidth,attr"` - SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate"` - } `xml:"Representation"` - SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate"` - } `xml:"AdaptationSet"` - } `xml:"Period"` -} - -func parseManifest(manifestB64 string) (directURL string, initURL string, mediaURLs []string, mimeType string, err error) { - manifestBytes, err := base64.StdEncoding.DecodeString(manifestB64) - if err != nil { - return "", "", nil, "", fmt.Errorf("failed to decode manifest: %w", err) - } - - manifestStr := string(manifestBytes) - - if strings.HasPrefix(strings.TrimSpace(manifestStr), "{") { - var btsManifest TidalBTSManifest - if err := json.Unmarshal(manifestBytes, &btsManifest); err != nil { - return "", "", nil, "", fmt.Errorf("failed to parse BTS manifest: %w", err) - } - - if len(btsManifest.URLs) == 0 { - return "", "", nil, "", fmt.Errorf("no URLs in BTS manifest") - } - - fmt.Printf("Manifest: BTS format (%s, %s)\n", btsManifest.MimeType, btsManifest.Codecs) - return btsManifest.URLs[0], "", nil, btsManifest.MimeType, nil - } - - fmt.Println("Manifest: DASH format") - - var mpd MPD - var segTemplate *SegmentTemplate - var dashMimeType string - - if err := xml.Unmarshal(manifestBytes, &mpd); err == nil { - var selectedBandwidth int - var selectedCodecs string - var selectedMimeType string - - for _, as := range mpd.Period.AdaptationSets { - - if as.SegmentTemplate != nil { - - if segTemplate == nil { - segTemplate = as.SegmentTemplate - selectedCodecs = as.Codecs - selectedMimeType = as.MimeType - } - } - - for _, rep := range as.Representations { - if rep.SegmentTemplate != nil { - if rep.Bandwidth > selectedBandwidth { - selectedBandwidth = rep.Bandwidth - segTemplate = rep.SegmentTemplate - - if rep.Codecs != "" { - selectedCodecs = rep.Codecs - } else { - selectedCodecs = as.Codecs - } - - selectedMimeType = as.MimeType - } - } - } - } - - if selectedBandwidth > 0 { - fmt.Printf("Selected stream: Codec=%s, Bandwidth=%d bps\n", selectedCodecs, selectedBandwidth) - dashMimeType = fmt.Sprintf("%s; codecs=\"%s\"", selectedMimeType, selectedCodecs) - } - } - - var mediaTemplate string - segmentCount := 0 - - if segTemplate != nil { - initURL = segTemplate.Initialization - mediaTemplate = segTemplate.Media - - for _, seg := range segTemplate.Timeline.Segments { - segmentCount += seg.Repeat + 1 - } - } - - if segmentCount > 0 && initURL != "" && mediaTemplate != "" { - initURL = strings.ReplaceAll(initURL, "&", "&") - mediaTemplate = strings.ReplaceAll(mediaTemplate, "&", "&") - - fmt.Printf("Parsed manifest via XML: %d segments\n", segmentCount) - - for i := 1; i <= segmentCount; i++ { - mediaURL := strings.ReplaceAll(mediaTemplate, "$Number$", fmt.Sprintf("%d", i)) - mediaURLs = append(mediaURLs, mediaURL) - } - return "", initURL, mediaURLs, dashMimeType, nil - } - - fmt.Println("Using regex fallback for DASH manifest...") - - initRe := regexp.MustCompile(`initialization="([^"]+)"`) - mediaRe := regexp.MustCompile(`media="([^"]+)"`) - - if match := initRe.FindStringSubmatch(manifestStr); len(match) > 1 { - initURL = match[1] - } - if match := mediaRe.FindStringSubmatch(manifestStr); len(match) > 1 { - mediaTemplate = match[1] - } - - if initURL == "" { - return "", "", nil, "", fmt.Errorf("no initialization URL found in manifest") - } - - initURL = strings.ReplaceAll(initURL, "&", "&") - mediaTemplate = strings.ReplaceAll(mediaTemplate, "&", "&") - - segmentCount = 0 - - segTagRe := regexp.MustCompile(`]*>`) - matches := segTagRe.FindAllString(manifestStr, -1) - - for _, match := range matches { - repeat := 0 - rRe := regexp.MustCompile(`r="(\d+)"`) - if rMatch := rRe.FindStringSubmatch(match); len(rMatch) > 1 { - fmt.Sscanf(rMatch[1], "%d", &repeat) - } - segmentCount += repeat + 1 - } - - if segmentCount == 0 { - return "", "", nil, "", fmt.Errorf("no segments found in manifest (XML: %d, Regex: 0)", len(matches)) - } - - fmt.Printf("Parsed manifest via Regex: %d segments\n", segmentCount) - - for i := 1; i <= segmentCount; i++ { - mediaURL := strings.ReplaceAll(mediaTemplate, "$Number$", fmt.Sprintf("%d", i)) - mediaURLs = append(mediaURLs, mediaURL) - } - - return "", initURL, mediaURLs, dashMimeType, nil -} - -func (t *TidalDownloader) downloadWithRotatingAPIs(trackID int64, outputFilename string, quality string, allowFallback bool) (string, error) { - qualities := []string{quality} - if isTidalHiResQuality(quality) && allowFallback { - qualities = append(qualities, "LOSSLESS") - } - - var lastErr error - for idx, candidateQuality := range qualities { - if idx > 0 { - fmt.Printf("⚠ %s unavailable/failed on all APIs, falling back to %s...\n", quality, candidateQuality) - } - - apiURL, err := t.tryDownloadAcrossTidalAPIs(trackID, outputFilename, candidateQuality, false) - if err == nil { - return apiURL, nil - } - lastErr = err - } - - if lastErr == nil { - lastErr = fmt.Errorf("no tidal api succeeded") - } - return "", lastErr -} - -func (t *TidalDownloader) tryDownloadAcrossTidalAPIs(trackID int64, outputFilename string, quality string, refreshed bool) (string, error) { - apis, err := getConfiguredTidalAPIAttemptList() - if err != nil && len(apis) == 0 { - return "", fmt.Errorf("failed to load tidal api list: %w", err) - } - if len(apis) == 0 { - return "", fmt.Errorf("no tidal apis available") - } - - var lastErr error - errors := make([]string, 0, len(apis)) - - for _, apiURL := range apis { - fmt.Printf("Trying Tidal API: %s\n", apiURL) - - downloader := NewTidalDownloader(apiURL) - downloadURL, err := downloader.GetDownloadURL(trackID, quality) - if err != nil { - lastErr = err - errors = append(errors, fmt.Sprintf("%s: %v", apiURL, err)) - continue - } - - if err := downloader.DownloadFile(downloadURL, outputFilename, quality); err != nil { - lastErr = err - cleanupTidalDownloadArtifacts(outputFilename) - errors = append(errors, fmt.Sprintf("%s: %v", apiURL, err)) - continue - } - - return apiURL, nil - } - - if lastErr == nil { - lastErr = fmt.Errorf("all tidal apis failed") - } - - fmt.Println("All Tidal APIs failed:") - for _, item := range errors { - fmt.Printf(" ✗ %s\n", item) - } - - return "", fmt.Errorf("all tidal apis failed for quality %s: %w", quality, lastErr) -} - -func cleanupTidalDownloadArtifacts(outputPath string) { - if outputPath == "" { - return - } - - _ = os.Remove(outputPath) - _ = os.Remove(outputPath + ".m4a.tmp") -} - -func isTidalHiResQuality(quality string) bool { - normalized := strings.TrimSpace(strings.ToUpper(quality)) - return normalized == "HI_RES" || normalized == "HI_RES_LOSSLESS" -} - -func buildTidalFilename(title, artist, album, albumArtist, releaseDate string, trackNumber, discNumber int, format string, includeTrackNumber bool, position int, useAlbumTrackNumber bool, extra ...string) string { - var filename string - isrc := "" - if len(extra) > 0 { - isrc = SanitizeOptionalFilename(extra[0]) - } - - numberToUse := position - if useAlbumTrackNumber && trackNumber > 0 { - numberToUse = trackNumber - } - - year := "" - if len(releaseDate) >= 4 { - year = releaseDate[:4] - } - - if strings.Contains(format, "{") { - filename = format - filename = strings.ReplaceAll(filename, "{title}", title) - filename = strings.ReplaceAll(filename, "{artist}", artist) - filename = strings.ReplaceAll(filename, "{album}", album) - filename = strings.ReplaceAll(filename, "{album_artist}", albumArtist) - filename = strings.ReplaceAll(filename, "{year}", year) - filename = strings.ReplaceAll(filename, "{date}", SanitizeFilename(releaseDate)) - filename = strings.ReplaceAll(filename, "{isrc}", isrc) - - if discNumber > 0 { - filename = strings.ReplaceAll(filename, "{disc}", fmt.Sprintf("%d", discNumber)) - } else { - filename = strings.ReplaceAll(filename, "{disc}", "") - } - - if numberToUse > 0 { - filename = strings.ReplaceAll(filename, "{track}", fmt.Sprintf("%02d", numberToUse)) - } else { - - filename = regexp.MustCompile(`\{track\}\.\s*`).ReplaceAllString(filename, "") - filename = regexp.MustCompile(`\{track\}\s*-\s*`).ReplaceAllString(filename, "") - filename = regexp.MustCompile(`\{track\}\s*`).ReplaceAllString(filename, "") - } - } else { - - switch format { - case "artist-title": - filename = fmt.Sprintf("%s - %s", artist, title) - case "title": - filename = title - default: - filename = fmt.Sprintf("%s - %s", title, artist) - } - - if includeTrackNumber && position > 0 { - filename = fmt.Sprintf("%02d. %s", numberToUse, filename) - } - } - - return filename + ".flac" -} diff --git a/backend/upc_tags.go b/backend/upc_tags.go deleted file mode 100644 index 14a638f..0000000 --- a/backend/upc_tags.go +++ /dev/null @@ -1,50 +0,0 @@ -package backend - -import "strings" - -const preferredUPCTagKey = "UPC" - -var ffprobeUPCTagKeys = []string{ - "upc", - "barcode", - "wm/upc", - "txxx:upc", - "txxx:barcode", - "txxx/upc", - "txxx/barcode", - "----:com.apple.itunes:upc", - "----:com.apple.itunes:barcode", -} - -func assignPreferredUPC(current *string, incoming string, preferred bool) { - incoming = strings.TrimSpace(incoming) - if incoming == "" { - return - } - - if preferred || strings.TrimSpace(*current) == "" { - *current = incoming - } -} - -func classifyUPCDescription(description string) (matched bool, preferred bool) { - switch strings.ToUpper(strings.TrimSpace(description)) { - case preferredUPCTagKey: - return true, true - case "BARCODE": - return true, false - default: - return false, false - } -} - -func firstPreferredFFprobeUPCValue(tags map[string]string) string { - for _, key := range ffprobeUPCTagKeys { - value := strings.TrimSpace(tags[key]) - if value != "" { - return value - } - } - - return "" -} diff --git a/frontend/.gitignore b/frontend/.gitignore deleted file mode 100644 index a547bf3..0000000 --- a/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/frontend/components.json b/frontend/components.json deleted file mode 100644 index fd90f3b..0000000 --- a/frontend/components.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema.json", - "style": "new-york", - "rsc": false, - "tsx": true, - "tailwind": { - "config": "", - "css": "src/index.css", - "baseColor": "neutral", - "cssVariables": true, - "prefix": "" - }, - "iconLibrary": "lucide", - "aliases": { - "components": "@/components", - "utils": "@/lib/utils", - "ui": "@/components/ui", - "lib": "@/lib", - "hooks": "@/hooks" - }, - "registries": { - "@lucide-animated": "https://lucide-animated.com/r/{name}.json" - } -} diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js deleted file mode 100644 index 13d2e6b..0000000 --- a/frontend/eslint.config.js +++ /dev/null @@ -1,22 +0,0 @@ -import js from '@eslint/js'; -import globals from 'globals'; -import reactHooks from 'eslint-plugin-react-hooks'; -import reactRefresh from 'eslint-plugin-react-refresh'; -import tseslint from 'typescript-eslint'; -import { defineConfig, globalIgnores } from 'eslint/config'; -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - js.configs.recommended, - tseslint.configs.recommended, - reactHooks.configs.flat.recommended, - reactRefresh.configs.vite, - ], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - }, -]); diff --git a/frontend/index.html b/frontend/index.html deleted file mode 100644 index 8257e4a..0000000 --- a/frontend/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - SpotiFLAC - - - -
- - - - \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json deleted file mode 100644 index 4972ef7..0000000 --- a/frontend/package.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc -b && vite build", - "postinstall": "node scripts/generate-icon.js", - "lint": "eslint .", - "preview": "vite preview", - "generate-icon": "node scripts/generate-icon.js" - }, - "dependencies": { - "@radix-ui/react-checkbox": "^1.3.3", - "@radix-ui/react-context-menu": "^2.2.16", - "@radix-ui/react-dialog": "^1.1.15", - "@radix-ui/react-label": "^2.1.8", - "@radix-ui/react-menubar": "^1.1.16", - "@radix-ui/react-progress": "^1.1.8", - "@radix-ui/react-scroll-area": "^1.2.10", - "@radix-ui/react-select": "^2.2.6", - "@radix-ui/react-slider": "^1.3.6", - "@radix-ui/react-slot": "^1.2.4", - "@radix-ui/react-switch": "^1.2.6", - "@radix-ui/react-tabs": "^1.1.13", - "@radix-ui/react-toggle": "^1.1.10", - "@radix-ui/react-toggle-group": "^1.1.11", - "@radix-ui/react-tooltip": "^1.2.8", - "@tailwindcss/vite": "^4.2.1", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "lucide-react": "^0.575.0", - "motion": "^12.34.3", - "next-themes": "^0.4.6", - "radix-ui": "^1.4.3", - "react": "^19.2.4", - "react-dom": "^19.2.4", - "sonner": "^2.0.7", - "tailwind-merge": "^3.5.0", - "tailwindcss": "^4.2.1" - }, - "devDependencies": { - "@eslint/js": "^10.0.1", - "@types/node": "^25.3.0", - "@types/react": "^19.2.14", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.4", - "eslint": "^10.0.2", - "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-react-refresh": "^0.5.2", - "globals": "^17.3.0", - "sharp": "^0.34.5", - "tw-animate-css": "^1.4.0", - "typescript": "~5.9.3", - "typescript-eslint": "^8.56.1", - "vite": "^7.3.1" - } -} diff --git a/frontend/package.json.md5 b/frontend/package.json.md5 deleted file mode 100644 index 806b9d6..0000000 --- a/frontend/package.json.md5 +++ /dev/null @@ -1 +0,0 @@ -8864b4f7b7971b624d1ba25030f2db4e \ No newline at end of file diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml deleted file mode 100644 index 2158658..0000000 --- a/frontend/pnpm-lock.yaml +++ /dev/null @@ -1,4519 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - '@radix-ui/react-checkbox': - specifier: ^1.3.3 - version: 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-context-menu': - specifier: ^2.2.16 - version: 2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-dialog': - specifier: ^1.1.15 - version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-label': - specifier: ^2.1.8 - version: 2.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-menubar': - specifier: ^1.1.16 - version: 1.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-progress': - specifier: ^1.1.8 - version: 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-scroll-area': - specifier: ^1.2.10 - version: 1.2.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-select': - specifier: ^2.2.6 - version: 2.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slider': - specifier: ^1.3.6 - version: 1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': - specifier: ^1.2.4 - version: 1.2.4(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-switch': - specifier: ^1.2.6 - version: 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-tabs': - specifier: ^1.1.13 - version: 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-toggle': - specifier: ^1.1.10 - version: 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-toggle-group': - specifier: ^1.1.11 - version: 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-tooltip': - specifier: ^1.2.8 - version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@tailwindcss/vite': - specifier: ^4.2.1 - version: 4.2.1(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(lightningcss@1.31.1)) - class-variance-authority: - specifier: ^0.7.1 - version: 0.7.1 - clsx: - specifier: ^2.1.1 - version: 2.1.1 - lucide-react: - specifier: ^0.575.0 - version: 0.575.0(react@19.2.4) - motion: - specifier: ^12.34.3 - version: 12.34.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - next-themes: - specifier: ^0.4.6 - version: 0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - radix-ui: - specifier: ^1.4.3 - version: 1.4.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: - specifier: ^19.2.4 - version: 19.2.4 - react-dom: - specifier: ^19.2.4 - version: 19.2.4(react@19.2.4) - sonner: - specifier: ^2.0.7 - version: 2.0.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - tailwind-merge: - specifier: ^3.5.0 - version: 3.5.0 - tailwindcss: - specifier: ^4.2.1 - version: 4.2.1 - devDependencies: - '@eslint/js': - specifier: ^10.0.1 - version: 10.0.1(eslint@10.0.2(jiti@2.6.1)) - '@types/node': - specifier: ^25.3.0 - version: 25.3.0 - '@types/react': - specifier: ^19.2.14 - version: 19.2.14 - '@types/react-dom': - specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.14) - '@vitejs/plugin-react': - specifier: ^5.1.4 - version: 5.1.4(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(lightningcss@1.31.1)) - eslint: - specifier: ^10.0.2 - version: 10.0.2(jiti@2.6.1) - eslint-plugin-react-hooks: - specifier: ^7.0.1 - version: 7.0.1(eslint@10.0.2(jiti@2.6.1)) - eslint-plugin-react-refresh: - specifier: ^0.5.2 - version: 0.5.2(eslint@10.0.2(jiti@2.6.1)) - globals: - specifier: ^17.3.0 - version: 17.3.0 - sharp: - specifier: ^0.34.5 - version: 0.34.5 - tw-animate-css: - specifier: ^1.4.0 - version: 1.4.0 - typescript: - specifier: ~5.9.3 - version: 5.9.3 - typescript-eslint: - specifier: ^8.56.1 - version: 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) - vite: - specifier: ^7.3.1 - version: 7.3.1(@types/node@25.3.0)(jiti@2.6.1)(lightningcss@1.31.1) - -packages: - - '@babel/code-frame@7.29.0': - resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.29.0': - resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.29.0': - resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.29.1': - resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.28.6': - resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-globals@7.28.0': - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.28.6': - resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.28.6': - resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-plugin-utils@7.28.6': - resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-option@7.27.1': - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.28.6': - resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.29.0': - resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/plugin-transform-react-jsx-self@7.27.1': - resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx-source@7.27.1': - resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/template@7.28.6': - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.29.0': - resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} - engines: {node: '>=6.9.0'} - - '@emnapi/runtime@1.8.1': - resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} - - '@esbuild/aix-ppc64@0.27.3': - resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.27.3': - resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.27.3': - resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.27.3': - resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.27.3': - resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.27.3': - resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.27.3': - resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.27.3': - resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.27.3': - resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.27.3': - resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.27.3': - resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.27.3': - resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.27.3': - resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.27.3': - resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.27.3': - resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.27.3': - resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.27.3': - resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.27.3': - resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.27.3': - resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.27.3': - resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.27.3': - resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.27.3': - resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/sunos-x64@0.27.3': - resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.27.3': - resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.27.3': - resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.27.3': - resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@eslint-community/eslint-utils@4.9.1': - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.12.2': - resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/config-array@0.23.2': - resolution: {integrity: sha512-YF+fE6LV4v5MGWRGj7G404/OZzGNepVF8fxk7jqmqo3lrza7a0uUcDnROGRBG1WFC1omYUS/Wp1f42i0M+3Q3A==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - '@eslint/config-helpers@0.5.2': - resolution: {integrity: sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - '@eslint/core@1.1.0': - resolution: {integrity: sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - '@eslint/js@10.0.1': - resolution: {integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - peerDependencies: - eslint: ^10.0.0 - peerDependenciesMeta: - eslint: - optional: true - - '@eslint/object-schema@3.0.2': - resolution: {integrity: sha512-HOy56KJt48Bx8KmJ+XGQNSUMT/6dZee/M54XyUyuvTvPXJmsERRvBchsUVx1UMe1WwIH49XLAczNC7V2INsuUw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - '@eslint/plugin-kit@0.6.0': - resolution: {integrity: sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - '@floating-ui/core@1.7.4': - resolution: {integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==} - - '@floating-ui/dom@1.7.5': - resolution: {integrity: sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==} - - '@floating-ui/react-dom@2.1.7': - resolution: {integrity: sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - - '@floating-ui/utils@0.2.10': - resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} - - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - - '@humanfs/node@0.16.7': - resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} - engines: {node: '>=18.18.0'} - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/retry@0.4.3': - resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} - engines: {node: '>=18.18'} - - '@img/colour@1.0.0': - resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} - engines: {node: '>=18'} - - '@img/sharp-darwin-arm64@0.34.5': - resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [darwin] - - '@img/sharp-darwin-x64@0.34.5': - resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-darwin-arm64@1.2.4': - resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} - cpu: [arm64] - os: [darwin] - - '@img/sharp-libvips-darwin-x64@1.2.4': - resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-linux-arm64@1.2.4': - resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-arm@1.2.4': - resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-ppc64@1.2.4': - resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-riscv64@1.2.4': - resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-s390x@1.2.4': - resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-x64@1.2.4': - resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linuxmusl-arm64@1.2.4': - resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@img/sharp-libvips-linuxmusl-x64@1.2.4': - resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@img/sharp-linux-arm64@0.34.5': - resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-arm@0.34.5': - resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-ppc64@0.34.5': - resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-riscv64@0.34.5': - resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-s390x@0.34.5': - resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-x64@0.34.5': - resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@img/sharp-linuxmusl-arm64@0.34.5': - resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@img/sharp-linuxmusl-x64@0.34.5': - resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - libc: [musl] - - '@img/sharp-wasm32@0.34.5': - resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [wasm32] - - '@img/sharp-win32-arm64@0.34.5': - resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [win32] - - '@img/sharp-win32-ia32@0.34.5': - resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [ia32] - os: [win32] - - '@img/sharp-win32-x64@0.34.5': - resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [win32] - - '@jridgewell/gen-mapping@0.3.13': - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - - '@jridgewell/remapping@2.3.5': - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - - '@jridgewell/trace-mapping@0.3.31': - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - - '@radix-ui/number@1.1.1': - resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} - - '@radix-ui/primitive@1.1.3': - resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} - - '@radix-ui/react-accessible-icon@1.1.7': - resolution: {integrity: sha512-XM+E4WXl0OqUJFovy6GjmxxFyx9opfCAIUku4dlKRd5YEPqt4kALOkQOp0Of6reHuUkJuiPBEc5k0o4z4lTC8A==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-accordion@1.2.12': - resolution: {integrity: sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-alert-dialog@1.1.15': - resolution: {integrity: sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-arrow@1.1.7': - resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-aspect-ratio@1.1.7': - resolution: {integrity: sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-avatar@1.1.10': - resolution: {integrity: sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-checkbox@1.3.3': - resolution: {integrity: sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-collapsible@1.1.12': - resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-collection@1.1.7': - resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-compose-refs@1.1.2': - resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-context-menu@2.2.16': - resolution: {integrity: sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-context@1.1.2': - resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-context@1.1.3': - resolution: {integrity: sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-dialog@1.1.15': - resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-direction@1.1.1': - resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-dismissable-layer@1.1.11': - resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-dropdown-menu@2.1.16': - resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-focus-guards@1.1.3': - resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-focus-scope@1.1.7': - resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-form@0.1.8': - resolution: {integrity: sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-hover-card@1.1.15': - resolution: {integrity: sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-id@1.1.1': - resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-label@2.1.7': - resolution: {integrity: sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-label@2.1.8': - resolution: {integrity: sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-menu@2.1.16': - resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-menubar@1.1.16': - resolution: {integrity: sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-navigation-menu@1.2.14': - resolution: {integrity: sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-one-time-password-field@0.1.8': - resolution: {integrity: sha512-ycS4rbwURavDPVjCb5iS3aG4lURFDILi6sKI/WITUMZ13gMmn/xGjpLoqBAalhJaDk8I3UbCM5GzKHrnzwHbvg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-password-toggle-field@0.1.3': - resolution: {integrity: sha512-/UuCrDBWravcaMix4TdT+qlNdVwOM1Nck9kWx/vafXsdfj1ChfhOdfi3cy9SGBpWgTXwYCuboT/oYpJy3clqfw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-popover@1.1.15': - resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-popper@1.2.8': - resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-portal@1.1.9': - resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-presence@1.1.5': - resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-primitive@2.1.3': - resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-primitive@2.1.4': - resolution: {integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-progress@1.1.7': - resolution: {integrity: sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-progress@1.1.8': - resolution: {integrity: sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-radio-group@1.3.8': - resolution: {integrity: sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-roving-focus@1.1.11': - resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-scroll-area@1.2.10': - resolution: {integrity: sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-select@2.2.6': - resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-separator@1.1.7': - resolution: {integrity: sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-slider@1.3.6': - resolution: {integrity: sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-slot@1.2.3': - resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-slot@1.2.4': - resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-switch@1.2.6': - resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-tabs@1.1.13': - resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-toast@1.2.15': - resolution: {integrity: sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-toggle-group@1.1.11': - resolution: {integrity: sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-toggle@1.1.10': - resolution: {integrity: sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-toolbar@1.1.11': - resolution: {integrity: sha512-4ol06/1bLoFu1nwUqzdD4Y5RZ9oDdKeiHIsntug54Hcr1pgaHiPqHFEaXI1IFP/EsOfROQZ8Mig9VTIRza6Tjg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-tooltip@1.2.8': - resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-use-callback-ref@1.1.1': - resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-controllable-state@1.2.2': - resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-effect-event@0.0.2': - resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-escape-keydown@1.1.1': - resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-is-hydrated@0.1.0': - resolution: {integrity: sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-layout-effect@1.1.1': - resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-previous@1.1.1': - resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-rect@1.1.1': - resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-size@1.1.1': - resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-visually-hidden@1.2.3': - resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/rect@1.1.1': - resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} - - '@rolldown/pluginutils@1.0.0-rc.3': - resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} - - '@rollup/rollup-android-arm-eabi@4.59.0': - resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.59.0': - resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.59.0': - resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.59.0': - resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.59.0': - resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.59.0': - resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm-musleabihf@4.59.0': - resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} - cpu: [arm] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-arm64-gnu@4.59.0': - resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm64-musl@4.59.0': - resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-loong64-gnu@4.59.0': - resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} - cpu: [loong64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-loong64-musl@4.59.0': - resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} - cpu: [loong64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-ppc64-gnu@4.59.0': - resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-ppc64-musl@4.59.0': - resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} - cpu: [ppc64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-riscv64-gnu@4.59.0': - resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-riscv64-musl@4.59.0': - resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-s390x-gnu@4.59.0': - resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-gnu@4.59.0': - resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-musl@4.59.0': - resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@rollup/rollup-openbsd-x64@4.59.0': - resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.59.0': - resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} - cpu: [arm64] - os: [openharmony] - - '@rollup/rollup-win32-arm64-msvc@4.59.0': - resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.59.0': - resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-gnu@4.59.0': - resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} - cpu: [x64] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.59.0': - resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} - cpu: [x64] - os: [win32] - - '@tailwindcss/node@4.2.1': - resolution: {integrity: sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==} - - '@tailwindcss/oxide-android-arm64@4.2.1': - resolution: {integrity: sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [android] - - '@tailwindcss/oxide-darwin-arm64@4.2.1': - resolution: {integrity: sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [darwin] - - '@tailwindcss/oxide-darwin-x64@4.2.1': - resolution: {integrity: sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [darwin] - - '@tailwindcss/oxide-freebsd-x64@4.2.1': - resolution: {integrity: sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==} - engines: {node: '>= 20'} - cpu: [x64] - os: [freebsd] - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': - resolution: {integrity: sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==} - engines: {node: '>= 20'} - cpu: [arm] - os: [linux] - - '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': - resolution: {integrity: sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@tailwindcss/oxide-linux-arm64-musl@4.2.1': - resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@tailwindcss/oxide-linux-x64-gnu@4.2.1': - resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@tailwindcss/oxide-linux-x64-musl@4.2.1': - resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@tailwindcss/oxide-wasm32-wasi@4.2.1': - resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - bundledDependencies: - - '@napi-rs/wasm-runtime' - - '@emnapi/core' - - '@emnapi/runtime' - - '@tybys/wasm-util' - - '@emnapi/wasi-threads' - - tslib - - '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': - resolution: {integrity: sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [win32] - - '@tailwindcss/oxide-win32-x64-msvc@4.2.1': - resolution: {integrity: sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==} - engines: {node: '>= 20'} - cpu: [x64] - os: [win32] - - '@tailwindcss/oxide@4.2.1': - resolution: {integrity: sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==} - engines: {node: '>= 20'} - - '@tailwindcss/vite@4.2.1': - resolution: {integrity: sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w==} - peerDependencies: - vite: ^5.2.0 || ^6 || ^7 - - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - - '@types/babel__generator@7.27.0': - resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} - - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - - '@types/babel__traverse@7.28.0': - resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} - - '@types/esrecurse@4.3.1': - resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} - - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/node@25.3.0': - resolution: {integrity: sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A==} - - '@types/react-dom@19.2.3': - resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} - peerDependencies: - '@types/react': ^19.2.0 - - '@types/react@19.2.14': - resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} - - '@typescript-eslint/eslint-plugin@8.56.1': - resolution: {integrity: sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.56.1 - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/parser@8.56.1': - resolution: {integrity: sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/project-service@8.56.1': - resolution: {integrity: sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/scope-manager@8.56.1': - resolution: {integrity: sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/tsconfig-utils@8.56.1': - resolution: {integrity: sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/type-utils@8.56.1': - resolution: {integrity: sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/types@8.56.1': - resolution: {integrity: sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.56.1': - resolution: {integrity: sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/utils@8.56.1': - resolution: {integrity: sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/visitor-keys@8.56.1': - resolution: {integrity: sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@vitejs/plugin-react@5.1.4': - resolution: {integrity: sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==} - engines: {node: ^20.19.0 || >=22.12.0} - peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn@8.16.0: - resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} - engines: {node: '>=0.4.0'} - hasBin: true - - ajv@6.14.0: - resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} - - aria-hidden@1.2.6: - resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} - engines: {node: '>=10'} - - balanced-match@4.0.4: - resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} - engines: {node: 18 || 20 || >=22} - - baseline-browser-mapping@2.10.0: - resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==} - engines: {node: '>=6.0.0'} - hasBin: true - - brace-expansion@5.0.3: - resolution: {integrity: sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==} - engines: {node: 18 || 20 || >=22} - - browserslist@4.28.1: - resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - caniuse-lite@1.0.30001774: - resolution: {integrity: sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA==} - - class-variance-authority@0.7.1: - resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} - - clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} - - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - csstype@3.2.3: - resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} - - detect-node-es@1.1.0: - resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} - - electron-to-chromium@1.5.302: - resolution: {integrity: sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==} - - enhanced-resolve@5.19.0: - resolution: {integrity: sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==} - engines: {node: '>=10.13.0'} - - esbuild@0.27.3: - resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} - engines: {node: '>=18'} - hasBin: true - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eslint-plugin-react-hooks@7.0.1: - resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==} - engines: {node: '>=18'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - - eslint-plugin-react-refresh@0.5.2: - resolution: {integrity: sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==} - peerDependencies: - eslint: ^9 || ^10 - - eslint-scope@9.1.1: - resolution: {integrity: sha512-GaUN0sWim5qc8KVErfPBWmc31LEsOkrUJbvJZV+xuL3u2phMUK4HIvXlWAakfC8W4nzlK+chPEAkYOYb5ZScIw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@5.0.1: - resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - eslint@10.0.2: - resolution: {integrity: sha512-uYixubwmqJZH+KLVYIVKY1JQt7tysXhtj21WSvjcSmU5SVNzMus1bgLe+pAt816yQ8opKfheVVoPLqvVMGejYw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - - espree@11.1.1: - resolution: {integrity: sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - esquery@1.7.0: - resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fdir@6.5.0: - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} - engines: {node: '>=12.0.0'} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flatted@3.3.3: - resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} - - framer-motion@12.34.3: - resolution: {integrity: sha512-v81ecyZKYO/DfpTwHivqkxSUBzvceOpoI+wLfgCgoUIKxlFKEXdg0oR9imxwXumT4SFy8vRk9xzJ5l3/Du/55Q==} - peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: - optional: true - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - get-nonce@1.0.1: - resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} - engines: {node: '>=6'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - globals@17.3.0: - resolution: {integrity: sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==} - engines: {node: '>=18'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - hermes-estree@0.25.1: - resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} - - hermes-parser@0.25.1: - resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} - engines: {node: '>= 4'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - jiti@2.6.1: - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} - hasBin: true - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - lightningcss-android-arm64@1.31.1: - resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [android] - - lightningcss-darwin-arm64@1.31.1: - resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [darwin] - - lightningcss-darwin-x64@1.31.1: - resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [darwin] - - lightningcss-freebsd-x64@1.31.1: - resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [freebsd] - - lightningcss-linux-arm-gnueabihf@1.31.1: - resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==} - engines: {node: '>= 12.0.0'} - cpu: [arm] - os: [linux] - - lightningcss-linux-arm64-gnu@1.31.1: - resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - lightningcss-linux-arm64-musl@1.31.1: - resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - libc: [musl] - - lightningcss-linux-x64-gnu@1.31.1: - resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - libc: [glibc] - - lightningcss-linux-x64-musl@1.31.1: - resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - libc: [musl] - - lightningcss-win32-arm64-msvc@1.31.1: - resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [win32] - - lightningcss-win32-x64-msvc@1.31.1: - resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [win32] - - lightningcss@1.31.1: - resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==} - engines: {node: '>= 12.0.0'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - - lucide-react@0.575.0: - resolution: {integrity: sha512-VuXgKZrk0uiDlWjGGXmKV6MSk9Yy4l10qgVvzGn2AWBx1Ylt0iBexKOAoA6I7JO3m+M9oeovJd3yYENfkUbOeg==} - peerDependencies: - react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - - magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - - minimatch@10.2.3: - resolution: {integrity: sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==} - engines: {node: 18 || 20 || >=22} - - motion-dom@12.34.3: - resolution: {integrity: sha512-sYgFe+pR9aIM7o4fhs2aXtOI+oqlUd33N9Yoxcgo1Fv7M20sRkHtCmzE/VRNIcq7uNJ+qio+Xubt1FXH3pQ+eQ==} - - motion-utils@12.29.2: - resolution: {integrity: sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==} - - motion@12.34.3: - resolution: {integrity: sha512-xZIkBGO7v/Uvm+EyaqYd+9IpXu0sZqLywVlGdCFrrMiaO9JI4Kx51mO9KlHSWwll+gZUVY5OJsWgYI5FywJ/tw==} - peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: - optional: true - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - next-themes@0.4.6: - resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} - peerDependencies: - react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - - node-releases@2.0.27: - resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} - - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@4.0.3: - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} - engines: {node: '>=12'} - - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} - engines: {node: ^10 || ^12 || >=14} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - radix-ui@1.4.3: - resolution: {integrity: sha512-aWizCQiyeAenIdUbqEpXgRA1ya65P13NKn/W8rWkcN0OPkRDxdBVLWnIEDsS2RpwCK2nobI7oMUSmexzTDyAmA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - react-dom@19.2.4: - resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} - peerDependencies: - react: ^19.2.4 - - react-refresh@0.18.0: - resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} - engines: {node: '>=0.10.0'} - - react-remove-scroll-bar@2.3.8: - resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - - react-remove-scroll@2.7.2: - resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - react-style-singleton@2.2.3: - resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - react@19.2.4: - resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} - engines: {node: '>=0.10.0'} - - rollup@4.59.0: - resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - scheduler@0.27.0: - resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.7.4: - resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} - engines: {node: '>=10'} - hasBin: true - - sharp@0.34.5: - resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - sonner@2.0.7: - resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==} - peerDependencies: - react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc - react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - tailwind-merge@3.5.0: - resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==} - - tailwindcss@4.2.1: - resolution: {integrity: sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==} - - tapable@2.3.0: - resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} - engines: {node: '>=6'} - - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} - engines: {node: '>=12.0.0'} - - ts-api-utils@2.4.0: - resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - tw-animate-css@1.4.0: - resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} - - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - typescript-eslint@8.56.1: - resolution: {integrity: sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' - - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} - hasBin: true - - undici-types@7.18.2: - resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - use-callback-ref@1.3.3: - resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - use-sidecar@1.1.3: - resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - use-sync-external-store@1.6.0: - resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - - vite@7.3.1: - resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - '@types/node': ^20.19.0 || >=22.12.0 - jiti: '>=1.21.0' - less: ^4.0.0 - lightningcss: ^1.21.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: '>=0.54.8' - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - - zod-validation-error@4.0.2: - resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} - engines: {node: '>=18.0.0'} - peerDependencies: - zod: ^3.25.0 || ^4.0.0 - - zod@4.3.6: - resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} - -snapshots: - - '@babel/code-frame@7.29.0': - dependencies: - '@babel/helper-validator-identifier': 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/compat-data@7.29.0': {} - - '@babel/core@7.29.0': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helpers': 7.28.6 - '@babel/parser': 7.29.0 - '@babel/template': 7.28.6 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - '@jridgewell/remapping': 2.3.5 - convert-source-map: 2.0.0 - debug: 4.4.3 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/generator@7.29.1': - dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - - '@babel/helper-compilation-targets@7.28.6': - dependencies: - '@babel/compat-data': 7.29.0 - '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.1 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-globals@7.28.0': {} - - '@babel/helper-module-imports@7.28.6': - dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-plugin-utils@7.28.6': {} - - '@babel/helper-string-parser@7.27.1': {} - - '@babel/helper-validator-identifier@7.28.5': {} - - '@babel/helper-validator-option@7.27.1': {} - - '@babel/helpers@7.28.6': - dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - - '@babel/parser@7.29.0': - dependencies: - '@babel/types': 7.29.0 - - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/template@7.28.6': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - - '@babel/traverse@7.29.0': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.0 - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - '@babel/types@7.29.0': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - - '@emnapi/runtime@1.8.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@esbuild/aix-ppc64@0.27.3': - optional: true - - '@esbuild/android-arm64@0.27.3': - optional: true - - '@esbuild/android-arm@0.27.3': - optional: true - - '@esbuild/android-x64@0.27.3': - optional: true - - '@esbuild/darwin-arm64@0.27.3': - optional: true - - '@esbuild/darwin-x64@0.27.3': - optional: true - - '@esbuild/freebsd-arm64@0.27.3': - optional: true - - '@esbuild/freebsd-x64@0.27.3': - optional: true - - '@esbuild/linux-arm64@0.27.3': - optional: true - - '@esbuild/linux-arm@0.27.3': - optional: true - - '@esbuild/linux-ia32@0.27.3': - optional: true - - '@esbuild/linux-loong64@0.27.3': - optional: true - - '@esbuild/linux-mips64el@0.27.3': - optional: true - - '@esbuild/linux-ppc64@0.27.3': - optional: true - - '@esbuild/linux-riscv64@0.27.3': - optional: true - - '@esbuild/linux-s390x@0.27.3': - optional: true - - '@esbuild/linux-x64@0.27.3': - optional: true - - '@esbuild/netbsd-arm64@0.27.3': - optional: true - - '@esbuild/netbsd-x64@0.27.3': - optional: true - - '@esbuild/openbsd-arm64@0.27.3': - optional: true - - '@esbuild/openbsd-x64@0.27.3': - optional: true - - '@esbuild/openharmony-arm64@0.27.3': - optional: true - - '@esbuild/sunos-x64@0.27.3': - optional: true - - '@esbuild/win32-arm64@0.27.3': - optional: true - - '@esbuild/win32-ia32@0.27.3': - optional: true - - '@esbuild/win32-x64@0.27.3': - optional: true - - '@eslint-community/eslint-utils@4.9.1(eslint@10.0.2(jiti@2.6.1))': - dependencies: - eslint: 10.0.2(jiti@2.6.1) - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.12.2': {} - - '@eslint/config-array@0.23.2': - dependencies: - '@eslint/object-schema': 3.0.2 - debug: 4.4.3 - minimatch: 10.2.3 - transitivePeerDependencies: - - supports-color - - '@eslint/config-helpers@0.5.2': - dependencies: - '@eslint/core': 1.1.0 - - '@eslint/core@1.1.0': - dependencies: - '@types/json-schema': 7.0.15 - - '@eslint/js@10.0.1(eslint@10.0.2(jiti@2.6.1))': - optionalDependencies: - eslint: 10.0.2(jiti@2.6.1) - - '@eslint/object-schema@3.0.2': {} - - '@eslint/plugin-kit@0.6.0': - dependencies: - '@eslint/core': 1.1.0 - levn: 0.4.1 - - '@floating-ui/core@1.7.4': - dependencies: - '@floating-ui/utils': 0.2.10 - - '@floating-ui/dom@1.7.5': - dependencies: - '@floating-ui/core': 1.7.4 - '@floating-ui/utils': 0.2.10 - - '@floating-ui/react-dom@2.1.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@floating-ui/dom': 1.7.5 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - '@floating-ui/utils@0.2.10': {} - - '@humanfs/core@0.19.1': {} - - '@humanfs/node@0.16.7': - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.4.3 - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/retry@0.4.3': {} - - '@img/colour@1.0.0': {} - - '@img/sharp-darwin-arm64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.2.4 - optional: true - - '@img/sharp-darwin-x64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.2.4 - optional: true - - '@img/sharp-libvips-darwin-arm64@1.2.4': - optional: true - - '@img/sharp-libvips-darwin-x64@1.2.4': - optional: true - - '@img/sharp-libvips-linux-arm64@1.2.4': - optional: true - - '@img/sharp-libvips-linux-arm@1.2.4': - optional: true - - '@img/sharp-libvips-linux-ppc64@1.2.4': - optional: true - - '@img/sharp-libvips-linux-riscv64@1.2.4': - optional: true - - '@img/sharp-libvips-linux-s390x@1.2.4': - optional: true - - '@img/sharp-libvips-linux-x64@1.2.4': - optional: true - - '@img/sharp-libvips-linuxmusl-arm64@1.2.4': - optional: true - - '@img/sharp-libvips-linuxmusl-x64@1.2.4': - optional: true - - '@img/sharp-linux-arm64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.2.4 - optional: true - - '@img/sharp-linux-arm@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.2.4 - optional: true - - '@img/sharp-linux-ppc64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-ppc64': 1.2.4 - optional: true - - '@img/sharp-linux-riscv64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-riscv64': 1.2.4 - optional: true - - '@img/sharp-linux-s390x@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.2.4 - optional: true - - '@img/sharp-linux-x64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.2.4 - optional: true - - '@img/sharp-linuxmusl-arm64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 - optional: true - - '@img/sharp-linuxmusl-x64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 - optional: true - - '@img/sharp-wasm32@0.34.5': - dependencies: - '@emnapi/runtime': 1.8.1 - optional: true - - '@img/sharp-win32-arm64@0.34.5': - optional: true - - '@img/sharp-win32-ia32@0.34.5': - optional: true - - '@img/sharp-win32-x64@0.34.5': - optional: true - - '@jridgewell/gen-mapping@0.3.13': - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/remapping@2.3.5': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/sourcemap-codec@1.5.5': {} - - '@jridgewell/trace-mapping@0.3.31': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - - '@radix-ui/number@1.1.1': {} - - '@radix-ui/primitive@1.1.3': {} - - '@radix-ui/react-accessible-icon@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-accordion@1.2.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-alert-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-aspect-ratio@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-avatar@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-context-menu@2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-context@1.1.2(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-context@1.1.3(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - aria-hidden: 1.2.6 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-direction@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-form@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-label': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-hover-card@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-id@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-label@2.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-label@2.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - aria-hidden: 1.2.6 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-menubar@1.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-navigation-menu@1.2.14(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-one-time-password-field@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-password-toggle-field@0.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - aria-hidden: 1.2.6 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@floating-ui/react-dom': 2.1.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/rect': 1.1.1 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-slot': 1.2.4(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-progress@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-progress@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-context': 1.1.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-radio-group@1.3.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-select@2.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - aria-hidden: 1.2.6 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-separator@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-slider@1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-slot@1.2.3(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-slot@1.2.4(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-switch@1.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-toast@1.2.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-toggle-group@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-toggle@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-toolbar@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-separator': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-toggle-group': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-is-hydrated@0.1.0(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - use-sync-external-store: 1.6.0(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-previous@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/rect': 1.1.1 - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-size@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/rect@1.1.1': {} - - '@rolldown/pluginutils@1.0.0-rc.3': {} - - '@rollup/rollup-android-arm-eabi@4.59.0': - optional: true - - '@rollup/rollup-android-arm64@4.59.0': - optional: true - - '@rollup/rollup-darwin-arm64@4.59.0': - optional: true - - '@rollup/rollup-darwin-x64@4.59.0': - optional: true - - '@rollup/rollup-freebsd-arm64@4.59.0': - optional: true - - '@rollup/rollup-freebsd-x64@4.59.0': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.59.0': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-loong64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-loong64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-ppc64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-ppc64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-riscv64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-x64-musl@4.59.0': - optional: true - - '@rollup/rollup-openbsd-x64@4.59.0': - optional: true - - '@rollup/rollup-openharmony-arm64@4.59.0': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.59.0': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.59.0': - optional: true - - '@rollup/rollup-win32-x64-gnu@4.59.0': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.59.0': - optional: true - - '@tailwindcss/node@4.2.1': - dependencies: - '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.19.0 - jiti: 2.6.1 - lightningcss: 1.31.1 - magic-string: 0.30.21 - source-map-js: 1.2.1 - tailwindcss: 4.2.1 - - '@tailwindcss/oxide-android-arm64@4.2.1': - optional: true - - '@tailwindcss/oxide-darwin-arm64@4.2.1': - optional: true - - '@tailwindcss/oxide-darwin-x64@4.2.1': - optional: true - - '@tailwindcss/oxide-freebsd-x64@4.2.1': - optional: true - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': - optional: true - - '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': - optional: true - - '@tailwindcss/oxide-linux-arm64-musl@4.2.1': - optional: true - - '@tailwindcss/oxide-linux-x64-gnu@4.2.1': - optional: true - - '@tailwindcss/oxide-linux-x64-musl@4.2.1': - optional: true - - '@tailwindcss/oxide-wasm32-wasi@4.2.1': - optional: true - - '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': - optional: true - - '@tailwindcss/oxide-win32-x64-msvc@4.2.1': - optional: true - - '@tailwindcss/oxide@4.2.1': - optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.2.1 - '@tailwindcss/oxide-darwin-arm64': 4.2.1 - '@tailwindcss/oxide-darwin-x64': 4.2.1 - '@tailwindcss/oxide-freebsd-x64': 4.2.1 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.1 - '@tailwindcss/oxide-linux-arm64-gnu': 4.2.1 - '@tailwindcss/oxide-linux-arm64-musl': 4.2.1 - '@tailwindcss/oxide-linux-x64-gnu': 4.2.1 - '@tailwindcss/oxide-linux-x64-musl': 4.2.1 - '@tailwindcss/oxide-wasm32-wasi': 4.2.1 - '@tailwindcss/oxide-win32-arm64-msvc': 4.2.1 - '@tailwindcss/oxide-win32-x64-msvc': 4.2.1 - - '@tailwindcss/vite@4.2.1(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(lightningcss@1.31.1))': - dependencies: - '@tailwindcss/node': 4.2.1 - '@tailwindcss/oxide': 4.2.1 - tailwindcss: 4.2.1 - vite: 7.3.1(@types/node@25.3.0)(jiti@2.6.1)(lightningcss@1.31.1) - - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - '@types/babel__generator': 7.27.0 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.28.0 - - '@types/babel__generator@7.27.0': - dependencies: - '@babel/types': 7.29.0 - - '@types/babel__template@7.4.4': - dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - - '@types/babel__traverse@7.28.0': - dependencies: - '@babel/types': 7.29.0 - - '@types/esrecurse@4.3.1': {} - - '@types/estree@1.0.8': {} - - '@types/json-schema@7.0.15': {} - - '@types/node@25.3.0': - dependencies: - undici-types: 7.18.2 - - '@types/react-dom@19.2.3(@types/react@19.2.14)': - dependencies: - '@types/react': 19.2.14 - - '@types/react@19.2.14': - dependencies: - csstype: 3.2.3 - - '@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.56.1 - '@typescript-eslint/type-utils': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.56.1 - eslint: 10.0.2(jiti@2.6.1) - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.56.1 - '@typescript-eslint/types': 8.56.1 - '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.56.1 - debug: 4.4.3 - eslint: 10.0.2(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/project-service@8.56.1(typescript@5.9.3)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.9.3) - '@typescript-eslint/types': 8.56.1 - debug: 4.4.3 - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@8.56.1': - dependencies: - '@typescript-eslint/types': 8.56.1 - '@typescript-eslint/visitor-keys': 8.56.1 - - '@typescript-eslint/tsconfig-utils@8.56.1(typescript@5.9.3)': - dependencies: - typescript: 5.9.3 - - '@typescript-eslint/type-utils@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/types': 8.56.1 - '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) - debug: 4.4.3 - eslint: 10.0.2(jiti@2.6.1) - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@8.56.1': {} - - '@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3)': - dependencies: - '@typescript-eslint/project-service': 8.56.1(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.9.3) - '@typescript-eslint/types': 8.56.1 - '@typescript-eslint/visitor-keys': 8.56.1 - debug: 4.4.3 - minimatch: 10.2.3 - semver: 7.7.4 - tinyglobby: 0.2.15 - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.2(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.56.1 - '@typescript-eslint/types': 8.56.1 - '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) - eslint: 10.0.2(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/visitor-keys@8.56.1': - dependencies: - '@typescript-eslint/types': 8.56.1 - eslint-visitor-keys: 5.0.1 - - '@vitejs/plugin-react@5.1.4(vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(lightningcss@1.31.1))': - dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) - '@rolldown/pluginutils': 1.0.0-rc.3 - '@types/babel__core': 7.20.5 - react-refresh: 0.18.0 - vite: 7.3.1(@types/node@25.3.0)(jiti@2.6.1)(lightningcss@1.31.1) - transitivePeerDependencies: - - supports-color - - acorn-jsx@5.3.2(acorn@8.16.0): - dependencies: - acorn: 8.16.0 - - acorn@8.16.0: {} - - ajv@6.14.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - aria-hidden@1.2.6: - dependencies: - tslib: 2.8.1 - - balanced-match@4.0.4: {} - - baseline-browser-mapping@2.10.0: {} - - brace-expansion@5.0.3: - dependencies: - balanced-match: 4.0.4 - - browserslist@4.28.1: - dependencies: - baseline-browser-mapping: 2.10.0 - caniuse-lite: 1.0.30001774 - electron-to-chromium: 1.5.302 - node-releases: 2.0.27 - update-browserslist-db: 1.2.3(browserslist@4.28.1) - - caniuse-lite@1.0.30001774: {} - - class-variance-authority@0.7.1: - dependencies: - clsx: 2.1.1 - - clsx@2.1.1: {} - - convert-source-map@2.0.0: {} - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - csstype@3.2.3: {} - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - deep-is@0.1.4: {} - - detect-libc@2.1.2: {} - - detect-node-es@1.1.0: {} - - electron-to-chromium@1.5.302: {} - - enhanced-resolve@5.19.0: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.3.0 - - esbuild@0.27.3: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.3 - '@esbuild/android-arm': 0.27.3 - '@esbuild/android-arm64': 0.27.3 - '@esbuild/android-x64': 0.27.3 - '@esbuild/darwin-arm64': 0.27.3 - '@esbuild/darwin-x64': 0.27.3 - '@esbuild/freebsd-arm64': 0.27.3 - '@esbuild/freebsd-x64': 0.27.3 - '@esbuild/linux-arm': 0.27.3 - '@esbuild/linux-arm64': 0.27.3 - '@esbuild/linux-ia32': 0.27.3 - '@esbuild/linux-loong64': 0.27.3 - '@esbuild/linux-mips64el': 0.27.3 - '@esbuild/linux-ppc64': 0.27.3 - '@esbuild/linux-riscv64': 0.27.3 - '@esbuild/linux-s390x': 0.27.3 - '@esbuild/linux-x64': 0.27.3 - '@esbuild/netbsd-arm64': 0.27.3 - '@esbuild/netbsd-x64': 0.27.3 - '@esbuild/openbsd-arm64': 0.27.3 - '@esbuild/openbsd-x64': 0.27.3 - '@esbuild/openharmony-arm64': 0.27.3 - '@esbuild/sunos-x64': 0.27.3 - '@esbuild/win32-arm64': 0.27.3 - '@esbuild/win32-ia32': 0.27.3 - '@esbuild/win32-x64': 0.27.3 - - escalade@3.2.0: {} - - escape-string-regexp@4.0.0: {} - - eslint-plugin-react-hooks@7.0.1(eslint@10.0.2(jiti@2.6.1)): - dependencies: - '@babel/core': 7.29.0 - '@babel/parser': 7.29.0 - eslint: 10.0.2(jiti@2.6.1) - hermes-parser: 0.25.1 - zod: 4.3.6 - zod-validation-error: 4.0.2(zod@4.3.6) - transitivePeerDependencies: - - supports-color - - eslint-plugin-react-refresh@0.5.2(eslint@10.0.2(jiti@2.6.1)): - dependencies: - eslint: 10.0.2(jiti@2.6.1) - - eslint-scope@9.1.1: - dependencies: - '@types/esrecurse': 4.3.1 - '@types/estree': 1.0.8 - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@5.0.1: {} - - eslint@10.0.2(jiti@2.6.1): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.2(jiti@2.6.1)) - '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.23.2 - '@eslint/config-helpers': 0.5.2 - '@eslint/core': 1.1.0 - '@eslint/plugin-kit': 0.6.0 - '@humanfs/node': 0.16.7 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - ajv: 6.14.0 - cross-spawn: 7.0.6 - debug: 4.4.3 - escape-string-regexp: 4.0.0 - eslint-scope: 9.1.1 - eslint-visitor-keys: 5.0.1 - espree: 11.1.1 - esquery: 1.7.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - minimatch: 10.2.3 - natural-compare: 1.4.0 - optionator: 0.9.4 - optionalDependencies: - jiti: 2.6.1 - transitivePeerDependencies: - - supports-color - - espree@11.1.1: - dependencies: - acorn: 8.16.0 - acorn-jsx: 5.3.2(acorn@8.16.0) - eslint-visitor-keys: 5.0.1 - - esquery@1.7.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - esutils@2.0.3: {} - - fast-deep-equal@3.1.3: {} - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fdir@6.5.0(picomatch@4.0.3): - optionalDependencies: - picomatch: 4.0.3 - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@4.0.1: - dependencies: - flatted: 3.3.3 - keyv: 4.5.4 - - flatted@3.3.3: {} - - framer-motion@12.34.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - motion-dom: 12.34.3 - motion-utils: 12.29.2 - tslib: 2.8.1 - optionalDependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - fsevents@2.3.3: - optional: true - - gensync@1.0.0-beta.2: {} - - get-nonce@1.0.1: {} - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - globals@17.3.0: {} - - graceful-fs@4.2.11: {} - - hermes-estree@0.25.1: {} - - hermes-parser@0.25.1: - dependencies: - hermes-estree: 0.25.1 - - ignore@5.3.2: {} - - ignore@7.0.5: {} - - imurmurhash@0.1.4: {} - - is-extglob@2.1.1: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - isexe@2.0.0: {} - - jiti@2.6.1: {} - - js-tokens@4.0.0: {} - - jsesc@3.1.0: {} - - json-buffer@3.0.1: {} - - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - json5@2.2.3: {} - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - lightningcss-android-arm64@1.31.1: - optional: true - - lightningcss-darwin-arm64@1.31.1: - optional: true - - lightningcss-darwin-x64@1.31.1: - optional: true - - lightningcss-freebsd-x64@1.31.1: - optional: true - - lightningcss-linux-arm-gnueabihf@1.31.1: - optional: true - - lightningcss-linux-arm64-gnu@1.31.1: - optional: true - - lightningcss-linux-arm64-musl@1.31.1: - optional: true - - lightningcss-linux-x64-gnu@1.31.1: - optional: true - - lightningcss-linux-x64-musl@1.31.1: - optional: true - - lightningcss-win32-arm64-msvc@1.31.1: - optional: true - - lightningcss-win32-x64-msvc@1.31.1: - optional: true - - lightningcss@1.31.1: - dependencies: - detect-libc: 2.1.2 - optionalDependencies: - lightningcss-android-arm64: 1.31.1 - lightningcss-darwin-arm64: 1.31.1 - lightningcss-darwin-x64: 1.31.1 - lightningcss-freebsd-x64: 1.31.1 - lightningcss-linux-arm-gnueabihf: 1.31.1 - lightningcss-linux-arm64-gnu: 1.31.1 - lightningcss-linux-arm64-musl: 1.31.1 - lightningcss-linux-x64-gnu: 1.31.1 - lightningcss-linux-x64-musl: 1.31.1 - lightningcss-win32-arm64-msvc: 1.31.1 - lightningcss-win32-x64-msvc: 1.31.1 - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 - - lucide-react@0.575.0(react@19.2.4): - dependencies: - react: 19.2.4 - - magic-string@0.30.21: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - - minimatch@10.2.3: - dependencies: - brace-expansion: 5.0.3 - - motion-dom@12.34.3: - dependencies: - motion-utils: 12.29.2 - - motion-utils@12.29.2: {} - - motion@12.34.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - framer-motion: 12.34.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - tslib: 2.8.1 - optionalDependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - ms@2.1.3: {} - - nanoid@3.3.11: {} - - natural-compare@1.4.0: {} - - next-themes@0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - node-releases@2.0.27: {} - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - path-exists@4.0.0: {} - - path-key@3.1.1: {} - - picocolors@1.1.1: {} - - picomatch@4.0.3: {} - - postcss@8.5.6: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - prelude-ls@1.2.1: {} - - punycode@2.3.1: {} - - radix-ui@1.4.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-accessible-icon': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-alert-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-aspect-ratio': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-avatar': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-checkbox': 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context-menu': 2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-form': 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-hover-card': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-label': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-menubar': 1.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-navigation-menu': 1.2.14(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-one-time-password-field': 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-password-toggle-field': 0.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-popover': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-progress': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-radio-group': 1.3.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-scroll-area': 1.2.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-select': 2.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-separator': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slider': 1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-switch': 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-toast': 1.2.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-toggle-group': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-toolbar': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-tooltip': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - react-dom@19.2.4(react@19.2.4): - dependencies: - react: 19.2.4 - scheduler: 0.27.0 - - react-refresh@0.18.0: {} - - react-remove-scroll-bar@2.3.8(@types/react@19.2.14)(react@19.2.4): - dependencies: - react: 19.2.4 - react-style-singleton: 2.2.3(@types/react@19.2.14)(react@19.2.4) - tslib: 2.8.1 - optionalDependencies: - '@types/react': 19.2.14 - - react-remove-scroll@2.7.2(@types/react@19.2.14)(react@19.2.4): - dependencies: - react: 19.2.4 - react-remove-scroll-bar: 2.3.8(@types/react@19.2.14)(react@19.2.4) - react-style-singleton: 2.2.3(@types/react@19.2.14)(react@19.2.4) - tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.2.14)(react@19.2.4) - use-sidecar: 1.1.3(@types/react@19.2.14)(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - - react-style-singleton@2.2.3(@types/react@19.2.14)(react@19.2.4): - dependencies: - get-nonce: 1.0.1 - react: 19.2.4 - tslib: 2.8.1 - optionalDependencies: - '@types/react': 19.2.14 - - react@19.2.4: {} - - rollup@4.59.0: - dependencies: - '@types/estree': 1.0.8 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.59.0 - '@rollup/rollup-android-arm64': 4.59.0 - '@rollup/rollup-darwin-arm64': 4.59.0 - '@rollup/rollup-darwin-x64': 4.59.0 - '@rollup/rollup-freebsd-arm64': 4.59.0 - '@rollup/rollup-freebsd-x64': 4.59.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 - '@rollup/rollup-linux-arm-musleabihf': 4.59.0 - '@rollup/rollup-linux-arm64-gnu': 4.59.0 - '@rollup/rollup-linux-arm64-musl': 4.59.0 - '@rollup/rollup-linux-loong64-gnu': 4.59.0 - '@rollup/rollup-linux-loong64-musl': 4.59.0 - '@rollup/rollup-linux-ppc64-gnu': 4.59.0 - '@rollup/rollup-linux-ppc64-musl': 4.59.0 - '@rollup/rollup-linux-riscv64-gnu': 4.59.0 - '@rollup/rollup-linux-riscv64-musl': 4.59.0 - '@rollup/rollup-linux-s390x-gnu': 4.59.0 - '@rollup/rollup-linux-x64-gnu': 4.59.0 - '@rollup/rollup-linux-x64-musl': 4.59.0 - '@rollup/rollup-openbsd-x64': 4.59.0 - '@rollup/rollup-openharmony-arm64': 4.59.0 - '@rollup/rollup-win32-arm64-msvc': 4.59.0 - '@rollup/rollup-win32-ia32-msvc': 4.59.0 - '@rollup/rollup-win32-x64-gnu': 4.59.0 - '@rollup/rollup-win32-x64-msvc': 4.59.0 - fsevents: 2.3.3 - - scheduler@0.27.0: {} - - semver@6.3.1: {} - - semver@7.7.4: {} - - sharp@0.34.5: - dependencies: - '@img/colour': 1.0.0 - detect-libc: 2.1.2 - semver: 7.7.4 - optionalDependencies: - '@img/sharp-darwin-arm64': 0.34.5 - '@img/sharp-darwin-x64': 0.34.5 - '@img/sharp-libvips-darwin-arm64': 1.2.4 - '@img/sharp-libvips-darwin-x64': 1.2.4 - '@img/sharp-libvips-linux-arm': 1.2.4 - '@img/sharp-libvips-linux-arm64': 1.2.4 - '@img/sharp-libvips-linux-ppc64': 1.2.4 - '@img/sharp-libvips-linux-riscv64': 1.2.4 - '@img/sharp-libvips-linux-s390x': 1.2.4 - '@img/sharp-libvips-linux-x64': 1.2.4 - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 - '@img/sharp-linux-arm': 0.34.5 - '@img/sharp-linux-arm64': 0.34.5 - '@img/sharp-linux-ppc64': 0.34.5 - '@img/sharp-linux-riscv64': 0.34.5 - '@img/sharp-linux-s390x': 0.34.5 - '@img/sharp-linux-x64': 0.34.5 - '@img/sharp-linuxmusl-arm64': 0.34.5 - '@img/sharp-linuxmusl-x64': 0.34.5 - '@img/sharp-wasm32': 0.34.5 - '@img/sharp-win32-arm64': 0.34.5 - '@img/sharp-win32-ia32': 0.34.5 - '@img/sharp-win32-x64': 0.34.5 - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - sonner@2.0.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - source-map-js@1.2.1: {} - - tailwind-merge@3.5.0: {} - - tailwindcss@4.2.1: {} - - tapable@2.3.0: {} - - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - - ts-api-utils@2.4.0(typescript@5.9.3): - dependencies: - typescript: 5.9.3 - - tslib@2.8.1: {} - - tw-animate-css@1.4.0: {} - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - typescript-eslint@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) - eslint: 10.0.2(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - typescript@5.9.3: {} - - undici-types@7.18.2: {} - - update-browserslist-db@1.2.3(browserslist@4.28.1): - dependencies: - browserslist: 4.28.1 - escalade: 3.2.0 - picocolors: 1.1.1 - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - use-callback-ref@1.3.3(@types/react@19.2.14)(react@19.2.4): - dependencies: - react: 19.2.4 - tslib: 2.8.1 - optionalDependencies: - '@types/react': 19.2.14 - - use-sidecar@1.1.3(@types/react@19.2.14)(react@19.2.4): - dependencies: - detect-node-es: 1.1.0 - react: 19.2.4 - tslib: 2.8.1 - optionalDependencies: - '@types/react': 19.2.14 - - use-sync-external-store@1.6.0(react@19.2.4): - dependencies: - react: 19.2.4 - - vite@7.3.1(@types/node@25.3.0)(jiti@2.6.1)(lightningcss@1.31.1): - dependencies: - esbuild: 0.27.3 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.59.0 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 25.3.0 - fsevents: 2.3.3 - jiti: 2.6.1 - lightningcss: 1.31.1 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - word-wrap@1.2.5: {} - - yallist@3.1.1: {} - - yocto-queue@0.1.0: {} - - zod-validation-error@4.0.2(zod@4.3.6): - dependencies: - zod: 4.3.6 - - zod@4.3.6: {} diff --git a/frontend/public/assets/flags/ad.svg b/frontend/public/assets/flags/ad.svg deleted file mode 100644 index 199ff19..0000000 --- a/frontend/public/assets/flags/ad.svg +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ae.svg b/frontend/public/assets/flags/ae.svg deleted file mode 100644 index 651ac85..0000000 --- a/frontend/public/assets/flags/ae.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/af.svg b/frontend/public/assets/flags/af.svg deleted file mode 100644 index 4dbe455..0000000 --- a/frontend/public/assets/flags/af.svg +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ag.svg b/frontend/public/assets/flags/ag.svg deleted file mode 100644 index 243c3d8..0000000 --- a/frontend/public/assets/flags/ag.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ai.svg b/frontend/public/assets/flags/ai.svg deleted file mode 100644 index 9c2ea33..0000000 --- a/frontend/public/assets/flags/ai.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/al.svg b/frontend/public/assets/flags/al.svg deleted file mode 100644 index e85d95f..0000000 --- a/frontend/public/assets/flags/al.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/am.svg b/frontend/public/assets/flags/am.svg deleted file mode 100644 index 99fa4dc..0000000 --- a/frontend/public/assets/flags/am.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/ao.svg b/frontend/public/assets/flags/ao.svg deleted file mode 100644 index b73b1ec..0000000 --- a/frontend/public/assets/flags/ao.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/aq.svg b/frontend/public/assets/flags/aq.svg deleted file mode 100644 index c7e3536..0000000 --- a/frontend/public/assets/flags/aq.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/ar.svg b/frontend/public/assets/flags/ar.svg deleted file mode 100644 index c753da1..0000000 --- a/frontend/public/assets/flags/ar.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/arab.svg b/frontend/public/assets/flags/arab.svg deleted file mode 100644 index 9ef079f..0000000 --- a/frontend/public/assets/flags/arab.svg +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/as.svg b/frontend/public/assets/flags/as.svg deleted file mode 100644 index 82459de..0000000 --- a/frontend/public/assets/flags/as.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/asean.svg b/frontend/public/assets/flags/asean.svg deleted file mode 100644 index 189ae02..0000000 --- a/frontend/public/assets/flags/asean.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/at.svg b/frontend/public/assets/flags/at.svg deleted file mode 100644 index 9d2775c..0000000 --- a/frontend/public/assets/flags/at.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/au.svg b/frontend/public/assets/flags/au.svg deleted file mode 100644 index 96e8076..0000000 --- a/frontend/public/assets/flags/au.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/aw.svg b/frontend/public/assets/flags/aw.svg deleted file mode 100644 index 413b7c4..0000000 --- a/frontend/public/assets/flags/aw.svg +++ /dev/null @@ -1,186 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ax.svg b/frontend/public/assets/flags/ax.svg deleted file mode 100644 index 0584d71..0000000 --- a/frontend/public/assets/flags/ax.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/az.svg b/frontend/public/assets/flags/az.svg deleted file mode 100644 index 3557522..0000000 --- a/frontend/public/assets/flags/az.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/ba.svg b/frontend/public/assets/flags/ba.svg deleted file mode 100644 index 93bd9cf..0000000 --- a/frontend/public/assets/flags/ba.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/bb.svg b/frontend/public/assets/flags/bb.svg deleted file mode 100644 index cecd5cc..0000000 --- a/frontend/public/assets/flags/bb.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/bd.svg b/frontend/public/assets/flags/bd.svg deleted file mode 100644 index 16b794d..0000000 --- a/frontend/public/assets/flags/bd.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/be.svg b/frontend/public/assets/flags/be.svg deleted file mode 100644 index ac706a0..0000000 --- a/frontend/public/assets/flags/be.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/bf.svg b/frontend/public/assets/flags/bf.svg deleted file mode 100644 index 4713822..0000000 --- a/frontend/public/assets/flags/bf.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/bg.svg b/frontend/public/assets/flags/bg.svg deleted file mode 100644 index af2d0d0..0000000 --- a/frontend/public/assets/flags/bg.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/bh.svg b/frontend/public/assets/flags/bh.svg deleted file mode 100644 index 7a2ea54..0000000 --- a/frontend/public/assets/flags/bh.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/bi.svg b/frontend/public/assets/flags/bi.svg deleted file mode 100644 index a4434a9..0000000 --- a/frontend/public/assets/flags/bi.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/bj.svg b/frontend/public/assets/flags/bj.svg deleted file mode 100644 index 0846724..0000000 --- a/frontend/public/assets/flags/bj.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/bl.svg b/frontend/public/assets/flags/bl.svg deleted file mode 100644 index f84cbba..0000000 --- a/frontend/public/assets/flags/bl.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/bm.svg b/frontend/public/assets/flags/bm.svg deleted file mode 100644 index f43a5eb..0000000 --- a/frontend/public/assets/flags/bm.svg +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/bn.svg b/frontend/public/assets/flags/bn.svg deleted file mode 100644 index f544c25..0000000 --- a/frontend/public/assets/flags/bn.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/bo.svg b/frontend/public/assets/flags/bo.svg deleted file mode 100644 index 7658e3f..0000000 --- a/frontend/public/assets/flags/bo.svg +++ /dev/null @@ -1,673 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/bq.svg b/frontend/public/assets/flags/bq.svg deleted file mode 100644 index 0e6bc76..0000000 --- a/frontend/public/assets/flags/bq.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/br.svg b/frontend/public/assets/flags/br.svg deleted file mode 100644 index 719a763..0000000 --- a/frontend/public/assets/flags/br.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/bs.svg b/frontend/public/assets/flags/bs.svg deleted file mode 100644 index 5cc918e..0000000 --- a/frontend/public/assets/flags/bs.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/bt.svg b/frontend/public/assets/flags/bt.svg deleted file mode 100644 index 20aef3a..0000000 --- a/frontend/public/assets/flags/bt.svg +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/bv.svg b/frontend/public/assets/flags/bv.svg deleted file mode 100644 index 40e16d9..0000000 --- a/frontend/public/assets/flags/bv.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/bw.svg b/frontend/public/assets/flags/bw.svg deleted file mode 100644 index 3435608..0000000 --- a/frontend/public/assets/flags/bw.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/by.svg b/frontend/public/assets/flags/by.svg deleted file mode 100644 index 948784f..0000000 --- a/frontend/public/assets/flags/by.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/bz.svg b/frontend/public/assets/flags/bz.svg deleted file mode 100644 index d81b16c..0000000 --- a/frontend/public/assets/flags/bz.svg +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ca.svg b/frontend/public/assets/flags/ca.svg deleted file mode 100644 index c9b23b4..0000000 --- a/frontend/public/assets/flags/ca.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/cc.svg b/frontend/public/assets/flags/cc.svg deleted file mode 100644 index a42dec6..0000000 --- a/frontend/public/assets/flags/cc.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/cd.svg b/frontend/public/assets/flags/cd.svg deleted file mode 100644 index b9cf528..0000000 --- a/frontend/public/assets/flags/cd.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/cefta.svg b/frontend/public/assets/flags/cefta.svg deleted file mode 100644 index f748d08..0000000 --- a/frontend/public/assets/flags/cefta.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/cf.svg b/frontend/public/assets/flags/cf.svg deleted file mode 100644 index a6cd367..0000000 --- a/frontend/public/assets/flags/cf.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/cg.svg b/frontend/public/assets/flags/cg.svg deleted file mode 100644 index f5a0e42..0000000 --- a/frontend/public/assets/flags/cg.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ch.svg b/frontend/public/assets/flags/ch.svg deleted file mode 100644 index b42d670..0000000 --- a/frontend/public/assets/flags/ch.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/public/assets/flags/ci.svg b/frontend/public/assets/flags/ci.svg deleted file mode 100644 index e400f0c..0000000 --- a/frontend/public/assets/flags/ci.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/ck.svg b/frontend/public/assets/flags/ck.svg deleted file mode 100644 index 18e547b..0000000 --- a/frontend/public/assets/flags/ck.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/public/assets/flags/cl.svg b/frontend/public/assets/flags/cl.svg deleted file mode 100644 index 5b3c72f..0000000 --- a/frontend/public/assets/flags/cl.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/cm.svg b/frontend/public/assets/flags/cm.svg deleted file mode 100644 index 70adc8b..0000000 --- a/frontend/public/assets/flags/cm.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/cn.svg b/frontend/public/assets/flags/cn.svg deleted file mode 100644 index 10d3489..0000000 --- a/frontend/public/assets/flags/cn.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/frontend/public/assets/flags/co.svg b/frontend/public/assets/flags/co.svg deleted file mode 100644 index ebd0a0f..0000000 --- a/frontend/public/assets/flags/co.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/cp.svg b/frontend/public/assets/flags/cp.svg deleted file mode 100644 index b8aa9cf..0000000 --- a/frontend/public/assets/flags/cp.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/cr.svg b/frontend/public/assets/flags/cr.svg deleted file mode 100644 index 5a409ee..0000000 --- a/frontend/public/assets/flags/cr.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/cu.svg b/frontend/public/assets/flags/cu.svg deleted file mode 100644 index 053c9ee..0000000 --- a/frontend/public/assets/flags/cu.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/cv.svg b/frontend/public/assets/flags/cv.svg deleted file mode 100644 index aec8994..0000000 --- a/frontend/public/assets/flags/cv.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/cw.svg b/frontend/public/assets/flags/cw.svg deleted file mode 100644 index bb0ece2..0000000 --- a/frontend/public/assets/flags/cw.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/cx.svg b/frontend/public/assets/flags/cx.svg deleted file mode 100644 index 3a83c23..0000000 --- a/frontend/public/assets/flags/cx.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/cy.svg b/frontend/public/assets/flags/cy.svg deleted file mode 100644 index ee4b0c7..0000000 --- a/frontend/public/assets/flags/cy.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/cz.svg b/frontend/public/assets/flags/cz.svg deleted file mode 100644 index 7913de3..0000000 --- a/frontend/public/assets/flags/cz.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/de.svg b/frontend/public/assets/flags/de.svg deleted file mode 100644 index 71aa2d2..0000000 --- a/frontend/public/assets/flags/de.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/dg.svg b/frontend/public/assets/flags/dg.svg deleted file mode 100644 index dfee2bb..0000000 --- a/frontend/public/assets/flags/dg.svg +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/dj.svg b/frontend/public/assets/flags/dj.svg deleted file mode 100644 index 9b00a82..0000000 --- a/frontend/public/assets/flags/dj.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/dk.svg b/frontend/public/assets/flags/dk.svg deleted file mode 100644 index 563277f..0000000 --- a/frontend/public/assets/flags/dk.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/dm.svg b/frontend/public/assets/flags/dm.svg deleted file mode 100644 index 5aa9cea..0000000 --- a/frontend/public/assets/flags/dm.svg +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/do.svg b/frontend/public/assets/flags/do.svg deleted file mode 100644 index 6de2b26..0000000 --- a/frontend/public/assets/flags/do.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/dz.svg b/frontend/public/assets/flags/dz.svg deleted file mode 100644 index 5ff29a7..0000000 --- a/frontend/public/assets/flags/dz.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/eac.svg b/frontend/public/assets/flags/eac.svg deleted file mode 100644 index 59d02d2..0000000 --- a/frontend/public/assets/flags/eac.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ec.svg b/frontend/public/assets/flags/ec.svg deleted file mode 100644 index 88c50bf..0000000 --- a/frontend/public/assets/flags/ec.svg +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ee.svg b/frontend/public/assets/flags/ee.svg deleted file mode 100644 index 8b98c2c..0000000 --- a/frontend/public/assets/flags/ee.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/eg.svg b/frontend/public/assets/flags/eg.svg deleted file mode 100644 index 88e32b3..0000000 --- a/frontend/public/assets/flags/eg.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/eh.svg b/frontend/public/assets/flags/eh.svg deleted file mode 100644 index 6aec728..0000000 --- a/frontend/public/assets/flags/eh.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/er.svg b/frontend/public/assets/flags/er.svg deleted file mode 100644 index 48a13b4..0000000 --- a/frontend/public/assets/flags/er.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/es-ct.svg b/frontend/public/assets/flags/es-ct.svg deleted file mode 100644 index 4d85911..0000000 --- a/frontend/public/assets/flags/es-ct.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/es-ga.svg b/frontend/public/assets/flags/es-ga.svg deleted file mode 100644 index 573ca45..0000000 --- a/frontend/public/assets/flags/es-ga.svg +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/es-pv.svg b/frontend/public/assets/flags/es-pv.svg deleted file mode 100644 index 63c19f4..0000000 --- a/frontend/public/assets/flags/es-pv.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/es.svg b/frontend/public/assets/flags/es.svg deleted file mode 100644 index a296ebf..0000000 --- a/frontend/public/assets/flags/es.svg +++ /dev/null @@ -1,544 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/et.svg b/frontend/public/assets/flags/et.svg deleted file mode 100644 index 3f99be4..0000000 --- a/frontend/public/assets/flags/et.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/eu.svg b/frontend/public/assets/flags/eu.svg deleted file mode 100644 index b0874c1..0000000 --- a/frontend/public/assets/flags/eu.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/fi.svg b/frontend/public/assets/flags/fi.svg deleted file mode 100644 index 470be2d..0000000 --- a/frontend/public/assets/flags/fi.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/fj.svg b/frontend/public/assets/flags/fj.svg deleted file mode 100644 index 332ae61..0000000 --- a/frontend/public/assets/flags/fj.svg +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/fk.svg b/frontend/public/assets/flags/fk.svg deleted file mode 100644 index a0dace8..0000000 --- a/frontend/public/assets/flags/fk.svg +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/fm.svg b/frontend/public/assets/flags/fm.svg deleted file mode 100644 index c1b7c97..0000000 --- a/frontend/public/assets/flags/fm.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/frontend/public/assets/flags/fo.svg b/frontend/public/assets/flags/fo.svg deleted file mode 100644 index f802d28..0000000 --- a/frontend/public/assets/flags/fo.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/fr.svg b/frontend/public/assets/flags/fr.svg deleted file mode 100644 index e682b90..0000000 --- a/frontend/public/assets/flags/fr.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/ga.svg b/frontend/public/assets/flags/ga.svg deleted file mode 100644 index 76edab4..0000000 --- a/frontend/public/assets/flags/ga.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/gb-eng.svg b/frontend/public/assets/flags/gb-eng.svg deleted file mode 100644 index 12e3b67..0000000 --- a/frontend/public/assets/flags/gb-eng.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/gb-nir.svg b/frontend/public/assets/flags/gb-nir.svg deleted file mode 100644 index e22190a..0000000 --- a/frontend/public/assets/flags/gb-nir.svg +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/gb-sct.svg b/frontend/public/assets/flags/gb-sct.svg deleted file mode 100644 index f50cd32..0000000 --- a/frontend/public/assets/flags/gb-sct.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/gb-wls.svg b/frontend/public/assets/flags/gb-wls.svg deleted file mode 100644 index d7f5791..0000000 --- a/frontend/public/assets/flags/gb-wls.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/public/assets/flags/gb.svg b/frontend/public/assets/flags/gb.svg deleted file mode 100644 index 7991383..0000000 --- a/frontend/public/assets/flags/gb.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/gd.svg b/frontend/public/assets/flags/gd.svg deleted file mode 100644 index b3d250d..0000000 --- a/frontend/public/assets/flags/gd.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ge.svg b/frontend/public/assets/flags/ge.svg deleted file mode 100644 index ab08a9a..0000000 --- a/frontend/public/assets/flags/ge.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/gf.svg b/frontend/public/assets/flags/gf.svg deleted file mode 100644 index f8fe94c..0000000 --- a/frontend/public/assets/flags/gf.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/gg.svg b/frontend/public/assets/flags/gg.svg deleted file mode 100644 index f8216c8..0000000 --- a/frontend/public/assets/flags/gg.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/public/assets/flags/gh.svg b/frontend/public/assets/flags/gh.svg deleted file mode 100644 index 5c3e3e6..0000000 --- a/frontend/public/assets/flags/gh.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/gi.svg b/frontend/public/assets/flags/gi.svg deleted file mode 100644 index a5d7570..0000000 --- a/frontend/public/assets/flags/gi.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/gl.svg b/frontend/public/assets/flags/gl.svg deleted file mode 100644 index eb5a52e..0000000 --- a/frontend/public/assets/flags/gl.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/gm.svg b/frontend/public/assets/flags/gm.svg deleted file mode 100644 index 8fe9d66..0000000 --- a/frontend/public/assets/flags/gm.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/gn.svg b/frontend/public/assets/flags/gn.svg deleted file mode 100644 index 40d6ad4..0000000 --- a/frontend/public/assets/flags/gn.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/gp.svg b/frontend/public/assets/flags/gp.svg deleted file mode 100644 index ee55c4b..0000000 --- a/frontend/public/assets/flags/gp.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/gq.svg b/frontend/public/assets/flags/gq.svg deleted file mode 100644 index 64c8eb2..0000000 --- a/frontend/public/assets/flags/gq.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/gr.svg b/frontend/public/assets/flags/gr.svg deleted file mode 100644 index 599741e..0000000 --- a/frontend/public/assets/flags/gr.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/gs.svg b/frontend/public/assets/flags/gs.svg deleted file mode 100644 index 29db9b9..0000000 --- a/frontend/public/assets/flags/gs.svg +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/gt.svg b/frontend/public/assets/flags/gt.svg deleted file mode 100644 index 7df9df5..0000000 --- a/frontend/public/assets/flags/gt.svg +++ /dev/null @@ -1,204 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/gu.svg b/frontend/public/assets/flags/gu.svg deleted file mode 100644 index 3b95219..0000000 --- a/frontend/public/assets/flags/gu.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/gw.svg b/frontend/public/assets/flags/gw.svg deleted file mode 100644 index d470bac..0000000 --- a/frontend/public/assets/flags/gw.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/gy.svg b/frontend/public/assets/flags/gy.svg deleted file mode 100644 index 569fb56..0000000 --- a/frontend/public/assets/flags/gy.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/public/assets/flags/hk.svg b/frontend/public/assets/flags/hk.svg deleted file mode 100644 index 4fd55bc..0000000 --- a/frontend/public/assets/flags/hk.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/hm.svg b/frontend/public/assets/flags/hm.svg deleted file mode 100644 index 815c482..0000000 --- a/frontend/public/assets/flags/hm.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/hn.svg b/frontend/public/assets/flags/hn.svg deleted file mode 100644 index 11fde67..0000000 --- a/frontend/public/assets/flags/hn.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/hr.svg b/frontend/public/assets/flags/hr.svg deleted file mode 100644 index dde825c..0000000 --- a/frontend/public/assets/flags/hr.svg +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ht.svg b/frontend/public/assets/flags/ht.svg deleted file mode 100644 index 8e8efc4..0000000 --- a/frontend/public/assets/flags/ht.svg +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/hu.svg b/frontend/public/assets/flags/hu.svg deleted file mode 100644 index 24fbfb9..0000000 --- a/frontend/public/assets/flags/hu.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/ic.svg b/frontend/public/assets/flags/ic.svg deleted file mode 100644 index 81e6ee2..0000000 --- a/frontend/public/assets/flags/ic.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/id.svg b/frontend/public/assets/flags/id.svg deleted file mode 100644 index 3b7c8fc..0000000 --- a/frontend/public/assets/flags/id.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/ie.svg b/frontend/public/assets/flags/ie.svg deleted file mode 100644 index 049be14..0000000 --- a/frontend/public/assets/flags/ie.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/il.svg b/frontend/public/assets/flags/il.svg deleted file mode 100644 index f43be7e..0000000 --- a/frontend/public/assets/flags/il.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/im.svg b/frontend/public/assets/flags/im.svg deleted file mode 100644 index fe6a59a..0000000 --- a/frontend/public/assets/flags/im.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/in.svg b/frontend/public/assets/flags/in.svg deleted file mode 100644 index bc47d74..0000000 --- a/frontend/public/assets/flags/in.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/io.svg b/frontend/public/assets/flags/io.svg deleted file mode 100644 index 3058f7d..0000000 --- a/frontend/public/assets/flags/io.svg +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/iq.svg b/frontend/public/assets/flags/iq.svg deleted file mode 100644 index 8044514..0000000 --- a/frontend/public/assets/flags/iq.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/frontend/public/assets/flags/ir.svg b/frontend/public/assets/flags/ir.svg deleted file mode 100644 index 8c6d516..0000000 --- a/frontend/public/assets/flags/ir.svg +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/is.svg b/frontend/public/assets/flags/is.svg deleted file mode 100644 index a6588af..0000000 --- a/frontend/public/assets/flags/is.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/it.svg b/frontend/public/assets/flags/it.svg deleted file mode 100644 index 20a8bfd..0000000 --- a/frontend/public/assets/flags/it.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/je.svg b/frontend/public/assets/flags/je.svg deleted file mode 100644 index 70a8754..0000000 --- a/frontend/public/assets/flags/je.svg +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/jm.svg b/frontend/public/assets/flags/jm.svg deleted file mode 100644 index 269df03..0000000 --- a/frontend/public/assets/flags/jm.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/jo.svg b/frontend/public/assets/flags/jo.svg deleted file mode 100644 index d6f927d..0000000 --- a/frontend/public/assets/flags/jo.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/jp.svg b/frontend/public/assets/flags/jp.svg deleted file mode 100644 index cc1c181..0000000 --- a/frontend/public/assets/flags/jp.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ke.svg b/frontend/public/assets/flags/ke.svg deleted file mode 100644 index 3a67ca3..0000000 --- a/frontend/public/assets/flags/ke.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/kg.svg b/frontend/public/assets/flags/kg.svg deleted file mode 100644 index e26db95..0000000 --- a/frontend/public/assets/flags/kg.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/kh.svg b/frontend/public/assets/flags/kh.svg deleted file mode 100644 index a7d52f2..0000000 --- a/frontend/public/assets/flags/kh.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ki.svg b/frontend/public/assets/flags/ki.svg deleted file mode 100644 index fda03f3..0000000 --- a/frontend/public/assets/flags/ki.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/km.svg b/frontend/public/assets/flags/km.svg deleted file mode 100644 index 414d65e..0000000 --- a/frontend/public/assets/flags/km.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/kn.svg b/frontend/public/assets/flags/kn.svg deleted file mode 100644 index 47fe64d..0000000 --- a/frontend/public/assets/flags/kn.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/kp.svg b/frontend/public/assets/flags/kp.svg deleted file mode 100644 index ad1b713..0000000 --- a/frontend/public/assets/flags/kp.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/kr.svg b/frontend/public/assets/flags/kr.svg deleted file mode 100644 index 6947eab..0000000 --- a/frontend/public/assets/flags/kr.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/kw.svg b/frontend/public/assets/flags/kw.svg deleted file mode 100644 index 3dd89e9..0000000 --- a/frontend/public/assets/flags/kw.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ky.svg b/frontend/public/assets/flags/ky.svg deleted file mode 100644 index aeaa7e0..0000000 --- a/frontend/public/assets/flags/ky.svg +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/kz.svg b/frontend/public/assets/flags/kz.svg deleted file mode 100644 index 2fac45b..0000000 --- a/frontend/public/assets/flags/kz.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/la.svg b/frontend/public/assets/flags/la.svg deleted file mode 100644 index 6aea6b7..0000000 --- a/frontend/public/assets/flags/la.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/lb.svg b/frontend/public/assets/flags/lb.svg deleted file mode 100644 index bde2581..0000000 --- a/frontend/public/assets/flags/lb.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/lc.svg b/frontend/public/assets/flags/lc.svg deleted file mode 100644 index bb25654..0000000 --- a/frontend/public/assets/flags/lc.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/li.svg b/frontend/public/assets/flags/li.svg deleted file mode 100644 index 7a4d183..0000000 --- a/frontend/public/assets/flags/li.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/lk.svg b/frontend/public/assets/flags/lk.svg deleted file mode 100644 index cbd660a..0000000 --- a/frontend/public/assets/flags/lk.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/lr.svg b/frontend/public/assets/flags/lr.svg deleted file mode 100644 index e482ab9..0000000 --- a/frontend/public/assets/flags/lr.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ls.svg b/frontend/public/assets/flags/ls.svg deleted file mode 100644 index a7c01a9..0000000 --- a/frontend/public/assets/flags/ls.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/lt.svg b/frontend/public/assets/flags/lt.svg deleted file mode 100644 index 90ec5d2..0000000 --- a/frontend/public/assets/flags/lt.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/lu.svg b/frontend/public/assets/flags/lu.svg deleted file mode 100644 index cc12206..0000000 --- a/frontend/public/assets/flags/lu.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/lv.svg b/frontend/public/assets/flags/lv.svg deleted file mode 100644 index f6decec..0000000 --- a/frontend/public/assets/flags/lv.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/ly.svg b/frontend/public/assets/flags/ly.svg deleted file mode 100644 index 1eaa51e..0000000 --- a/frontend/public/assets/flags/ly.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ma.svg b/frontend/public/assets/flags/ma.svg deleted file mode 100644 index 7ce56ef..0000000 --- a/frontend/public/assets/flags/ma.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/mc.svg b/frontend/public/assets/flags/mc.svg deleted file mode 100644 index 9cb6c9e..0000000 --- a/frontend/public/assets/flags/mc.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/md.svg b/frontend/public/assets/flags/md.svg deleted file mode 100644 index e9ba506..0000000 --- a/frontend/public/assets/flags/md.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/me.svg b/frontend/public/assets/flags/me.svg deleted file mode 100644 index 297888c..0000000 --- a/frontend/public/assets/flags/me.svg +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/mf.svg b/frontend/public/assets/flags/mf.svg deleted file mode 100644 index 6305edc..0000000 --- a/frontend/public/assets/flags/mf.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/mg.svg b/frontend/public/assets/flags/mg.svg deleted file mode 100644 index 5fa2d24..0000000 --- a/frontend/public/assets/flags/mg.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/mh.svg b/frontend/public/assets/flags/mh.svg deleted file mode 100644 index 7b9f490..0000000 --- a/frontend/public/assets/flags/mh.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/mk.svg b/frontend/public/assets/flags/mk.svg deleted file mode 100644 index 4f5cae7..0000000 --- a/frontend/public/assets/flags/mk.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/ml.svg b/frontend/public/assets/flags/ml.svg deleted file mode 100644 index 6f6b716..0000000 --- a/frontend/public/assets/flags/ml.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/mm.svg b/frontend/public/assets/flags/mm.svg deleted file mode 100644 index 42b4dee..0000000 --- a/frontend/public/assets/flags/mm.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/mn.svg b/frontend/public/assets/flags/mn.svg deleted file mode 100644 index 6a38a71..0000000 --- a/frontend/public/assets/flags/mn.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/mo.svg b/frontend/public/assets/flags/mo.svg deleted file mode 100644 index f638b6c..0000000 --- a/frontend/public/assets/flags/mo.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/public/assets/flags/mp.svg b/frontend/public/assets/flags/mp.svg deleted file mode 100644 index 26bfa22..0000000 --- a/frontend/public/assets/flags/mp.svg +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/mq.svg b/frontend/public/assets/flags/mq.svg deleted file mode 100644 index b221951..0000000 --- a/frontend/public/assets/flags/mq.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/mr.svg b/frontend/public/assets/flags/mr.svg deleted file mode 100644 index d859972..0000000 --- a/frontend/public/assets/flags/mr.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/ms.svg b/frontend/public/assets/flags/ms.svg deleted file mode 100644 index 4367505..0000000 --- a/frontend/public/assets/flags/ms.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/mt.svg b/frontend/public/assets/flags/mt.svg deleted file mode 100644 index 5d5d7c8..0000000 --- a/frontend/public/assets/flags/mt.svg +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/mu.svg b/frontend/public/assets/flags/mu.svg deleted file mode 100644 index 82d7a3b..0000000 --- a/frontend/public/assets/flags/mu.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/mv.svg b/frontend/public/assets/flags/mv.svg deleted file mode 100644 index 10450f9..0000000 --- a/frontend/public/assets/flags/mv.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/mw.svg b/frontend/public/assets/flags/mw.svg deleted file mode 100644 index 137ff87..0000000 --- a/frontend/public/assets/flags/mw.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/frontend/public/assets/flags/mx.svg b/frontend/public/assets/flags/mx.svg deleted file mode 100644 index e3ec2bc..0000000 --- a/frontend/public/assets/flags/mx.svg +++ /dev/null @@ -1,382 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/my.svg b/frontend/public/assets/flags/my.svg deleted file mode 100644 index 115f864..0000000 --- a/frontend/public/assets/flags/my.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/mz.svg b/frontend/public/assets/flags/mz.svg deleted file mode 100644 index 0f94c3a..0000000 --- a/frontend/public/assets/flags/mz.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/na.svg b/frontend/public/assets/flags/na.svg deleted file mode 100644 index 35b9f78..0000000 --- a/frontend/public/assets/flags/na.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/nc.svg b/frontend/public/assets/flags/nc.svg deleted file mode 100644 index fa15551..0000000 --- a/frontend/public/assets/flags/nc.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ne.svg b/frontend/public/assets/flags/ne.svg deleted file mode 100644 index 39a82b8..0000000 --- a/frontend/public/assets/flags/ne.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/nf.svg b/frontend/public/assets/flags/nf.svg deleted file mode 100644 index fd61b25..0000000 --- a/frontend/public/assets/flags/nf.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/public/assets/flags/ng.svg b/frontend/public/assets/flags/ng.svg deleted file mode 100644 index 81eb35f..0000000 --- a/frontend/public/assets/flags/ng.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/ni.svg b/frontend/public/assets/flags/ni.svg deleted file mode 100644 index e4861f5..0000000 --- a/frontend/public/assets/flags/ni.svg +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/nl.svg b/frontend/public/assets/flags/nl.svg deleted file mode 100644 index e90f5b0..0000000 --- a/frontend/public/assets/flags/nl.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/no.svg b/frontend/public/assets/flags/no.svg deleted file mode 100644 index a5f2a15..0000000 --- a/frontend/public/assets/flags/no.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/np.svg b/frontend/public/assets/flags/np.svg deleted file mode 100644 index 6242856..0000000 --- a/frontend/public/assets/flags/np.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/nr.svg b/frontend/public/assets/flags/nr.svg deleted file mode 100644 index ff394c4..0000000 --- a/frontend/public/assets/flags/nr.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/nu.svg b/frontend/public/assets/flags/nu.svg deleted file mode 100644 index 4067baf..0000000 --- a/frontend/public/assets/flags/nu.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/frontend/public/assets/flags/nz.svg b/frontend/public/assets/flags/nz.svg deleted file mode 100644 index 935d8a7..0000000 --- a/frontend/public/assets/flags/nz.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/om.svg b/frontend/public/assets/flags/om.svg deleted file mode 100644 index 4f1461a..0000000 --- a/frontend/public/assets/flags/om.svg +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/pa.svg b/frontend/public/assets/flags/pa.svg deleted file mode 100644 index 9ab733f..0000000 --- a/frontend/public/assets/flags/pa.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/pc.svg b/frontend/public/assets/flags/pc.svg deleted file mode 100644 index 5202d6d..0000000 --- a/frontend/public/assets/flags/pc.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/pe.svg b/frontend/public/assets/flags/pe.svg deleted file mode 100644 index 33e6cfd..0000000 --- a/frontend/public/assets/flags/pe.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/pf.svg b/frontend/public/assets/flags/pf.svg deleted file mode 100644 index bea0354..0000000 --- a/frontend/public/assets/flags/pf.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/pg.svg b/frontend/public/assets/flags/pg.svg deleted file mode 100644 index 7b7e77a..0000000 --- a/frontend/public/assets/flags/pg.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/public/assets/flags/ph.svg b/frontend/public/assets/flags/ph.svg deleted file mode 100644 index b910e24..0000000 --- a/frontend/public/assets/flags/ph.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/pk.svg b/frontend/public/assets/flags/pk.svg deleted file mode 100644 index 4ddc19f..0000000 --- a/frontend/public/assets/flags/pk.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/pl.svg b/frontend/public/assets/flags/pl.svg deleted file mode 100644 index 42d2b0c..0000000 --- a/frontend/public/assets/flags/pl.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/pm.svg b/frontend/public/assets/flags/pm.svg deleted file mode 100644 index 19a9330..0000000 --- a/frontend/public/assets/flags/pm.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/pn.svg b/frontend/public/assets/flags/pn.svg deleted file mode 100644 index 209ea71..0000000 --- a/frontend/public/assets/flags/pn.svg +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/pr.svg b/frontend/public/assets/flags/pr.svg deleted file mode 100644 index ec51831..0000000 --- a/frontend/public/assets/flags/pr.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ps.svg b/frontend/public/assets/flags/ps.svg deleted file mode 100644 index 362d435..0000000 --- a/frontend/public/assets/flags/ps.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/pt.svg b/frontend/public/assets/flags/pt.svg deleted file mode 100644 index 2767cd4..0000000 --- a/frontend/public/assets/flags/pt.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/pw.svg b/frontend/public/assets/flags/pw.svg deleted file mode 100644 index 9f89c5f..0000000 --- a/frontend/public/assets/flags/pw.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/frontend/public/assets/flags/py.svg b/frontend/public/assets/flags/py.svg deleted file mode 100644 index abccd87..0000000 --- a/frontend/public/assets/flags/py.svg +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/qa.svg b/frontend/public/assets/flags/qa.svg deleted file mode 100644 index 901f3fa..0000000 --- a/frontend/public/assets/flags/qa.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/re.svg b/frontend/public/assets/flags/re.svg deleted file mode 100644 index 64e788e..0000000 --- a/frontend/public/assets/flags/re.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/ro.svg b/frontend/public/assets/flags/ro.svg deleted file mode 100644 index fda0f7b..0000000 --- a/frontend/public/assets/flags/ro.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/rs.svg b/frontend/public/assets/flags/rs.svg deleted file mode 100644 index 6d4f74d..0000000 --- a/frontend/public/assets/flags/rs.svg +++ /dev/null @@ -1,292 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ru.svg b/frontend/public/assets/flags/ru.svg deleted file mode 100644 index cf24301..0000000 --- a/frontend/public/assets/flags/ru.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/rw.svg b/frontend/public/assets/flags/rw.svg deleted file mode 100644 index 06e26ae..0000000 --- a/frontend/public/assets/flags/rw.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sa.svg b/frontend/public/assets/flags/sa.svg deleted file mode 100644 index 596cf48..0000000 --- a/frontend/public/assets/flags/sa.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sb.svg b/frontend/public/assets/flags/sb.svg deleted file mode 100644 index 6066f94..0000000 --- a/frontend/public/assets/flags/sb.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sc.svg b/frontend/public/assets/flags/sc.svg deleted file mode 100644 index 9a46b36..0000000 --- a/frontend/public/assets/flags/sc.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/sd.svg b/frontend/public/assets/flags/sd.svg deleted file mode 100644 index 12818b4..0000000 --- a/frontend/public/assets/flags/sd.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/se.svg b/frontend/public/assets/flags/se.svg deleted file mode 100644 index 8ba745a..0000000 --- a/frontend/public/assets/flags/se.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/sg.svg b/frontend/public/assets/flags/sg.svg deleted file mode 100644 index c4dd4ac..0000000 --- a/frontend/public/assets/flags/sg.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sh-ac.svg b/frontend/public/assets/flags/sh-ac.svg deleted file mode 100644 index c43b301..0000000 --- a/frontend/public/assets/flags/sh-ac.svg +++ /dev/null @@ -1,689 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sh-hl.svg b/frontend/public/assets/flags/sh-hl.svg deleted file mode 100644 index 2150bf6..0000000 --- a/frontend/public/assets/flags/sh-hl.svg +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sh-ta.svg b/frontend/public/assets/flags/sh-ta.svg deleted file mode 100644 index ba39063..0000000 --- a/frontend/public/assets/flags/sh-ta.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sh.svg b/frontend/public/assets/flags/sh.svg deleted file mode 100644 index 7aba0ae..0000000 --- a/frontend/public/assets/flags/sh.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/si.svg b/frontend/public/assets/flags/si.svg deleted file mode 100644 index 1bbdd94..0000000 --- a/frontend/public/assets/flags/si.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sj.svg b/frontend/public/assets/flags/sj.svg deleted file mode 100644 index bb2799c..0000000 --- a/frontend/public/assets/flags/sj.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/sk.svg b/frontend/public/assets/flags/sk.svg deleted file mode 100644 index 676018e..0000000 --- a/frontend/public/assets/flags/sk.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/public/assets/flags/sl.svg b/frontend/public/assets/flags/sl.svg deleted file mode 100644 index a07baf7..0000000 --- a/frontend/public/assets/flags/sl.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/sm.svg b/frontend/public/assets/flags/sm.svg deleted file mode 100644 index e41d2f7..0000000 --- a/frontend/public/assets/flags/sm.svg +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sn.svg b/frontend/public/assets/flags/sn.svg deleted file mode 100644 index 7c0673d..0000000 --- a/frontend/public/assets/flags/sn.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/so.svg b/frontend/public/assets/flags/so.svg deleted file mode 100644 index a581ac6..0000000 --- a/frontend/public/assets/flags/so.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sr.svg b/frontend/public/assets/flags/sr.svg deleted file mode 100644 index 5e71c40..0000000 --- a/frontend/public/assets/flags/sr.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/ss.svg b/frontend/public/assets/flags/ss.svg deleted file mode 100644 index b257aa0..0000000 --- a/frontend/public/assets/flags/ss.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/st.svg b/frontend/public/assets/flags/st.svg deleted file mode 100644 index 1294bcb..0000000 --- a/frontend/public/assets/flags/st.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sv.svg b/frontend/public/assets/flags/sv.svg deleted file mode 100644 index cbc674a..0000000 --- a/frontend/public/assets/flags/sv.svg +++ /dev/null @@ -1,593 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sx.svg b/frontend/public/assets/flags/sx.svg deleted file mode 100644 index ac78561..0000000 --- a/frontend/public/assets/flags/sx.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/sy.svg b/frontend/public/assets/flags/sy.svg deleted file mode 100644 index 97c05cf..0000000 --- a/frontend/public/assets/flags/sy.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/sz.svg b/frontend/public/assets/flags/sz.svg deleted file mode 100644 index eb538e4..0000000 --- a/frontend/public/assets/flags/sz.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/tc.svg b/frontend/public/assets/flags/tc.svg deleted file mode 100644 index 1258971..0000000 --- a/frontend/public/assets/flags/tc.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/td.svg b/frontend/public/assets/flags/td.svg deleted file mode 100644 index fa3bd92..0000000 --- a/frontend/public/assets/flags/td.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/tf.svg b/frontend/public/assets/flags/tf.svg deleted file mode 100644 index fba2335..0000000 --- a/frontend/public/assets/flags/tf.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/tg.svg b/frontend/public/assets/flags/tg.svg deleted file mode 100644 index 9d6ea6c..0000000 --- a/frontend/public/assets/flags/tg.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/th.svg b/frontend/public/assets/flags/th.svg deleted file mode 100644 index 1e93a61..0000000 --- a/frontend/public/assets/flags/th.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/tj.svg b/frontend/public/assets/flags/tj.svg deleted file mode 100644 index f8c9a03..0000000 --- a/frontend/public/assets/flags/tj.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/tk.svg b/frontend/public/assets/flags/tk.svg deleted file mode 100644 index 05d3e86..0000000 --- a/frontend/public/assets/flags/tk.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/tl.svg b/frontend/public/assets/flags/tl.svg deleted file mode 100644 index 3d0701a..0000000 --- a/frontend/public/assets/flags/tl.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/tm.svg b/frontend/public/assets/flags/tm.svg deleted file mode 100644 index 4154ed7..0000000 --- a/frontend/public/assets/flags/tm.svg +++ /dev/null @@ -1,204 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/tn.svg b/frontend/public/assets/flags/tn.svg deleted file mode 100644 index 5735c19..0000000 --- a/frontend/public/assets/flags/tn.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/to.svg b/frontend/public/assets/flags/to.svg deleted file mode 100644 index d072337..0000000 --- a/frontend/public/assets/flags/to.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/frontend/public/assets/flags/tr.svg b/frontend/public/assets/flags/tr.svg deleted file mode 100644 index b96da21..0000000 --- a/frontend/public/assets/flags/tr.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/tt.svg b/frontend/public/assets/flags/tt.svg deleted file mode 100644 index bc24938..0000000 --- a/frontend/public/assets/flags/tt.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/tv.svg b/frontend/public/assets/flags/tv.svg deleted file mode 100644 index 675210e..0000000 --- a/frontend/public/assets/flags/tv.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/public/assets/flags/tw.svg b/frontend/public/assets/flags/tw.svg deleted file mode 100644 index 57fd98b..0000000 --- a/frontend/public/assets/flags/tw.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/tz.svg b/frontend/public/assets/flags/tz.svg deleted file mode 100644 index a2cfbca..0000000 --- a/frontend/public/assets/flags/tz.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/ua.svg b/frontend/public/assets/flags/ua.svg deleted file mode 100644 index 03daa19..0000000 --- a/frontend/public/assets/flags/ua.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/public/assets/flags/ug.svg b/frontend/public/assets/flags/ug.svg deleted file mode 100644 index 520eee5..0000000 --- a/frontend/public/assets/flags/ug.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/um.svg b/frontend/public/assets/flags/um.svg deleted file mode 100644 index 9e9edda..0000000 --- a/frontend/public/assets/flags/um.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/public/assets/flags/un.svg b/frontend/public/assets/flags/un.svg deleted file mode 100644 index 632bbb4..0000000 --- a/frontend/public/assets/flags/un.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/us.svg b/frontend/public/assets/flags/us.svg deleted file mode 100644 index 9cfd0c9..0000000 --- a/frontend/public/assets/flags/us.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/public/assets/flags/uy.svg b/frontend/public/assets/flags/uy.svg deleted file mode 100644 index 62c36f8..0000000 --- a/frontend/public/assets/flags/uy.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/uz.svg b/frontend/public/assets/flags/uz.svg deleted file mode 100644 index 0ccca1b..0000000 --- a/frontend/public/assets/flags/uz.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/va.svg b/frontend/public/assets/flags/va.svg deleted file mode 100644 index 3e297d6..0000000 --- a/frontend/public/assets/flags/va.svg +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/vc.svg b/frontend/public/assets/flags/vc.svg deleted file mode 100644 index f26c2d8..0000000 --- a/frontend/public/assets/flags/vc.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/frontend/public/assets/flags/ve.svg b/frontend/public/assets/flags/ve.svg deleted file mode 100644 index 314e7f5..0000000 --- a/frontend/public/assets/flags/ve.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/vg.svg b/frontend/public/assets/flags/vg.svg deleted file mode 100644 index ac90088..0000000 --- a/frontend/public/assets/flags/vg.svg +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/vi.svg b/frontend/public/assets/flags/vi.svg deleted file mode 100644 index d88d68f..0000000 --- a/frontend/public/assets/flags/vi.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/vn.svg b/frontend/public/assets/flags/vn.svg deleted file mode 100644 index 7e4bac8..0000000 --- a/frontend/public/assets/flags/vn.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/frontend/public/assets/flags/vu.svg b/frontend/public/assets/flags/vu.svg deleted file mode 100644 index 326d29e..0000000 --- a/frontend/public/assets/flags/vu.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/wf.svg b/frontend/public/assets/flags/wf.svg deleted file mode 100644 index 054c57d..0000000 --- a/frontend/public/assets/flags/wf.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/ws.svg b/frontend/public/assets/flags/ws.svg deleted file mode 100644 index 0e758a7..0000000 --- a/frontend/public/assets/flags/ws.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/xk.svg b/frontend/public/assets/flags/xk.svg deleted file mode 100644 index 0e8958d..0000000 --- a/frontend/public/assets/flags/xk.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/xx.svg b/frontend/public/assets/flags/xx.svg deleted file mode 100644 index 9333be3..0000000 --- a/frontend/public/assets/flags/xx.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/frontend/public/assets/flags/ye.svg b/frontend/public/assets/flags/ye.svg deleted file mode 100644 index 1c9e6d6..0000000 --- a/frontend/public/assets/flags/ye.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frontend/public/assets/flags/yt.svg b/frontend/public/assets/flags/yt.svg deleted file mode 100644 index e7776b3..0000000 --- a/frontend/public/assets/flags/yt.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/public/assets/flags/za.svg b/frontend/public/assets/flags/za.svg deleted file mode 100644 index d563adb..0000000 --- a/frontend/public/assets/flags/za.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/zm.svg b/frontend/public/assets/flags/zm.svg deleted file mode 100644 index 360f37a..0000000 --- a/frontend/public/assets/flags/zm.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/assets/flags/zw.svg b/frontend/public/assets/flags/zw.svg deleted file mode 100644 index 93aac4f..0000000 --- a/frontend/public/assets/flags/zw.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/public/icon.svg b/frontend/public/icon.svg deleted file mode 100644 index da7bd7f..0000000 --- a/frontend/public/icon.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/frontend/scripts/generate-icon.js b/frontend/scripts/generate-icon.js deleted file mode 100644 index 02eec68..0000000 --- a/frontend/scripts/generate-icon.js +++ /dev/null @@ -1,24 +0,0 @@ -import sharp from 'sharp'; -import { readFileSync, mkdirSync } from 'fs'; -import { dirname, join } from 'path'; -import { fileURLToPath } from 'url'; -const __dirname = dirname(fileURLToPath(import.meta.url)); -const rootDir = join(__dirname, '..', '..'); -const svgPath = join(rootDir, 'frontend', 'public', 'icon.svg'); -const outputPath = join(rootDir, 'build', 'appicon.png'); -async function generateIcon() { - try { - mkdirSync(join(rootDir, 'build'), { recursive: true }); - const svgBuffer = readFileSync(svgPath); - await sharp(svgBuffer) - .resize(1024, 1024) - .png() - .toFile(outputPath); - console.log('✓ Icon generated:', outputPath); - } - catch (error) { - console.error('✗ Failed to generate icon:', error.message); - process.exit(1); - } -} -generateIcon(); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx deleted file mode 100644 index e71853c..0000000 --- a/frontend/src/App.tsx +++ /dev/null @@ -1,726 +0,0 @@ -import { useState, useEffect, useCallback, useLayoutEffect, useRef } from "react"; -import { Button } from "@/components/ui/button"; -import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; -import { Search, X, ArrowUp } from "lucide-react"; -import { TooltipProvider } from "@/components/ui/tooltip"; -import { getSettings, getSettingsWithDefaults, loadSettings, saveSettings, applyThemeMode, applyFont } from "@/lib/settings"; -import { applyTheme } from "@/lib/themes"; -import { OpenFolder, CheckFFmpegInstalled, DownloadFFmpeg, GetRecentFetches, SaveRecentFetches } from "../wailsjs/go/main/App"; -import { EventsOn, EventsOff, Quit } from "../wailsjs/runtime/runtime"; -import { toastWithSound as toast } from "@/lib/toast-with-sound"; -import { TitleBar } from "@/components/TitleBar"; -import { Sidebar, type PageType } from "@/components/Sidebar"; -import { Header } from "@/components/Header"; -import { SearchBar } from "@/components/SearchBar"; -import { TrackInfo } from "@/components/TrackInfo"; -import { AlbumInfo } from "@/components/AlbumInfo"; -import { PlaylistInfo } from "@/components/PlaylistInfo"; -import { ArtistInfo } from "@/components/ArtistInfo"; -import { DownloadQueue } from "@/components/DownloadQueue"; -import { DownloadProgressToast } from "@/components/DownloadProgressToast"; -import { AudioAnalysisPage } from "@/components/AudioAnalysisPage"; -import { AudioConverterPage } from "@/components/AudioConverterPage"; -import { AudioResamplerPage } from "@/components/AudioResamplerPage"; -import { FileManagerPage } from "@/components/FileManagerPage"; -import { SettingsPage } from "@/components/SettingsPage"; -import { DebugLoggerPage } from "@/components/DebugLoggerPage"; -import { OtherProjects } from "@/components/OtherProjects"; -import { HistoryPage } from "@/components/HistoryPage"; -import { SupportPage } from "@/components/SupportPage"; -import type { HistoryItem } from "@/components/FetchHistory"; -import { useDownload } from "@/hooks/useDownload"; -import { useMetadata } from "@/hooks/useMetadata"; -import { useLyrics } from "@/hooks/useLyrics"; -import { useCover } from "@/hooks/useCover"; -import { useAvailability } from "@/hooks/useAvailability"; -import { ensureApiStatusCheckStarted } from "@/lib/api-status"; -import { useDownloadQueueDialog } from "@/hooks/useDownloadQueueDialog"; -import { useDownloadProgress } from "@/hooks/useDownloadProgress"; -import { buildPlaylistFolderName } from "@/lib/playlist"; -const HISTORY_KEY = "spotiflac_fetch_history"; -const MAX_HISTORY = 5; -function extractSpotifyEntityFromURL(url: string): { - type: string; - id: string; -} | null { - const trimmed = url.trim(); - if (!trimmed) { - return null; - } - const spotifyUriMatch = trimmed.match(/^spotify:(track|album|playlist|artist):([A-Za-z0-9]+)$/i); - if (spotifyUriMatch) { - return { - type: spotifyUriMatch[1].toLowerCase(), - id: spotifyUriMatch[2], - }; - } - try { - const parsed = new URL(trimmed); - const segments = parsed.pathname.split("/").filter(Boolean); - const supportedTypes = new Set(["track", "album", "playlist", "artist"]); - for (let i = 0; i < segments.length - 1; i++) { - const segment = segments[i].toLowerCase(); - if (!supportedTypes.has(segment)) { - continue; - } - const id = segments[i + 1]; - if (id) { - return { type: segment, id }; - } - } - } - catch { - } - return null; -} -function normalizeHistoryURL(url: string): string { - const trimmed = url.trim(); - if (!trimmed) - return trimmed; - const withoutQuery = trimmed.split("?")[0].replace(/\/+$/, ""); - const spotifyEntity = extractSpotifyEntityFromURL(withoutQuery); - if (spotifyEntity) { - return `https://open.spotify.com/${spotifyEntity.type}/${spotifyEntity.id}`; - } - return withoutQuery.replace(/(\/artist\/[A-Za-z0-9]+)\/discography\/all$/i, "$1"); -} -function getHistoryIdentityKey(type: HistoryItem["type"], url: string): string { - const normalizedUrl = normalizeHistoryURL(url); - const spotifyEntity = extractSpotifyEntityFromURL(normalizedUrl); - if (spotifyEntity) { - return `${type}:${spotifyEntity.id}`; - } - return `${type}:${normalizedUrl}`; -} -function dedupeHistoryItems(items: HistoryItem[]): HistoryItem[] { - const seen = new Set(); - const deduped: HistoryItem[] = []; - for (const item of items) { - const normalizedUrl = normalizeHistoryURL(item.url); - const key = getHistoryIdentityKey(item.type, normalizedUrl); - if (seen.has(key)) - continue; - seen.add(key); - deduped.push({ ...item, url: normalizedUrl }); - } - return deduped; -} -function sortHistoryItems(items: HistoryItem[]): HistoryItem[] { - return [...items].sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0)); -} -function normalizeHistoryItems(items: HistoryItem[]): HistoryItem[] { - return dedupeHistoryItems(sortHistoryItems(items)).slice(0, MAX_HISTORY); -} -function parseStoredHistory(value: string | null): HistoryItem[] { - if (!value) { - return []; - } - try { - const parsed = JSON.parse(value); - return Array.isArray(parsed) ? parsed : []; - } - catch (err) { - console.error("Failed to parse stored history:", err); - return []; - } -} -function App() { - const [currentPage, setCurrentPage] = useState("main"); - const contentScrollRef = useRef(null); - const [spotifyUrl, setSpotifyUrl] = useState(""); - const [selectedTracks, setSelectedTracks] = useState([]); - const [searchQuery, setSearchQuery] = useState(""); - const [sortBy, setSortBy] = useState("default"); - const [currentListPage, setCurrentListPage] = useState(1); - const [hasUpdate, setHasUpdate] = useState(false); - const [releaseDate, setReleaseDate] = useState(null); - const [fetchHistory, setFetchHistory] = useState([]); - const [isSearchMode, setIsSearchMode] = useState(false); - const [region, setRegion] = useState(() => localStorage.getItem("spotiflac_region") || "US"); - useEffect(() => { - localStorage.setItem("spotiflac_region", region); - }, [region]); - const [showScrollTop, setShowScrollTop] = useState(false); - const [hasUnsavedSettings, setHasUnsavedSettings] = useState(false); - const [pendingPageChange, setPendingPageChange] = useState(null); - const [showUnsavedChangesDialog, setShowUnsavedChangesDialog] = useState(false); - const [resetSettingsFn, setResetSettingsFn] = useState<(() => void) | null>(null); - const ITEMS_PER_PAGE = 50; - const CURRENT_VERSION = __APP_VERSION__; - const download = useDownload(region); - const metadata = useMetadata(); - const lyrics = useLyrics(); - const cover = useCover(); - const availability = useAvailability(); - const downloadQueue = useDownloadQueueDialog(); - const downloadProgress = useDownloadProgress(); - const [isFFmpegInstalled, setIsFFmpegInstalled] = useState(null); - const [isInstallingFFmpeg, setIsInstallingFFmpeg] = useState(false); - const [ffmpegInstallProgress, setFfmpegInstallProgress] = useState(0); - const [ffmpegInstallStatus, setFfmpegInstallStatus] = useState(""); - useLayoutEffect(() => { - const savedSettings = getSettings(); - if (savedSettings) { - applyThemeMode(savedSettings.themeMode); - applyTheme(savedSettings.theme); - applyFont(savedSettings.fontFamily, savedSettings.customFonts); - } - }, []); - useEffect(() => { - const initSettings = async () => { - const settings = await loadSettings(); - applyThemeMode(settings.themeMode); - applyTheme(settings.theme); - applyFont(settings.fontFamily, settings.customFonts); - if (!settings.downloadPath) { - const settingsWithDefaults = await getSettingsWithDefaults(); - await saveSettings(settingsWithDefaults); - } - }; - initSettings(); - const checkFFmpeg = async () => { - try { - const installed = await CheckFFmpegInstalled(); - setIsFFmpegInstalled(installed); - } - catch (err) { - console.error("Failed to check FFmpeg:", err); - setIsFFmpegInstalled(false); - } - }; - checkFFmpeg(); - const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - const handleChange = () => { - const currentSettings = getSettings(); - if (currentSettings.themeMode === "auto") { - applyThemeMode("auto"); - applyTheme(currentSettings.theme); - } - }; - mediaQuery.addEventListener("change", handleChange); - checkForUpdates(); - ensureApiStatusCheckStarted(); - void loadHistory(); - return () => { - mediaQuery.removeEventListener("change", handleChange); - }; - }, []); - useEffect(() => { - const contentElement = contentScrollRef.current; - if (!contentElement) { - return; - } - const handleScroll = () => { - setShowScrollTop(contentElement.scrollTop > 300); - }; - handleScroll(); - contentElement.addEventListener("scroll", handleScroll, { passive: true }); - return () => { - contentElement.removeEventListener("scroll", handleScroll); - }; - }, []); - const scrollToTop = useCallback(() => { - contentScrollRef.current?.scrollTo({ top: 0, behavior: "smooth" }); - }, []); - useEffect(() => { - contentScrollRef.current?.scrollTo({ top: 0, behavior: "auto" }); - setShowScrollTop(false); - }, [currentPage]); - useEffect(() => { - setSelectedTracks([]); - setSearchQuery(""); - download.resetDownloadedTracks(); - lyrics.resetLyricsState(); - cover.resetCoverState(); - availability.clearAvailability(); - setSortBy("default"); - setCurrentListPage(1); - }, [metadata.metadata]); - const checkForUpdates = async () => { - try { - const response = await fetch("https://api.github.com/repos/afkarxyz/SpotiFLAC/releases/latest"); - const data = await response.json(); - const latestVersion = data.tag_name?.replace(/^v/, "") || ""; - if (data.published_at) { - setReleaseDate(data.published_at); - } - if (latestVersion && latestVersion > CURRENT_VERSION) { - setHasUpdate(true); - } - } - catch (err) { - console.error("Failed to check for updates:", err); - } - }; - const persistRecentHistory = useCallback(async (history: HistoryItem[]) => { - try { - await SaveRecentFetches(JSON.stringify(history)); - } - catch (err) { - console.error("Failed to save recent fetches:", err); - } - }, []); - const loadHistory = useCallback(async () => { - try { - const saved = parseStoredHistory(localStorage.getItem(HISTORY_KEY)); - const persisted = parseStoredHistory(await GetRecentFetches()); - const normalized = normalizeHistoryItems([...persisted, ...saved]); - setFetchHistory(normalized); - await persistRecentHistory(normalized); - } - catch (err) { - console.error("Failed to load history:", err); - } - finally { - localStorage.removeItem(HISTORY_KEY); - } - }, [persistRecentHistory]); - const handleInstallFFmpeg = async () => { - setIsInstallingFFmpeg(true); - setFfmpegInstallProgress(0); - setFfmpegInstallStatus("starting"); - try { - EventsOn("ffmpeg:progress", (progress: number) => { - setFfmpegInstallProgress(progress); - if (progress >= 100) { - setFfmpegInstallStatus("extracting"); - } - else { - setFfmpegInstallStatus("downloading"); - } - }); - EventsOn("ffmpeg:status", (status: string) => { - setFfmpegInstallStatus(status); - }); - const response = await DownloadFFmpeg(); - EventsOff("ffmpeg:progress"); - EventsOff("ffmpeg:status"); - if (response.success) { - toast.success("FFmpeg installed successfully!"); - setIsFFmpegInstalled(true); - } - else { - toast.error(`Failed to install FFmpeg: ${response.error}`); - } - } - catch (error) { - console.error("Error installing FFmpeg:", error); - toast.error(`Error during FFmpeg installation: ${error}`); - } - finally { - setIsInstallingFFmpeg(false); - setFfmpegInstallProgress(0); - setFfmpegInstallStatus(""); - } - }; - const addToHistory = (item: Omit) => { - setFetchHistory((prev) => { - const normalizedUrl = normalizeHistoryURL(item.url); - const identityKey = getHistoryIdentityKey(item.type, normalizedUrl); - const filtered = prev.filter((h) => getHistoryIdentityKey(h.type, h.url) !== identityKey); - const newItem: HistoryItem = { - ...item, - url: normalizedUrl, - id: crypto.randomUUID(), - timestamp: Date.now(), - }; - const updated = normalizeHistoryItems([newItem, ...filtered]); - void persistRecentHistory(updated); - return updated; - }); - }; - const removeFromHistory = (id: string) => { - setFetchHistory((prev) => { - if (!prev.some((h) => h.id === id)) - return prev; - const updated = prev.filter((h) => h.id !== id); - void persistRecentHistory(updated); - return updated; - }); - }; - const handleHistorySelect = async (item: HistoryItem) => { - setSpotifyUrl(item.url); - const updatedUrl = await metadata.handleFetchMetadata(item.url); - if (updatedUrl) { - setSpotifyUrl(updatedUrl); - } - }; - const handleFetchMetadata = async () => { - const updatedUrl = await metadata.handleFetchMetadata(spotifyUrl); - if (updatedUrl) { - setSpotifyUrl(updatedUrl); - } - }; - useEffect(() => { - if (!metadata.metadata || !spotifyUrl) - return; - let historyItem: Omit | null = null; - if ("track" in metadata.metadata) { - const { track } = metadata.metadata; - historyItem = { - url: spotifyUrl, - type: "track", - name: track.name, - artist: track.artists, - image: track.images, - }; - } - else if ("album_info" in metadata.metadata) { - const { album_info } = metadata.metadata; - historyItem = { - url: spotifyUrl, - type: "album", - name: album_info.name, - artist: `${album_info.total_tracks.toLocaleString()} tracks`, - image: album_info.images, - }; - } - else if ("playlist_info" in metadata.metadata) { - const { playlist_info } = metadata.metadata; - historyItem = { - url: spotifyUrl, - type: "playlist", - name: playlist_info.owner.name, - artist: `${playlist_info.tracks.total.toLocaleString()} tracks`, - image: playlist_info.cover || playlist_info.owner.images || "", - }; - } - else if ("artist_info" in metadata.metadata) { - const { artist_info } = metadata.metadata; - historyItem = { - url: spotifyUrl, - type: "artist", - name: artist_info.name, - artist: `${artist_info.total_albums.toLocaleString()} albums`, - image: artist_info.images, - }; - } - if (historyItem) { - addToHistory(historyItem); - } - }, [metadata.metadata]); - const handleSearchChange = (value: string) => { - setSearchQuery(value); - setCurrentListPage(1); - }; - const toggleTrackSelection = (id: string) => { - setSelectedTracks((prev) => prev.includes(id) ? prev.filter((prevId) => prevId !== id) : [...prev, id]); - }; - const toggleSelectAll = (tracks: any[]) => { - const tracksWithId = tracks.filter((track) => track.spotify_id).map((track) => track.spotify_id || ""); - if (tracksWithId.length === 0) - return; - const allSelected = tracksWithId.every(id => selectedTracks.includes(id)); - if (allSelected) { - setSelectedTracks(prev => prev.filter(id => !tracksWithId.includes(id))); - } - else { - setSelectedTracks(prev => Array.from(new Set([...prev, ...tracksWithId]))); - } - }; - const handleOpenFolder = async () => { - const settings = getSettings(); - if (!settings.downloadPath) { - toast.error("Download path not set"); - return; - } - try { - await OpenFolder(settings.downloadPath); - } - catch (error) { - console.error("Error opening folder:", error); - toast.error(`Error opening folder: ${error}`); - } - }; - const renderMetadata = () => { - if (!metadata.metadata) - return null; - if ("track" in metadata.metadata) { - const { track } = metadata.metadata; - const trackId = track.spotify_id || ""; - return ( lyrics.handleDownloadLyrics(spotifyId, name, artists, albumName, undefined, undefined, albumArtist, releaseDate, discNumber)} onDownloadCover={(coverUrl, trackName, artistName, albumName, _playlistName, _position, trackId, albumArtist, releaseDate, discNumber) => cover.handleDownloadCover(coverUrl, trackName, artistName, albumName, undefined, undefined, trackId, albumArtist, releaseDate, discNumber)} onCheckAvailability={availability.checkAvailability} onOpenFolder={handleOpenFolder} onAlbumClick={metadata.handleAlbumClick} onArtistClick={async (artist) => { - const artistUrl = await metadata.handleArtistClick(artist); - if (artistUrl) { - setSpotifyUrl(artistUrl); - } - }} onBack={metadata.resetMetadata}/>); - } - if ("album_info" in metadata.metadata) { - const { album_info, track_list } = metadata.metadata; - return ( lyrics.handleDownloadLyrics(spotifyId, name, artists, albumName, album_info.name, position, albumArtist, releaseDate, discNumber, true)} onDownloadCover={(coverUrl, trackName, artistName, albumName, _folderName, _isArtistDiscography, position, trackId, albumArtist, releaseDate, discNumber) => cover.handleDownloadCover(coverUrl, trackName, artistName, albumName, album_info.name, position, trackId, albumArtist, releaseDate, discNumber, true)} onCheckAvailability={availability.checkAvailability} onDownloadAllLyrics={() => lyrics.handleDownloadAllLyrics(track_list, album_info.name, undefined, true)} onDownloadAllCovers={() => cover.handleDownloadAllCovers(track_list, album_info.name, true)} onDownloadAll={() => download.handleDownloadAll(track_list, album_info.name, true)} onDownloadSelected={() => download.handleDownloadSelected(selectedTracks, track_list, album_info.name, true)} onStopDownload={download.handleStopDownload} onOpenFolder={handleOpenFolder} onPageChange={setCurrentListPage} onBack={metadata.resetMetadata} onArtistClick={async (artist) => { - const pendingArtistUrl = artist.external_urls.replace(/\/$/, "") + "/discography/all"; - setSpotifyUrl(pendingArtistUrl); - const artistUrl = await metadata.handleArtistClick(artist); - if (artistUrl) { - setSpotifyUrl(artistUrl); - } - }} onTrackClick={async (track) => { - if (track.external_urls) { - setSpotifyUrl(track.external_urls); - await metadata.handleFetchMetadata(track.external_urls); - } - }}/>); - } - if ("playlist_info" in metadata.metadata) { - const { playlist_info, track_list } = metadata.metadata; - const settings = getSettings(); - const playlistFolderName = buildPlaylistFolderName(playlist_info.owner.name, playlist_info.owner.display_name, settings.playlistOwnerFolderName); - return ( lyrics.handleDownloadLyrics(spotifyId, name, artists, albumName, playlistFolderName, position, albumArtist, releaseDate, discNumber)} onDownloadCover={(coverUrl, trackName, artistName, albumName, _folderName, _isArtistDiscography, position, trackId, albumArtist, releaseDate, discNumber) => cover.handleDownloadCover(coverUrl, trackName, artistName, albumName, playlistFolderName, position, trackId, albumArtist, releaseDate, discNumber)} onCheckAvailability={availability.checkAvailability} onDownloadAllLyrics={() => lyrics.handleDownloadAllLyrics(track_list, playlistFolderName)} onDownloadAllCovers={() => cover.handleDownloadAllCovers(track_list, playlistFolderName)} onDownloadAll={() => download.handleDownloadAll(track_list, playlistFolderName)} onDownloadSelected={() => download.handleDownloadSelected(selectedTracks, track_list, playlistFolderName)} onStopDownload={download.handleStopDownload} onOpenFolder={handleOpenFolder} onPageChange={setCurrentListPage} onBack={metadata.resetMetadata} onAlbumClick={metadata.handleAlbumClick} onArtistClick={async (artist) => { - const pendingArtistUrl = artist.external_urls.replace(/\/$/, "") + "/discography/all"; - setSpotifyUrl(pendingArtistUrl); - const artistUrl = await metadata.handleArtistClick(artist); - if (artistUrl) { - setSpotifyUrl(artistUrl); - } - }} onTrackClick={async (track) => { - if (track.external_urls) { - setSpotifyUrl(track.external_urls); - await metadata.handleFetchMetadata(track.external_urls); - } - }}/>); - } - if ("artist_info" in metadata.metadata) { - const { artist_info, album_list, track_list } = metadata.metadata; - return ( lyrics.handleDownloadLyrics(spotifyId, name, artists, albumName, artist_info.name, position, albumArtist, releaseDate, discNumber)} onDownloadCover={(coverUrl, trackName, artistName, albumName, _folderName, _isArtistDiscography, position, trackId, albumArtist, releaseDate, discNumber) => cover.handleDownloadCover(coverUrl, trackName, artistName, albumName, artist_info.name, position, trackId, albumArtist, releaseDate, discNumber)} onCheckAvailability={availability.checkAvailability} onDownloadAllLyrics={() => lyrics.handleDownloadAllLyrics(track_list, artist_info.name)} onDownloadAllCovers={() => cover.handleDownloadAllCovers(track_list, artist_info.name)} onDownloadAll={() => download.handleDownloadAll(track_list, artist_info.name)} onDownloadSelected={() => download.handleDownloadSelected(selectedTracks, track_list, artist_info.name)} onStopDownload={download.handleStopDownload} onOpenFolder={handleOpenFolder} onAlbumClick={metadata.handleAlbumClick} onBack={metadata.resetMetadata} onArtistClick={async (artist) => { - const pendingArtistUrl = artist.external_urls.replace(/\/$/, "") + "/discography/all"; - setSpotifyUrl(pendingArtistUrl); - const artistUrl = await metadata.handleArtistClick(artist); - if (artistUrl) { - setSpotifyUrl(artistUrl); - } - }} onPageChange={setCurrentListPage} onTrackClick={async (track) => { - if (track.external_urls) { - setSpotifyUrl(track.external_urls); - await metadata.handleFetchMetadata(track.external_urls); - } - }}/>); - } - return null; - }; - const handlePageChange = (page: PageType) => { - if (currentPage === "settings" && hasUnsavedSettings && page !== "settings") { - setPendingPageChange(page); - setShowUnsavedChangesDialog(true); - return; - } - setCurrentPage(page); - }; - const handleDiscardChanges = () => { - setShowUnsavedChangesDialog(false); - if (resetSettingsFn) { - resetSettingsFn(); - } - const savedSettings = getSettings(); - applyThemeMode(savedSettings.themeMode); - applyTheme(savedSettings.theme); - applyFont(savedSettings.fontFamily, savedSettings.customFonts); - if (pendingPageChange) { - setCurrentPage(pendingPageChange); - setPendingPageChange(null); - } - }; - const handleCancelNavigation = () => { - setShowUnsavedChangesDialog(false); - setPendingPageChange(null); - }; - const renderPage = () => { - switch (currentPage) { - case "settings": - return ; - case "debug": - return ; - case "projects": - return ; - case "support": - return ; - case "history": - return { - metadata.loadFromCache(cachedData); - setCurrentPage("main"); - }}/>; - case "audio-analysis": - return ; - case "audio-converter": - return ; - case "audio-resampler": - return ; - case "file-manager": - return ; - default: - return (<> -
- - - - - - -
- -
- Fetch Album - - Do you want to fetch metadata for this album? - - {metadata.selectedAlbum && (
-

{metadata.selectedAlbum.name}

-
)} - - - - -
-
- - { - setSpotifyUrl(url); - const updatedUrl = await metadata.handleFetchMetadata(url); - if (updatedUrl) { - setSpotifyUrl(updatedUrl); - } - }} history={fetchHistory} onHistorySelect={handleHistorySelect} onHistoryRemove={removeFromHistory} hasResult={!!metadata.metadata} searchMode={isSearchMode} onSearchModeChange={setIsSearchMode} region={region} onRegionChange={setRegion}/> - - {!isSearchMode && metadata.metadata && renderMetadata()} - ); - } - }; - return ( -
- - - - -
-
-
- {renderPage()} -
-
-
- - - - - - - - - {showScrollTop && ()} - - - - - - Unsaved Changes - - You have unsaved changes in Settings. Are you sure you want to leave? Your changes will be lost. - - - - - - - - - - - - - Fetch Failed - - - Metadata fetch failed. Try using a high-quality VPN such as - Surfshark, ExpressVPN, Proton VPN, or a similar service. - - - Choose a location that is not blocked by Spotify or the - related service, such as the USA, UK, Germany, Netherlands, - or Singapore. - - - If you are already using a VPN, try switching to another - server and fetch again. - - - - - - - - - - { }}> - - - - FFmpeg Required - - - SpotiFLAC checks your system for FFmpeg and FFprobe first. - If they are not available, the required binaries will be downloaded from GitHub. - This setup downloads about 30-40MB of data. - - - - {isInstallingFFmpeg && (
- {ffmpegInstallStatus === "extracting" ? (
-
-
- Extracting... -
- Finalizing setup -
) : (
-
-
- Downloading... - {downloadProgress.is_downloading && downloadProgress.mb_downloaded > 0 && ( - {downloadProgress.mb_downloaded.toFixed(1)}MB - {downloadProgress.speed_mbps > 0 && ` @ ${downloadProgress.speed_mbps.toFixed(1)}MB/s`} - )} -
- {ffmpegInstallProgress}% -
-
-
-
-
)} -
)} - - - {!isInstallingFFmpeg && ()} - - - -
-
-
); -} -export default App; diff --git a/frontend/src/assets/audiotts-pro.webp b/frontend/src/assets/audiotts-pro.webp deleted file mode 100644 index 95158755160e3e17bb3ba898f4bc0038b8eb51d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9172 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 a$~WA;*LjMt)}C-|y3=>qL_&xF!2bY*9PTp! diff --git a/frontend/src/assets/chatgpt-tts.webp b/frontend/src/assets/chatgpt-tts.webp deleted file mode 100644 index b77385bfe922dfccaa0a50e3c520f5f493cf69c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6922 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 NbD7an!hfd#{{xI-ZH)i` diff --git a/frontend/src/assets/github-lang-colors.ts b/frontend/src/assets/github-lang-colors.ts deleted file mode 100644 index e390cab..0000000 --- a/frontend/src/assets/github-lang-colors.ts +++ /dev/null @@ -1,18 +0,0 @@ -export const langColors: Record = { - "TypeScript": "#2b7489", - "Go": "#375eab", - "Python": "#3572A5", - "CSS": "#563d7c", - "HTML": "#e44b23", - "JavaScript": "#f1e05a", - "Java": "#b07219", - "C": "#555555", - "C Sharp": "#178600", - "cpp": "#f34b7d", - "Ruby": "#701516", - "PHP": "#4F5D95", - "Swift": "#ffac45", - "Kotlin": "#F18E33", - "Rust": "#dea584", - "Shell": "#89e051" -}; diff --git a/frontend/src/assets/icons/am.png b/frontend/src/assets/icons/am.png deleted file mode 100644 index 5040e0e2368630b36b657436b2590e945e89d136..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9483 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 P2~bzoQL1`u6Y;+QY2~>o diff --git a/frontend/src/assets/icons/amzn.png b/frontend/src/assets/icons/amzn.png deleted file mode 100644 index e1388461ead8ea6250081d61d2c92f67247c9b1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56880 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

FLbzm%a*Skx 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 diff --git a/frontend/src/assets/icons/lrclib.png b/frontend/src/assets/icons/lrclib.png deleted file mode 100644 index ac3e5e774a4744417449718f17d903417872661f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22223 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 diff --git a/frontend/src/assets/icons/musicbrainz_d.png b/frontend/src/assets/icons/musicbrainz_d.png deleted file mode 100644 index 7467b95d34502203f79694606cce8ed9c9dd2b23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28301 zcmV*xKt8{TP)a zQ6AZnA6eJFckNxlk;#m%$YOH0EwJ4y3skGT&HTE?_YI* zCI=u9x`7V$@@Y0YobKv#>ihm*d|xdH0%i%Cfq6h1&>p>IfCiv3dY=T`32zQy0vcdP zKSw^NN1u-|JK#m{%YfYQ)#!5pP>McZjQ(8!MuFkzEf4epJ<<4xO`=a-60SB33&}KjcASe30z_q~5zzQIHp)V>% zjE|uL90lG6HUh5$?=j6WT^+zRz#YJYz*QeR*(F>LqWAI^BgTbBFyWq@XiyR*JO#WA zJPp*CW|&S6U@`Ekz&`@6p78nD$Yac81kw8=!1toJcbF!a4i4ZZ;J1J;L?`{k3yO_D z#%w_Fv3pt~g1?HKK`>VxfQ0ye3_Mc5me}B9%(0YVC-7&$SEA0uoNxe=-~TJ%@!05N z#6S#i7w{i}znjetU;*%NfIoj%b&5#u8m z0e%H|fobLd7DmO2Rg>|Xs%=O2J5#z!VkqBqTw)0s7 z_*QKEF=9*$2$$t6Q5WvKIDmf_wIX7~h%r6T3jFkZqyWOr_uSe1q8Kq^Oga90#IZ3Y z4j=~{h>CwPV#Ju9c=Sx7firOcLTdQHSzlI+7%|QVhNI4$yq~lhz;6KepWAiCh!NvF zpfREto3scZ7YQE3T>P^Df#<9Dn)%DVKd9Bv$OZDJ3r{Mx}3@{*4DY z@SS%l_vL9=EA))NjKHfnPS_dlGA1NhIe@y}dT z^Cbp$chUQUt@OULkJ4z7+@%Z96DL0yG|NOw=kWJ`Na4qSg12h}&JB-ZuDA*#6*qro zAjAQD8R$P72XHHJ+tgfFjHyIW3m8Ap&(Y_$aqQ*o6g!78(+*a~1}Opfr>Oh*0h;)G zI|YV8Y4gie4}5^V?k*D7J&d(@EtrY({pZ9ud!!>L@P9iS2k?JPF=t?mNrn`3i#;Rs zytbRJ7j`hVqZ<<)I~NKr`4#VUe-Kg))YDml;wZ(}zm2#19h~(K;aq(`M*9-=^%ye( zLc{-`fW9+v0PCaEKMwzA2)v;(eeWFL@CzR>xbY}{v5J{-2`uf@C;lfQ2%`l%g>Jcc zJ%{j~{xX#vZ<4s~5$wxuL2qb}9l`WRDq4{`u5iQ;f-iSFAF;xs%S9w$lBJ zT~vAtSjhx-E)9Vn8u2+Hj0U7OK)FC=*SmOKyRmn?fpg8HSgWo@PsjCvX^wvy)$_`y z;{e*DWuN%;pT-FMfU$i&D%3yr;!g5igJ>osav3yJBk=vn{B2=c;3Uy)7r!`0X~XkW z_HD+I`oOghV=lcE&6LHo7}F5#5uxa}PsaiL`swr!V_Y~CkB!jt#vZz!-^R#}Zv0ve zE0w@>Ed0P%&S6R*5rw9qr?Lc|i$C5^@y%~j-M5j%)%RgveII7~@~QdVG0p{YnE&4C zIsh5_l{+Yo0Hztd(INvIk8t#<&Gdh8nCe&wGihUI6YACSC-u}n1tby(0yM)yOEnQx z%GA2{P#8EuWzPnjYwpLn^mg=Y%hX>>j5EQV!19P*{FDx09dP*>{n!{&j-cu@vb~EV z&xHN_a?iL5_w7bE9O)HzJyoavDKAQ#jfQ3?z_bafMJl`Argn4})!iFNT>Sv{$}7Q* zhe)Rpo``Azr*r_1MDOF%f0|(IKp$N%?x6RLJ&Ye5P~p9qw$O~I`hLC*|75iRT|;w{ zXqJs%%2VF(9Nyj!urIw8`}&8m7OhngLyQXwvFXo!ngfuHzu5Sv0gAoj^t`r{?pJm) zvb&dB)x)q2bkmd-uJF{KE~qb*X(pO$f>)(B+C%B>A5l571?SS+NM7|2THB)d?z*tJ z7FYrtI++8Iq3>AL=K`ZTUS{B(19ZNyouREq@y1GOD$jE4Xe?`*8UIHRU7KN|8R7^$ z{3E+5^&H0A`yuv~cjH`n7kWw-Ok-R?7U8d)%mK(3Vq759${r&-yXks*3;pjMq%@RA zGc*jD+t+63u_@7tVc-WfD*N8U>)A_n`|H@(J%O|4S~SPK&{sGYar>zpz|9xtdgeBy za$o5j3Mw*g<~V~NfqwTSi_$PO+%B4rEU-u#;I)mIo`2-co*M7;?{qJ(Yz4N zjOzpE5g)O0^JC+`v*3=KIjD>jIr`>KdVaKx{E>dVvWG5JebbnQFNLO@09F!zsF%{) zKc;$M3(i${<6QeNMy6$UIK1hP#lT8n??eY6oZ^>W*z1}*@JdyNwj8DN#~(7Zsgp{f zq^kP5ZG_u+vlU|C^5b6@*-1Io+l1tDm z=R#lQY()?e{d{Ml1Gpr5KZowZ^NV8F2tBXt;^^~R89Ue?p7@T5HrK;m=@u9ULAgL_ z!_TPf-$-Kp12|XThta+)>?XvROlT8_{p!!|iV0tgF^TZ<6?NJld3F>1TMuD)CWa$} zJn>U~0-Bm8)N~VnxSQgOU!}bDHQcKoB600QXpJI#6JwH~MKyqvI)E6H$i6$U;UGt! z-a_v?2dNdxShjolkG3_lbrLoMyZIQ?#c=4J_M6)M}`pn7mCm2Gb+qEd6&6>*q) z?np#YfN}sW5rb%qb400cjNaFFbKu7tDRqtD*8Gkp>(U9Aif)Xu}!;3PmZY%nZ> z;y9I!&r+4K;%goxdD#Q#3#6MB;~cOQcv~F6d?1dk&H=);H~7vW4*ckShIbyLmam{Y z7N$K-EMIlsG`ze=C0|9GQ8ZqfS~8ODL%*++(u-fCy5kolZ}=Sc#kZhk;<4hhgyMS_ z2M||S&Jsbj#^B~ox?bE)?>l>_4wY3~&v2(nxF7kSzzeA6D_ALu1$T6iTr>lF?b?a@ zfOmK&eIB-99wPv6r@S?8O}v`^M094a1gA zJ*EXzd(jW56sqdUt{tbsY`m;?8 zesDzP{nM(SUk~@IKIPG}nl4;$&mxvSv5Mxa+QR~%kirHMD$k@Ez^6b$epnE5xiLe3XqtH$_nMsP5ZDt!tku6eg~J3~R-e zXz_l*$)M~$jsQLZGP2wG%1(|ww~f-#Av9gbN+-etG?*sgegM^Cjat#e$vG@}d<9FM zSWRki6KEa;6R6-diT-`iXGRqu6qP)@g;Fu@KH3> z9YCz=@G+DJ^Yr|DFP%U6kg=UT)bs$|b;4C$#fp1@FHnwe9d+8*#yyOLLHjN9S@Oh6 zTGn@24veXk%3y3TK548Km7};+ukH`<7cohxm9T!%yHOt2QcS( znM6frXlo~(Pj93Dt^E{whcObiQq-;I*VE$E*EGD6hc{fo&e(K(ZV^j9vxdydTy%k@ z3-6>R1EO!Bq7=z-WHea3-dRQi(k*Z^1l2OtJ#XW6?!emeDz4NAR$nuh*N)Bl|K_gV za{&1xLv%g6jbpEEW9&#Dx@Kc#l4@Oj+8DmT4^)xQ_k3EfZ)f@E*V26bf~W;q3B!V! z3^DkcM^LMsZ~y|CS`^xGp$$`1=w}zzXjYgO1eGF{jn7j(xS7Pox8vUYIgEuX=c34| zHFqO`0LnvodS2V5w)IB$^r{=qa#BiHZ(10B9W}}IJ!)m2J$=dX z3(>XC&~RT)c(1BXXvy96)^?2cg`wc6@8b{l<8>b;7#oIa1ufy8h|11JBaY6F3FsvO4+o6_?=NcsI_9i_sEkby|y4 z4!knK=pe-{?^1sERf6s#N`!=HKj5sO96^e}m-@g#@;zUnvg<99w|pM+;+xQub4Sfc z9KhV@jd(D!x0_=x?BwXvA5bj_0jHsI{pn^yGP~~;Jat{UD_T@*ul2@7*je$_($q-tz^_Oncb6l(0v=2~v=0Bi+6Rd+mA(Klv)&*7sGrPo)KC z>ja3}hSD(!JgNt`FmhxUi7Q3z_%WAk0@?0p}1{Uedu@v>RH zUm(x=G#X@|TvUb&^uB$7u4lK194zbf9};_&#RJr0wQ;EdJbTn$~ro zX>t-4r$=fsS&%YIsfcy;O{DJq4Yl)6FmU2l6di&3ztt>5EqXtQ*)osxqhDfVpcntx zQS^qU$KfiT!f@c>fXn??Pn{4u9e3_;#4aGS|xG-@-2DH1xs*met_}s{xwu8V1@O9NrUa8QKNQb z3uE28v3LH0#5E6NUvxuQoSa3FXMNVlviM$&u|2&UeQ6uruk509WEdmqU^loS;rVnh zer3lR)cmlmSMqTer&N(|(Id-AE);?$IrYb)n|k)Or-J-A=5@DW&%a0r)K0uEnuA{| zG5X%?jBnn6ZaFmEatF!PSE3mbCWY-m%?z+tUXHn7G5*nmXicq?JpT}==Uq$X&}4q# z!7Djd+L)Q)LTnc1c?}AEb zPe5eLwPFo#w1nwewBJ6TMUStd^;#L>6<=J8Lf#1vm`#w@UZsq^;!*-5gGPUJ@*C=q zAAI2{j{V)2sSXUPPmjFwCQJV1za_bPT~r4NUrW8Q6=UHNst0#tPL*d5eAR8xtQP$7 z5j9p^-Mta_+Iz9DegLz5d6>S;V9a<2Q0*(x|G_~HJ+pz~_ob~@#ZJ5EuB9gYriJnA z;f}rx@pxlZRpiUAZeZcVD_D5nGMpAE@>PL+`2DKFKMNrRyIMst`)Cb0MeY%XX7WBk zrRN|6&p%1&SQpNGsec5FZ{5n^(@)|qy9iA=$S@VqZ5zFzIb;H=RwF~4g4a3-f2Njc zQrBMVKgjsgU%}eFk;K*aV_$v;Mw77W%}mVL0${D;F(h{|-2)T{hB0j$r#XFM z>+M2A4mMp=frw6}Q#jvIKUpI1@_YbE8kN@nc^!2`nCTzu-7W{Ia z>Yn%TkL<+Tw-M(CX&bInBgZoh=1g7FJ@)cWx}M+8=+Q0=5;zTMG*b^x{b_LME20n? za?97K3>PsRgSH#yvG9@QwBNJ@Gc5y{l?m&*v)uRvz8JrbKT<@m6eBIr`gUanyLAz% zOD?B;cpt$?FJ2H}*gDy3Z$P(GAKh*g|6Ujmi-1|_<)4QaJqSlcbs1E$68NP&rH#)~ zQM6=t;$HVC#==!IYVCMNIe_v|f!<&2<=6|`8QgjlzgWddrqCr%iH5(3pz*8`vO(StbG_@E`C)#VaqLldn} z{2GQ?qkL$Wnhi)@egnBXAB>*U6GmRkk5lP87L^Z-aEIW0!52z39W9w5s8#U?x+uQ! z9jXU6VPAPKi7W5HXr38u!x`ZKq)pcU{y~ntv_rkG3>7hK11sYyl8zwor^BJI4sl)A zsphMcdW+Z%7E3<6ToH8SE@?+sG~xBdomt1rb6U`ay(g1l_?@?LZrq16ZwYAP0Oa{7 zl3Z~y_HX|Ss=Y_h3#0Gp zzo_WKTd!?p(POKafBRxAX+tVnuIdD%pL@oyplKM{9Ag`|U_AFj7X0QPqp41`IL6Q^ znz?zHYVfA+FiVlcl#@55Iw-@hJx{f-pY*CF1acx@Cc?qJW9FLGz)ijH z9zvX?7qJ)1=l#g=<=OXOM`)cxR3hk|bqgp}n@0?oGx#)l}r{WMYc?KB2K-2N_MhGMMncWvtG1mgvYw&ADW_r*R4Vv=z37cO=KbCu zkht;QDF2^uf~#>&nS&@rMlZxQ!gQ1-s8$(z<+~jF+E>tgAFClVIgV+nL{7bN{Gnq6 zV}sL{sAXC^03m?T6XB}vwA$Mdf(jifgJr6tRnn`nijPldxZPH1Lk1ruSr z^A=)MN1);dK)J7k<{B*f;!3r#*Kko2x}`;@{xrTRKLNg9A$9++st^{hM6EiAH_(gM za}>Yt7=C{*wZ3lkUYvp9rouV=k9%j8GKArKP%IFXi)hVlxc5GWd)h||xY*dB1S|Wkg*o--EA=bhbm;3*hRM-=v zlIWoUZ)BL>AAFg|K97H1z~2XMNG(p0}(BYR~lE$ipaNaI)0=&3@| zpcbBdDi<$LVCJb8GUY^6!w%@FM(mX>Sj#V_cH`anVTzQ@Rg{(QFjPJSti9$3$tZ0v>e~* zjh+`Zs~fcuCmMbtYUfqSZ+U@Z-~2m@+cu+1A3fnnY>j_p5Ix&~bNgesH{Fk!YyDW4Ccs{GHNg${V|@4yrI)@+g*MA#qamS%isck4@^@2e20{WBj{+ zj<;j_+@z=Yw9Z{KLmj>Hy>+gHQjA za&ISwjNiI0i3J@b7A?i@SVCgSDv~RgE5{HP{k)Iy7feho>RWmt^---fM)~MY#y@ zxQ{XMdh08N(J+!$#+tvD^b^0&Xz{<`A3lJVOik;m{+S|n0B3^Z+iTO=1Jrf@#PD6b z${729ww0~l{(#Q64$-)*O>Nkn62hNSt*QcBFgAwQ)5G|t57h~6wYHI1x`O2DHKeat zPjclNG&2`X>Wxm=)~g$myw6hUJw)%fzsktlzrY(AQI&TiCDh-xnheY|I%IN5HD}~i z>gmEHKF8ufgoI@MO(d_rTbLP67{4a}OGVL1)W%gTMNwBr8^K(735i?oqwxK|Bk(*G z9Zc_g;PeqYfU|6uP0#7Rdbll4hLV_O=YBl;Tl*CHhO)W`j;N=69_S; zn?e_IOtrr+mCsPEr`p#`xx1Uu_us{S<|&eEFQM_aJ4sz}Bc>~q-ubYDaGc~LJWb7P z6ZZUt)W-AFiY3hEX7zPbR(%^1B(tGG32(xrLr(uv0X>_;U3Wd2N@XPMufKd*{Nfn- zUGL%-^0>=ZVb5O{IW%zsWi%~?v+7zZi{8N7w>_MFm?elEz^p)BMoUgHhw)>*?EcXQ zZ2!R~#=FK;Ax#Y5t9n?bg?@^WYCWCC6*i?&17BwBt3I9|vgInb7ue`R#1Z&-gM$pc z{xT!)zD0W7l{DY;C=J)%4rXga?_G)J`3vX?o3_vWE{TOpIQrNB9j~v4)Vvnb4Gxy9 z@&|A^FO*8+8C zR>W*ugtcTP)jgZl+<geFykR1e<<--EtEO<@+LO_{X2AT>Oz;5>9nOH7Fknn zFdJ!3&&RP&zL_Tb_zmq%RI2?1GP^ItrHZb+My2dit$6r;pmKK2H8G{4U#&9oi`N+6 z@GiOA@1*7N-^5*Z31~7;P^UO6t6D(zhDTWBrWpP9|G+5>DH(HLqKm1Frp2+yP*Sc1 zJ=GkgaFVh}iexhI+>hyd<|k-1U(Gv=ZQg|T^}lB6zg>cn5wg*dC@n~%x6TXc%;cJ5 z2M}X=7`~;Z<$Aa5W7{|1XYcd7sE$=hG&mvOvj#~kMK;kyLbGu!_tdAYsvGL)rnKJ- zGz=Uy@-Id&wSgMtl1I7hQ7zT*s**C;s)z26kJ0zjC&};FPV2AyFEripAez+>r3CV` zi=g>ruDD0F^Tz)Ezfc<*Ld(cL{}i@UrFSpJD*Fp6^Qp_J*#y-wN(c6Z^F}i8V;C4o zpGsF3#e)Y)U$!W$2h>-QMVC+phN?4b_T!TfJAfI7P~=hyd_hfTaDNwje)1uEpW4pI z(P4DQBGDo(w*XVONxNCHi3Uu=R(c7(U;Tt19Thlh0lo}5O@QKIunqO*1~ygMf-HKJ z3KhzwnqtSX+$6=rhv@u^KcRB;Agxb)5wk%AH|zPdZ1@deufC1sV}p!+{m-FTKy#B5 zhHOss<0l1@?#R!UapI4xWP50qi`CMit}W0!3{#_8DqweXV5vGq@yozD~ns}8n z9kBzLF_>80Pf!{f<-l{B*!1-c4DRez8V}1Q=-{Qb4 z`v@vNPD4V4`(mW7ktCbUk+f6FSmkq*NtmWOAQA7X*p_MPSd9*D#$tT5LVlz~O=bvm zgZ^iprZO_d!aw-GlUTGO6g!D_{WZ-Xb^B-WI}cI#`EwYJ%>=S$E!%_Ac@WM$OVXHg zr~8(z#p2;37)SS#ZkP|6JXvzOkK!)Bg!#Y!&l%hBCjR(1$&1&Ky5yRO!Ku#F>`)!( zqOfTS@anm(+R7f$qn3mrisWntNA zMn_5%Ori2_XXNLvV&xi{|9k%&OO|dF$DbgNo^2&@?Pn(x=fJtTfPYIbg?C@1^y*It zhKIumyt8ovYU$8GH%x|Ke~Hv(SI~Il-JxR*qTL2fB9l^d+SgBhCF%g=D0lB?;F%|3 zco;n=HI3PW*a1vCNTMw#zC*24;^~m_F^wW)q^bBmgD*a>H~`yz^*1rI+2{loBg;p^C{eT`p+7c8 zZV~DGzKGqnfUzI^HNnU*npEM>27Z9mkjC42l%8+?J$5cfa_zc^xhd2eRIAD#A@Gnq zKSyo!D81kLYsNNipsAx-)mo+t{rqGgb^y}}>cnv%FzMfMh^^mvhy5??BHvfUO4+!r zp~A7H*<=!p>eM$317Gs|v)+=Kd&2z<$5cOYK;^Q9%A&px5?f0AZA0I$~$Cs zR;O-Vx>+$N%f|&YT%0TKqgE}F|JGlI#2shRe^<3d$HGh{C>+>F;oyFfYs3Le*yvPF z*F7#%7Wh?)`!>?|qrYMB#TPIW32dREmlDYAi2fB~2QVF=B3sEd4e~u>?E29rwtw$E z26y*kC2f+;E`jEwYX)gMOUBLN7;?jE_`WwScavmbNSr{XA))5yy-bRRn{UT%U+~d6 zdS!%?x!y}3QSR!cu>F08UVoP2;ltphaGM&j?az%{k`6OFYAgi!)7TReV6HT~QXaGKE81Ae694TJ;=dFMxPCyD~iJ(N=)t8XF?LLf@ zP<@p@67hJW{Stt9Vwh|2q~E5;tx890N#U3Dyc4L50E zFI<4t))7S?wdnb8U~I#S^!@M~1mz0l?k+XzEYX0GYQS`DQfX5SNX?ewUmdXnIPZuS ziBxr2Ze*YS9Y@&w^^NR*ZU@DI0#4e&NJ#-u!`2-#$t+1LizU^4YWQc9g9`Os(W6%N z&z}sTrcqOTem?0-F2QM^H-QdJ-r1B6@1*N*|BAw{?P$75!}T}O{`ud+YMVcSS-FTg zZxP1Q71VZb4<`)I1d<~8HLRqAyR-u%k@zSr83AJ-yvNAT-@uS!qtJv2vyl<*O{CMd zA|b8IB+Mqn4&Z#__%M%6zGs-d&unJv*WYLOz#yh;;kKq!4NBKc74B!<1}wu?r@i+{ zQ+%g@bOZc~k5{OXXtJ1p$0AaT&XZRD99%kZ{rK+BxD+?JXxFifnLc63M5r@9jr2QW^h z_m~=D5;fvbz$A=bWLq(nb)q53S!VsQ131r!hIuNZWsdxO6WhMGfunC7MAvkjoDf}# zVQ3_+w3^~`l_GAS+InXS)ds9VwN%A0blPrcWAWq5X}f7Tx^bQyfZ8MQ)yb~O^qgwr z)sIn&TA`2pwyo%H5<}(yY97^|V-#iJrjSRsrCUIht6Lb7|DUxCm|TZ}o@oeKjE_eE zHnq|ymEIo3SS(a;V)#zNQVd0oYlqv4vn=$lBX$7i&G1dNOw+&Ps4DR7`oShjqh*rq zY1KB9dr`)A(@xmam+if9eD_TAd^zm`wfZX#AhRS($NfuK^vFu=hGg^&m8j}{9w6b2 z?D>23!k&J7;6|8u?e=!cT}LqS@TLE58dy!uO7Z!lG+i~NEOgdW_=;H6L>D3wHOW_Z zBnIAi0li$Hp(UxR{UYLOnFfZT;R!e4EIj$^h#kO`LWX&S?80Z{U_bkw-L9ti`nGke z@!j;o1{GEsQr%a>JdLWlFJ|x6&Ol=zBHam>IXz497zcixYll9pWQ z#O9t~pnR+|oC-XvL_FLx(33JVA=e;mKVc`JHa3czG)b8WG;ur;C!uUR&UVBOU@D@|L9Bf0)9K?WEF4#Yb?aPC!ll%74clQ2p^Wf@(p9{=Sf(2;;DX z`?F=;?^6&vfGL42;TR0;>}1nd-(vr>+bQ&yNaS4XbU4LlYYy3TBPlzDq1#bguX@_i zrmW|R9jF4|NJ;gl8`k7l_`ot2+_#KGOFBB~3llEBt?>+qaY0wTXt- zh2gfJ8eFO&mfV%4OaRsCL zC&dp{mCRT;;TNd^%@M>7U`n74&`c-`*gzsDV_6%?Eg+^>vP@k><_?Jf)MUC5$`SCd)Zie>~8PS83@XT*;u^nQVV-W-4!m61+UJKRtI zQ{Ts3aVbv6%7`OCqLREC{?UvCsOuIb-MS%4^wLWCz}pNw^CMCTS#6GF*v>)|Ks^(` zv`?TZ2{Xy}sfJ=Ca|y8nm`W9)l82tMa9fgUX~#AbWD_}3Rz`hKttL}^!RZ^m9GrfD zH|~WJWjUMX+ZM6tp%t`T(-BFMN0W5NFJuBD&Az}te;S68&d8J%RbqR5RA_c|-!xyIB6qW8B9Qo`2N~QZKjjI=(Q!6eUg8G@;=)CuNBGf`Z+z{_$!9qehasy8OyQGZU{;_Aqnw?9$cKGKd~@?AyQ^4Nbn<* zm^)q|b^ud?@F+1fiw38O*6chL?uUvu^;7@!j4&)t1r)mr_=PIzrCH`bu#|-lE+w

wdbQh`1uEJ`X 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 diff --git a/frontend/src/assets/icons/musicbrainz_l.png b/frontend/src/assets/icons/musicbrainz_l.png deleted file mode 100644 index 1b864f73d96abce4ffaaca5f06f63c3eea949ec6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28243 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 XzN0QoiK&L=8-@7D>RBtquOw9xHv*L> zWm$%qRJ%weqkBMxPLkP0Wqz1x8;L{)nIt&^I&v}ba;a>n`ebqDmnq@b$zW-poU3WV zq$2=Pm3Qb_aQ?71Y%~Jj`~i3>39F$_90#n;>tI%Ia>gzD@`Zl6BRmJNpFlftrZo*U ztfAlO12Oc90}vWg;nwpz*%B-`@j7DFwOH};A}sp*M@Tfr;fomCc1wq^05K`JPk9NJ z&0{N301%EqlMp87=;)}3;3yka3q=4C9qga=NSXqxu>q+qtDyIz&c(!z?ZSRPjDx7U zlAYwNAk(lKi8(Wn`uIKA^|eA(Xnzhi-5Yogpu54SP1l5-GEs7L1qOd(IQpGbi$21)f zU3mF(;qF&(TT~(f2OS7w=s|nW#}E!a34Q1o$ls2jwt>PA0YcEmS>m@-VfeVi4&Vm~}N`3U6lpYVa)^wx4CGHMRg*Z=HorEW`eT zP;|}pkc$QZoW_3dLxjYepp?+0AD=DbM^dJdo)&id4`7e1&6!@oTmeU9%B zCOLyGI&Cz9%mb`^Hdz?m5A%oQl|mx^vgm6&OK-^E9ys-b1R zQAdPjjU=!eVW(PPH8+Ac)*`v=Go(J53)I(u`GdV9BCsr)<^f~U1+MWo@7nlxJMTLV zwQ?lF=Bo(NvK3fkBI?Vom3s-$wbC(X|(0CkVK3(Ne@D*C<8CzV#}2V}mn;FHd%}E(LcKow#K}9x@Wfn6W#KFW>2Na)nBFHNuRZk6F+U zI~wu#X9JtoQY$2K4bK5|5t&B~s;Hb?g&~&=M_>T;=)06r-gy>ZqOKVW|Mn49zV-!@ z4GB@wBQlTpyKbV7nvzI-gt`$a0&s*$x*|LmSHH`9camF7QlOL#K=9=d|GE|8HPH+{ z2})@{L@xOO;)6#bIsM3=)Y#h_J5{Mkp=<$_%Hm_0u&%VR+rUYalC3(1cwvd~wbv z!}qCvM0`bJk`QJ0yK;;ek0(Py(9j*o+3}s|HKv_B#PJg$msTM5!lSS^tpm#&!NI+N zX@aK`Kp+TZ&Hz{!bF<%GtF z*S`7^0tX!o$rovN1ms}BFj#2?(A?xqFv=l32e8ku1es^xxkGT^PY*|+ve*svJ9Fly z9e@m9M)SI@SpMQ-k>n#?|LoAv?PMOB80<&L7ZK$>=jh+{JASIR&hKk!g<47>J$2gA z&PNk&JDQ0{>(9V9@<>Qm_|f{$2Vrks2NnqBeU*SG;zH+7J@5!o zCJlATJRQu6-|NAlL2w?$moI#RPam0&hLv^j6&c%%Ur3Hw7BpE!&|f5K`p!&&?wjwK zSh%1uy?QlQ`_E;1Wqw1Pf|vggEq}icyrEj`a*m2l z9)XP1G+{@ZAXN^5anc#^pLhl&IpQi0b&%xSB}fQ_jt2CWkbVQb5A+QKH>pira%IVP z;Ry4@L3$2gUqKBu*$=kU6kZxI!LVW87x?0tPw>^W<)Wq3Uq(N7U{md$`s95P6j63x zqrstew;DeovwlrH+OpJ6HAiJS))<2ZA$aKFh>Sl4p(9DAi(WU47?XB#0{Y-15xU}s zX#K~1;L&C<(HxT}PJo)BqAfxuKp#5+#;NB+uR2te=bX}>xYOQ0A5TH;GX%bYgOJ*| z7D_;Yq{*<;CK5Hx2%K~Z^!^7r&%Xm?F%{WvX%vHDa}Cb{bOxOk=b#T<7vcWrPke+G zuYQ5nO)a9HPYp1F#Ycg?Z9}JXKGAp8u+X6~O%34nwSX8kmRooZV1I$Burp~adFCT5du|cxmR5^UKiogEZFZn&*Og=x1xo~f zUsF_f*Ee&tW=V|WqMH?uqx$)$ky!l|Dt~YtjKPPv284ElJYw)4J_$S?MeNzX1Ia{g zNH1jA7A5(TKyexTlP-dB)G1KP2D_xJ#@+1rViJfr=TpwdPBcOy4*w30pI&bgzN!Pz z|3^0=@#Pn=qAgI0OA#1-D44HoN8=YzU}sv<`q@G!Xc8^j$SFJr(47#whjZIFZxt5( zV*$1<+>A^-4Ij-EAZhV!lWv(%7!K=2&{Vx!#)a?gs+~y~ZN8(xH4uQLYiL>cG0Z!E zi-Fhu62{0Q+G+TcQP4KX5IEsnYUe}zKmQb=w;&AdlX_BH%V0bIbElDK?Y^ZxhM}Wj z9Cj@9QHMaOpav{*M9r=tcSPu+8%1d*VqYvm%lvtWeYs4GARlzot&qc!4xB&?N~9k` z$57>f9JT7Uc1JsSy(%*G8`1Fg+X(3tfjHHjT*7kz-2rhiIp@2U4fR;~$cI?__9`SB z;-aia!$aGSyw(*15r476;$x1WWp`xw_XfIO*`%rR)=b*2G&3g5j2oTUT$H#-d^5Rb zH8wnS7Y1JcOZW!UIhQW>woV`k(6roRCqV5t0P(k9gZb4mFw==-95J8mj!%@&+=uR< z`mz1a4#&Y6v$Xy1(Bp*NN`kH{mGyztw+c$XD(HiULkbr|qHMb;vC^)e742+q{EGOz z>{Kh7=gmR=beb--8CEhW^am*yQuoFy=yU1!07g}U_6{e}#)0gD@=eD-JAsCo(~+*L z2CHg64LLXP96(pYy_ixhQLK9X3w-w2$7tQ$B-%+;|8_DDcg01C$P?7UkVJmKz0h+A zpP|+>AEWrVQjndfqcNUFGM0grAFH=!<-7V1i4kZFXJ13A97ri!c z1k}raBdexk^AbXX19)ow06TLmp2%|+d`*Pv>ei2m{co&)GAh>J;sok?Nqr>pVt zL+@krN9&;&8dRTiVGFY-G7nQ=XhD(W(_~$o^K-T1?+#=Hs>YycJ_JHKqRlD9TT`OC zM@Ir0!nx^@hfsCxjZljEwKFs_UVD4pThSl|vQvxq4SSy}Z%f?SLxo20FBD|z)}ijT zmr+0MRiXV)GGjz}Zu^wvjMDXW*z}h_qUt&y{8Za##Qh+3;yr+oZUaMf;aqI~`(I%v zlVBmAqhv&-!yLnN09^rbF-d4zvl)y3`4N`?d$IUl3sV*tJ4^=lX?}$DVg&S{;Ouwh z#Ncj$(`y7-W+)=zO-)8qLqZHjrQ~4i#|yCeAAiMwA6^T|DDC*{n>VkKteJ8VVeoV{ znm?F>nirlGB0lVD%>_AugN-fmH?xt!+a^rfex$U>8{MLUVGIjzaorqE?m+0e8 zWM)~jqI`o6JGm82@6N*3Cm)B|+A2n(lLB(?PyY@)2heF`C(;^7)YoF=t4p!unT2R1 zGLJ~`Wf`Q-xG>S9uSXCtB9NKfwIjs#1F|Z-{;)1~uZHTFQ0}D!S>s!?M6^(O&5s}l zDtF|+=LNEiOBz4kg4mLG#g5-g|0x=Wa03r3fNMgfD#PDYHq^% zyKhHi!90|lItj**kxsxQ&-&TNraaD-Jf;ZXcRmHLkI0-git zECiV+gEg~0#o~W{g7tIPK=W%b%Bb$`Tys>rr?OteSB#*qNDLDp!!I=B&qC~swk_nl ziz@}Kl2SS(Wl>cegI$9k#32QcE((vb)7oC6>CE5ix1HH@jNuX`xY{d z4N${H6xxV;IijPaO02>c(4ZQMFn&@Wrq`HBS%@_!g|pzgji$HWMDv`v2po7Id;^C- zDJ~YfyG@DHhB`q7jxAjRp3XoiDHTUVdhbZZn4F892jM@#a{&7aaXo9OTee=1c~-u* z6q#6B=<$ifj?l4lH0}L*2oWP9B)MpZ%vn9ZD?fY=)Ud{mQK$}U}DGL^r!n_TNc!kQmDlg zzPl<)G?+wF5Gc}x0}#VSC~~7#Z%TVgKq%rvI%x_=KoaCiNtvJk$G-Rit)G74v=NgN z5eZ6Fj4_k^L9no+o{35k>f^AfMK}@>W4<>(@+UOC|1JUt9){qd zhl$yKT1g2Y>2CSX{kj7vT5u-t@(hWnCbuQvBp;op{jM=PiABeu?1hv%{hmn(j~S2T zS!>bw)@-NQ(aljZ24R$eh%Q2YGFH>v@v{<1PgN39<&Cv5m>Jv23&^sVWk|PO|9z)~ zs_3$qd_u-|P{){w_cl zwh`3CPTAT-wSOj@01d{7E?S8AvZZKxXO@T#Xh$T25oB36?B3zIXa{u#O~oiM@x2f} z5cd})IT`|5Rwm{F>izn|H*5s7ioR~Nkc|@T4uws8Lk>XI&;B3$BS)k9smEbOWAH_S z2t<6)4aJ%ML+Ah9yjI<(prj%olA!5?DbDkIe2+MXZm0;A8qld%pu2{bbP}Ee*k^Fa znj!=`($Ta-kYP+r3=SK`&=sFh=ILoWen-eo>!Ha!^v`Hh(s@4=Ma=J`us74tAg1{W z($lt`uOlO9%a?aZKHKi=5`cswP*o=?&~z}L4kZ|Zf7nPApL#lskq3hb$4ikxyZ4{B zfXN2R&bky@MISUj_bAjvgE;Fu(ZHS!)0si2ptK@@L^Oj~YZ8{Z>&GdIB;Fg{uZo>N z-;AH&Ie<(J3Brv@TC9qvbKxc1@ z#&5MYBU4j@Ae9U<06{U#3@F>i6Upcbp zd#TJrpS#H9hcs~nN~ZyUEq~H1q*JEznqAOwff9X`M5M^V;WOo*@e@1;&GC@3R;^I!Z1Xpd)sEdqk*;kZs&Kc{ZFz~;Wo5k@l*Hmb)7=P z+cObc^(FdU`E7)c8S9X6c93CbZcf04K6n(QE3ZZLxxd5waxz>1TeBDLJM z=k7b2jcUa}gs=K3l!M0zim@op?~6v?ZrH!O{aqfxivac+PRp($sqXmd0{E2oBeG{{ zq7G9;V5Ti(GL|sfEZaFtD%uXWsVB>*Zu7l3QjwbwRW>qyr=&&>KsW>85V#1nDKw}2 z18Mnh`Pbt}Zdi}X|N0TsvSF@%L3`s)Lk?FUa@F-{e)>VA7tDc7^A38^;1kaQbP}|4 zZ4X90w1-1<;gA&xit6m*9k%rn+REp5;82~rx*>$i)}!Yq$3i7JD%+)EX;GtRZq+~z z2GRKTn@HDIqw3mQ;2V4-z-za6AZGtAOF%M;5xMeaG|LJyb7w;eMS6`B@Qwf;x)p*7 zO`$vO*p|KhmfgMGkUo18_^wQ58ZdDn@G4My&nAuh8i|OAMy+iJB^jE*s9)ooH$fXW zQFQI02Xi>G@Em}L9sxQQ(D5PLr{E83+ah>!0#<7)*5C7cG`{tsBlWclCm?A$B9~qZ z^_Y`jXEIJ=um{6)03Lb{C}BvnTTK?nfpGD5EkZdI5yBoDAG!~9|9R4(5;Ls>CqON` zI*Km)0n{Uo7v;sglQ-`|cn-irj{_YKs3H)I=z_mb|E9`;BkT!mdE!yjzVIB){dQY; zu@hm4k#55`z6*8q;ey)SQxk%o1MrX^AO+uK0zB3VoAmqL8&AZ9j{d$D)wA+})T>Zj z?uVig71wsC#FB)qPd|a07oTxw9dP2ix9l{zaS4A<%|&Pf$++J9&)VNpMf23 z6+=Ww&{OF9iIL+pdoK+;)(Wek2E4Iegytmvxi1h+Jcf#r@(>#9qN1f&P_|*C`kAM| zWEJJ-U+OpkG3BYP&YuaTq%XpkUW4X;+~dqXB%VMIiUvFf;2}34jl|Ywa8-kL#PLuM zItJ>9QBeC1u<#*m0- z1UnI?iLH^I|+AJpI z2G6_{#_bl_ z%K>=U@1U?=t{jNS5C0$h$6pL4MsL+RjXP}xKEx~l(%Gjex>5KJ7>mevZh&^eY2fL$ z6L5E9^N_>Y_dW6C#RQ(l7f3VHxM z2jF4(byDls9^vp9xNs-A*lsA^}M_0VALYo`4b#BU4|GjSt;} z@l(JgN8EEeGLRyrP)8nw^qdXOEWysMOQA@>58I9-8P7lo1kw8ON2q@G2~>XXhmM-@ z4)S7T+;Id>I|tUfmB@Ux98xeO2u2i12xky$aq=BhEpR6e=7;};`07=VNk>qjQQGy`_{XVGfJ!>*1Yoz94fM|Cr%LGM2RrDt6NFj6UQv#awAB-Mw&IhVs~sDo5oDhNzG zm4ek+hs;-B!d&~Ma1e;KIs~G9Q5)J%=yeW2$Vicrt2mPaHchNsQvo*7vE_pWd<=Eek$G=t!E%OClX+oBF&4nPkYjz^-hI6n|wDSNKt1 z9fg^;g{HvPr=Nr|Vif!b94>bK9hrh@sQm^*?KiB=;1dS)9|7aw(_o_siMg|ooI3;7 zx>YWBVedzs?ho|*8~{zSiJM5(ClTKiL#iPKPT{0a27Hcux0&o6;tx54FjnRWZ*~Yt z?DjUDohd&+_jhH)X;(FyTigjlZH{=-!nSC7kBpM?fEb2KlOF6?RImkk zrv2Z~CIzWcDCvGR+k9Uy=0pU>U4rm6w?Z2;PV_qD&!E&E9s$sl1*iAiCr;R6qF``hM#g*XZ}g*)aE- zs)broh47U>5gbEn@d7~K-lm*u^hgIlMolH2z7q$a@A!Vg0R#sGA*nP4HalJ_`ytYW zW9P{r%bp7%5`tgnSqTHekH*kFo| z{@?o%nhqF&_-6}Xr4opYJqaa~FK`BZi2i`KpOFGH)`-NH%f;BSZdfj8W?(v=LPjq_ zpNlT-pmgbCTlA6bAL!tIJPD>LV{Z1VS zHDI_q1{r;>SLlICWSPbmG=DfBrBg0+hko0v*gL zbOxI0qYp)V@JMi~4s^0~*_9}G2S8bTJ87Zh*b0pL@xh1;D|6p$>MG0i>O5?NB*BbF z(fIZ(6rVZ)5*f)({r5CrREAR2$Nd47-m*-)wvys1U`5gN&RZ~}QJ_zdrm%MTk~x(J zeLe(F7`uxIQ4-yRb+7&h4YOy!YHfiM2%z+=^H4JBT%k3vqtnPhG9vIDejMT}KJPSl zp(~Le2a(Qz0d~rUl{7Kng25Q``(s_>cSlBh#-DePRRxLFU!msTq{KssKCOd%0DX2T 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 WGBh7daO2Vd0000 - - - - - - - - - - - - - - \ No newline at end of file diff --git a/frontend/src/assets/icons/qbz.png b/frontend/src/assets/icons/qbz.png deleted file mode 100644 index a6eb75e96dc1d1be932c1969a3b53f55705749d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30704 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 mJGY>Nl;_~tpz41A04a#$vuUZsdIm=LLR1tq)YJ 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%0A3i9>f48YLC>Wa|MEBo`vMYZG>g*yD!mL$P`k9t5 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 diff --git a/frontend/src/assets/icons/songstats.png b/frontend/src/assets/icons/songstats.png deleted file mode 100644 index ae111fc413359f01307dc5c104f8f14c29ca6935..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40971 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 B({TU* diff --git a/frontend/src/assets/icons/spotiflac.svg b/frontend/src/assets/icons/spotiflac.svg deleted file mode 100644 index cd3d7b2..0000000 --- a/frontend/src/assets/icons/spotiflac.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/src/assets/icons/spotubedl.svg b/frontend/src/assets/icons/spotubedl.svg deleted file mode 100644 index 09e2249..0000000 --- a/frontend/src/assets/icons/spotubedl.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/src/assets/icons/tidal_d.png b/frontend/src/assets/icons/tidal_d.png deleted file mode 100644 index 4760bfadf4bac5866626f3ed438a35bc669d5d36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3948 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ÐD_1KZC6DB#jMJ=>D(_&znvE1a!*N^YZ|}L4 zewv*7(T!ohqZY4s)g3T;+DAYpa9xtL!SOzy5xc)1#e+OiQR27G= znBl(c*D5<%`7=N@`o!t^+z}yZCq2ZmZl=Ofme|VbzVjJtsZV@)#6^W~7pSt#@ZvR1 z`AI6stLapXMog#T<%-j98`0a*(Nc5Cv^zw!zuY~IlgJrSwXpw=s3pU9 zWy#Z)40rNF)GRjfx!R&`2%)U^XN3H_1yxs7R?f!O&J3*F{pjr?&sEv*Nf*ZND@gO{ zLXQouvTB^8^v?&=wbyTJyfBt`i?E?^?wW*MW<-<2-an60VXCnnZiL>vZRXq1?7(nS qag}*@9e*mLyab^35QQ2$5(CQ8*(=m_SNQiC;QqEYsX24??tcLx^-y>K diff --git a/frontend/src/assets/icons/tidal_l.png b/frontend/src/assets/icons/tidal_l.png deleted file mode 100644 index 7397386dfdce598955c34c18c9d76ed0c446e6c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3937 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 - - - - - - diff --git a/frontend/src/assets/ko-fi.gif b/frontend/src/assets/ko-fi.gif deleted file mode 100644 index 221d0b965523356c71e5911184d0c87803143169..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 924277 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

gA62PSf8y@%li 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

r4ef|1-2w|JA&4ttTZ+EwF->tMcO6FCPfxf9G4B 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 diff --git a/frontend/src/assets/kofi_symbol.svg b/frontend/src/assets/kofi_symbol.svg deleted file mode 100644 index ade749d..0000000 --- a/frontend/src/assets/kofi_symbol.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/frontend/src/assets/patreon.svg b/frontend/src/assets/patreon.svg deleted file mode 100644 index 5a0c330..0000000 --- a/frontend/src/assets/patreon.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/frontend/src/assets/patreon_symbol.svg b/frontend/src/assets/patreon_symbol.svg deleted file mode 100644 index f5d2997..0000000 --- a/frontend/src/assets/patreon_symbol.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/frontend/src/assets/usdt.jpg b/frontend/src/assets/usdt.jpg deleted file mode 100644 index 5732bda4022a036678342c941f2461ad2d740780..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35056 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 RbRbOv-Ty!NpWu(q{{nUzTh0Ig diff --git a/frontend/src/assets/x.webp b/frontend/src/assets/x.webp deleted file mode 100644 index 44059a7fba9bf56a4a68cc0f4e31ea1ef064a315..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18318 zcma%BV{;}YNY;4=MZ9Cc6wrv|5+cr0P?tAYqxLq?<^I^KHPE}7$_c^UB zEg=yu2>@t_izuoqa%sW>005-_HW1{0m$00oR5}6x0CFF31LPt90q&HaBT#p{pm!gc zdDQHDG`*NPY~-%*?Bp6=XVtVo#6-Hz51=vs^X2;igd0VleZRywURA1B?Y7#Q2e#VmP}iHhmdD_6SL;e)@leh5I^lWSw^7sBC}tGG>(Ar^^PK@7 zT%X6kk-nSkwb~p`ujk019i5fx+q=87o0E&n<8#aDGu7D+j(CP!{gp3ks8@V;zklJm z<8}PrKOVN)b&9G)Nit@SMJQn+mC82Q$`q~J(i=Ew%7u!lXj3K1m6~KT(_a|>&Qf^G zLpXpOJ~IUfFJFE=J9>CGo@yk0y)hXMvjf7cz;z#TG8T451G*$k+Eg6+VI&dDl|M*B zmh79N&}Te_cwaIHZ9n_#=x5iHlw~0sX`+x5iJoB ztlBCmb)u=CkLQuB%AG6EZr+D#G+iIgz0=_U?r#n)s&v}cP{q|`rr0hix~b@{HY?}P zOMi%-9g(e?lBl6UmDo**xDCzC#NC)|OS}ijA%WOk>aZNN=mmbW& zmpmXEYicNEC=;I^f0l6G;jmYi-s~dk`8&Fc!+frC?E($m>;d~AWl{e$cF*#+Dstg< zAH{>14^;EX$CDm$;dQ{`C-6Os(mw|OfhIawZuR6g-hATX%m*UWxbSc|+4?kG#bHN- zTwE;Kt1K=~tMS53Ns5Xg{fm8ZCAMSMQ$=nuDQXYPkmIrjSXPQf&9{~1fB~MXaH?EF zhk$)x327U_Pg7!98K-}4|CnPDUPWbIR`Yh2$reA~q#1r_emnSqhdNf-N*z{I{%mYh zH+jghmHivJOqp%8P$#7yO~yAVY<1B|N^Jle_LH zB!;?(g;3+&MJ{GK7CQXUdKEGtp4usoK%T12yasVU6XA^7=-234teZc@u#*UtC^Ls! zT6 z1HV~vij?$zjhM^vjb85Lg)iPWq0}lzIQ|-RlBXHHYF>dSzHh{697*v^J8NRgHh#_h zNL#z*7N#GS(>Lp^nu15yRUy$ly_eaKl_|mMo7M^dfr?SQR?+x=i7n&m3$A9&Nb{0%Z}02N5>O=l;~Cp0 zL8eT%cThl>kB`FUv!^a-XQ0AH+59||n;32JT#zmB^)`t_-xVXU*;kw?pn#a;L|x&& zP-@)AJ6iGT@fi)#XR7#{zt@-)mAdY(sXFr0nz$*9tyZcSSH^T2Uq6X~8Eq>=BaoLH zeJ8&2{Is_eu(Jz(xq94&vLi<7c7-SY;1^{tNJ+Xa;G?JOKP%oL3GY_v)`N6_;(fJr z2_eii%ckc&q7-XTI^Cg~%6qAqH_g~d_159<#f~tgcq{w%n6yH1@Fa)Ubhfo}Gq zAl6-L_FGD{`{=dQ7W1TF=QmLK)<)d&tx1|1*sI(UbE{eP^ADv(7F)4uLl1s4YCP5Y zlTw)XCRSOGlzNwudWDzZ;fHDk2z6*j&rSjVfB*+Dl%P1w^?*R4n-K27?E}p9#~?9w z2n4Q~GavTa!0dO+274ymfLIeyi}kD%0A3iWkQn`#gi^9;Mo{A*EgytJJeyzuLG#du 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 - failedTracks: Set; - skippedTracks: Set; - downloadingTrack: string | null; - isDownloading: boolean; - bulkDownloadType: "all" | "selected" | null; - downloadProgress: number; - downloadRemainingCount: number; - currentDownloadInfo: { - name: string; - artists: string; - } | null; - currentPage: number; - itemsPerPage: number; - downloadedLyrics?: Set; - failedLyrics?: Set; - skippedLyrics?: Set; - downloadingLyricsTrack?: string | null; - checkingAvailabilityTrack?: string | null; - availabilityMap?: Map; - downloadedCovers?: Set; - failedCovers?: Set; - skippedCovers?: Set; - downloadingCoverTrack?: string | null; - isBulkDownloadingCovers?: boolean; - isBulkDownloadingLyrics?: boolean; - isMetadataLoading?: boolean; - onSearchChange: (value: string) => void; - onSortChange: (value: string) => void; - onToggleTrack: (id: string) => void; - onToggleSelectAll: (tracks: TrackMetadata[]) => void; - onDownloadTrack: (id: string, name: string, artists: string, albumName: string, spotifyId?: string, folderName?: string, durationMs?: number, position?: number, albumArtist?: string, releaseDate?: string, coverUrl?: string, spotifyTrackNumber?: number, spotifyDiscNumber?: number, spotifyTotalTracks?: number, spotifyTotalDiscs?: number, copyright?: string, publisher?: string) => void; - onDownloadLyrics?: (spotifyId: string, name: string, artists: string, albumName: string, folderName?: string, isArtistDiscography?: boolean, position?: number, albumArtist?: string, releaseDate?: string, discNumber?: number) => void; - onDownloadCover?: (coverUrl: string, trackName: string, artistName: string, albumName: string, folderName?: string, isArtistDiscography?: boolean, position?: number, trackId?: string, albumArtist?: string, releaseDate?: string, discNumber?: number) => void; - onCheckAvailability?: (spotifyId: string) => void; - onDownloadAllLyrics?: () => void; - onDownloadAllCovers?: () => void; - onDownloadAll: () => void; - onDownloadSelected: () => void; - onStopDownload: () => void; - onOpenFolder: () => void; - onPageChange: (page: number) => void; - onArtistClick?: (artist: { - id: string; - name: string; - external_urls: string; - }) => void; - onTrackClick?: (track: TrackMetadata) => void; - onBack?: () => void; -} -export function AlbumInfo({ albumInfo, trackList, searchQuery, sortBy, selectedTracks, downloadedTracks, failedTracks, skippedTracks, downloadingTrack, isDownloading, bulkDownloadType, downloadProgress, downloadRemainingCount, currentDownloadInfo, currentPage, itemsPerPage, downloadedLyrics, failedLyrics, skippedLyrics, downloadingLyricsTrack, checkingAvailabilityTrack, availabilityMap, downloadedCovers, failedCovers, skippedCovers, downloadingCoverTrack, isBulkDownloadingCovers, isBulkDownloadingLyrics, isMetadataLoading = false, onSearchChange, onSortChange, onToggleTrack, onToggleSelectAll, onDownloadTrack, onDownloadLyrics, onDownloadCover, onCheckAvailability, onDownloadAllLyrics, onDownloadAllCovers, onDownloadAll, onDownloadSelected, onStopDownload, onOpenFolder, onPageChange, onArtistClick, onTrackClick, onBack, }: AlbumInfoProps) { - const settings = getSettings(); - const albumArtistNames = splitArtistNames(albumInfo.artists); - const artistSeparator = albumInfo.artists.includes(";") ? "; " : ", "; - const fetchedTrackCount = trackList.length; - const totalTrackCount = albumInfo.total_tracks; - const showStreamingProgress = isMetadataLoading && totalTrackCount > 0 && fetchedTrackCount < totalTrackCount; - const clickableAlbumArtists = (() => { - const artistsByName = new Map(); - for (const track of trackList) { - const clickableTrackArtists = buildClickableArtists(track.artists, track.artists_data, track.artist_id, track.artist_url); - for (const artist of clickableTrackArtists) { - const normalizedName = artist.name.trim().toLowerCase(); - if (!normalizedName || !artist.external_urls || artistsByName.has(normalizedName)) { - continue; - } - artistsByName.set(normalizedName, artist); - } - } - return albumArtistNames.map((name) => { - const normalizedName = name.trim().toLowerCase(); - const matchedArtist = artistsByName.get(normalizedName); - if (matchedArtist) { - return { - ...matchedArtist, - name, - }; - } - if (albumArtistNames.length === 1 && albumInfo.artist_id && albumInfo.artist_url) { - return { - id: albumInfo.artist_id, - name, - external_urls: albumInfo.artist_url, - }; - } - return { - id: "", - name, - external_urls: "", - }; - }); - })(); - const [downloadingAlbumCover, setDownloadingAlbumCover] = useState(false); - const handleDownloadAlbumCover = async () => { - if (!albumInfo.images) - return; - setDownloadingAlbumCover(true); - try { - const os = settings.operatingSystem; - let outputDir = settings.downloadPath; - const albumName = albumInfo.name; - const artistName = albumInfo.artists; - const placeholder = "__SLASH_PLACEHOLDER__"; - const templateData: TemplateData = { - artist: artistName?.replace(/\//g, placeholder), - album: albumName?.replace(/\//g, placeholder), - album_artist: artistName?.replace(/\//g, placeholder), - title: albumName?.replace(/\//g, placeholder), - year: albumInfo.release_date?.substring(0, 4), - date: albumInfo.release_date, - }; - if (settings.folderTemplate) { - const folderPath = parseTemplate(settings.folderTemplate, templateData); - if (folderPath) { - const parts = folderPath.split("/").filter((p: string) => p.trim()); - for (const part of parts) { - outputDir = joinPath(os, outputDir, sanitizePath(part.replace(new RegExp(placeholder, "g"), " "), os)); - } - } - } - const response = await downloadCover({ - cover_url: albumInfo.images, - track_name: albumName, - artist_name: "", - album_name: "", - album_artist: "", - release_date: "", - output_dir: outputDir, - filename_format: "title", - track_number: false, - position: 0, - disc_number: 0, - }); - if (response.success) { - if (response.already_exists) - toast.info("Cover already exists"); - else - toast.success("Separate album cover downloaded"); - } - else { - toast.error(response.error || "Failed to download cover"); - } - } - catch (err) { - toast.error(err instanceof Error ? err.message : "Failed to download cover"); - } - finally { - setDownloadingAlbumCover(false); - } - }; - return (

- - {onBack && (
- -
)} - -
- {albumInfo.images && (
- {albumInfo.name} -
- - - - -

Download Separate Album Cover

-
-
-
)} -
-
-

Album

-

{albumInfo.name}

-
- - {clickableAlbumArtists.length > 0 ? clickableAlbumArtists.map((artist, index) => ( - {onArtistClick && artist.external_urls ? ( onArtistClick({ - id: artist.id, - name: artist.name, - external_urls: artist.external_urls, - })}> - {artist.name} - ) : (artist.name)} - {index < clickableAlbumArtists.length - 1 && artistSeparator} - )) : albumInfo.artists} - - - {albumInfo.release_date} - - - {showStreamingProgress - ? `${fetchedTrackCount.toLocaleString()} / ${totalTrackCount.toLocaleString()} tracks` - : `${Math.max(totalTrackCount, fetchedTrackCount).toLocaleString()} ${Math.max(totalTrackCount, fetchedTrackCount) === 1 ? "track" : "tracks"}`} - -
-
-
- - {selectedTracks.length > 0 && ()} - {onDownloadAllLyrics && ( - - - - -

Download All Lyrics

-
-
)} - {onDownloadAllCovers && ( - - - - -

Download All Separate Covers

-
-
)} - {downloadedTracks.size > 0 && ( - - - - -

Open Folder

-
-
)} -
- {isDownloading && ()} -
-
-
-
-
- - -
-
); -} diff --git a/frontend/src/components/ApiStatusTab.tsx b/frontend/src/components/ApiStatusTab.tsx deleted file mode 100644 index e451746..0000000 --- a/frontend/src/components/ApiStatusTab.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { Button } from "@/components/ui/button"; -import { PlugZap, CheckCircle2, Loader2, Wrench } from "lucide-react"; -import { TidalIcon, QobuzIcon, AmazonIcon, AppleMusicIcon, DeezerIcon } from "./PlatformIcons"; -import { useApiStatus } from "@/hooks/useApiStatus"; -import { SPOTIFLAC_NEXT_SOURCES } from "@/lib/api-status"; -function renderStatusIndicator(status: "checking" | "online" | "offline" | "idle") { - if (status === "online") { - return ; - } - if (status === "offline") { - return ; - } - return null; -} -function renderPlatformIcon(type: string) { - if (type === "tidal") { - return ; - } - if (type === "amazon") { - return ; - } - if (type === "deezer") { - return ; - } - if (type === "apple") { - return ; - } - return ; -} -export function ApiStatusTab() { - const { sources, statuses, nextStatuses, checkingSources, checkAllCurrent, checkAllNext } = useApiStatus(); - const isCheckingCurrent = sources.some((source) => checkingSources[source.id] === true); - const isCheckingNext = SPOTIFLAC_NEXT_SOURCES.some((source) => nextStatuses[source.id] === "checking"); - return (
-
-
-

SpotiFLAC

- -
- -
- {sources.map((source) => { - const status = statuses[source.id] || "idle"; - return (
-
-
- {renderPlatformIcon(source.type)} -

{source.name}

-
-
{renderStatusIndicator(status)}
-
-
); - })} -
-
- -
- -
-
-

SpotiFLAC Next

- -
- -
- {SPOTIFLAC_NEXT_SOURCES.map((source) => { - const status = nextStatuses[source.id] || "idle"; - return (
-
- {renderPlatformIcon(source.id)} -

{source.name}

-
-
{renderStatusIndicator(status)}
-
); - })} -
-
-
); -} diff --git a/frontend/src/components/ArtistInfo.tsx b/frontend/src/components/ArtistInfo.tsx deleted file mode 100644 index 8737cbb..0000000 --- a/frontend/src/components/ArtistInfo.tsx +++ /dev/null @@ -1,643 +0,0 @@ -import { Button } from "@/components/ui/button"; -import { Card, CardContent } from "@/components/ui/card"; -import { Download, FolderOpen, ImageDown, FileText, BadgeCheck, XCircle, Filter } from "lucide-react"; -import { Spinner } from "@/components/ui/spinner"; -import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; -import { SearchAndSort } from "./SearchAndSort"; -import { TrackList } from "./TrackList"; -import { DownloadProgress } from "./DownloadProgress"; -import type { TrackMetadata, TrackAvailability } from "@/types/api"; -import { downloadHeader, downloadGalleryImage, downloadAvatar } from "@/lib/api"; -import { getSettings } from "@/lib/settings"; -import { toastWithSound as toast } from "@/lib/toast-with-sound"; -import { useState, useMemo } from "react"; -import { Checkbox } from "@/components/ui/checkbox"; -import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; -import { ScrollArea } from "@/components/ui/scroll-area"; -interface ArtistInfoProps { - artistInfo: { - name: string; - images: string; - header?: string; - gallery?: string[]; - followers: number; - total_albums?: number; - genres: string[]; - biography?: string; - verified?: boolean; - listeners?: number; - rank?: number; - }; - albumList: Array<{ - id: string; - name: string; - images: string; - release_date: string; - album_type: string; - external_urls: string; - total_tracks?: number; - }>; - trackList: TrackMetadata[]; - searchQuery: string; - sortBy: string; - selectedTracks: string[]; - downloadedTracks: Set; - failedTracks: Set; - skippedTracks: Set; - downloadingTrack: string | null; - isDownloading: boolean; - bulkDownloadType: "all" | "selected" | null; - downloadProgress: number; - downloadRemainingCount: number; - currentDownloadInfo: { - name: string; - artists: string; - } | null; - currentPage: number; - itemsPerPage: number; - downloadedLyrics?: Set; - failedLyrics?: Set; - skippedLyrics?: Set; - downloadingLyricsTrack?: string | null; - checkingAvailabilityTrack?: string | null; - availabilityMap?: Map; - downloadedCovers?: Set; - failedCovers?: Set; - skippedCovers?: Set; - downloadingCoverTrack?: string | null; - isBulkDownloadingCovers?: boolean; - isBulkDownloadingLyrics?: boolean; - isMetadataLoading?: boolean; - onSearchChange: (value: string) => void; - onSortChange: (value: string) => void; - onToggleTrack: (id: string) => void; - onToggleSelectAll: (tracks: TrackMetadata[]) => void; - onDownloadTrack: (id: string, name: string, artists: string, albumName: string, spotifyId?: string, folderName?: string, durationMs?: number, position?: number, albumArtist?: string, releaseDate?: string, coverUrl?: string, spotifyTrackNumber?: number, spotifyDiscNumber?: number, spotifyTotalTracks?: number, spotifyTotalDiscs?: number, copyright?: string, publisher?: string) => void; - onDownloadLyrics?: (spotifyId: string, name: string, artists: string, albumName: string, folderName?: string, isArtistDiscography?: boolean, position?: number, albumArtist?: string, releaseDate?: string, discNumber?: number) => void; - onDownloadCover?: (coverUrl: string, trackName: string, artistName: string, albumName: string, folderName?: string, isArtistDiscography?: boolean, position?: number, trackId?: string, albumArtist?: string, releaseDate?: string, discNumber?: number) => void; - onCheckAvailability?: (spotifyId: string) => void; - onDownloadAllLyrics?: () => void; - onDownloadAllCovers?: () => void; - onDownloadAll: () => void; - onDownloadSelected: () => void; - onStopDownload: () => void; - onOpenFolder: () => void; - onAlbumClick: (album: { - id: string; - name: string; - external_urls: string; - }) => void; - onArtistClick: (artist: { - id: string; - name: string; - external_urls: string; - }) => void; - onPageChange: (page: number) => void; - onTrackClick?: (track: TrackMetadata) => void; - onBack?: () => void; -} -export function ArtistInfo({ artistInfo, albumList, trackList, searchQuery, sortBy, selectedTracks, downloadedTracks, failedTracks, skippedTracks, downloadingTrack, isDownloading, bulkDownloadType, downloadProgress, downloadRemainingCount, currentDownloadInfo, currentPage, itemsPerPage, downloadedLyrics, failedLyrics, skippedLyrics, downloadingLyricsTrack, checkingAvailabilityTrack, availabilityMap, downloadedCovers, failedCovers, skippedCovers, downloadingCoverTrack, isBulkDownloadingCovers, isBulkDownloadingLyrics, isMetadataLoading = false, onSearchChange, onSortChange, onToggleTrack, onToggleSelectAll, onDownloadTrack, onDownloadLyrics, onDownloadCover, onCheckAvailability, onDownloadAllLyrics, onDownloadAllCovers, onDownloadAll, onDownloadSelected, onStopDownload, onOpenFolder, onAlbumClick, onArtistClick, onPageChange, onTrackClick, onBack, }: ArtistInfoProps) { - const [downloadingHeader, setDownloadingHeader] = useState(false); - const [downloadingAvatar, setDownloadingAvatar] = useState(false); - const [downloadingGalleryIndex, setDownloadingGalleryIndex] = useState(null); - const [downloadingAllGallery, setDownloadingAllGallery] = useState(false); - const [activeTab, setActiveTab] = useState<"albums" | "tracks" | "gallery">("albums"); - const [activeAlbumFilter, setActiveAlbumFilter] = useState("all"); - const displayedAlbumCount = artistInfo.total_albums || albumList.length; - const fetchedAlbumCount = albumList.length; - const totalAlbumCount = artistInfo.total_albums || fetchedAlbumCount; - const totalTrackCount = albumList.reduce((sum, album) => sum + (album.total_tracks || 0), 0); - const fetchedTrackCount = trackList.length; - const albumCountLabel = isMetadataLoading && totalAlbumCount > 0 && fetchedAlbumCount < totalAlbumCount - ? `${fetchedAlbumCount.toLocaleString()} / ${totalAlbumCount.toLocaleString()} albums` - : `${displayedAlbumCount.toLocaleString()} ${displayedAlbumCount === 1 ? "album" : "albums"}`; - const resolvedTrackCount = totalTrackCount > 0 ? totalTrackCount : fetchedTrackCount; - const trackCountLabel = isMetadataLoading && totalTrackCount > 0 && fetchedTrackCount < totalTrackCount - ? `${fetchedTrackCount.toLocaleString()} / ${totalTrackCount.toLocaleString()} tracks` - : `${resolvedTrackCount.toLocaleString()} ${resolvedTrackCount === 1 ? "track" : "tracks"}`; - const albumFilterCounts = useMemo(() => { - const counts = new Map(); - counts.set("all", (albumList || []).length); - for (const album of albumList || []) { - const type = (album.album_type || "").trim().toLowerCase(); - if (!type) - continue; - counts.set(type, (counts.get(type) || 0) + 1); - } - return counts; - }, [albumList]); - const albumFilters = useMemo(() => { - const uniqueTypes = Array.from(new Set((albumList || []) - .map((album) => (album.album_type || "").trim().toLowerCase()) - .filter(Boolean))); - return ["all", ...uniqueTypes]; - }, [albumList]); - const filteredAlbums = useMemo(() => { - if (activeAlbumFilter === "all") { - return albumList || []; - } - return (albumList || []).filter((album) => (album.album_type || "").trim().toLowerCase() === activeAlbumFilter); - }, [albumList, activeAlbumFilter]); - const filteredAlbumGroups = useMemo(() => { - const albumTypeMap = new Map(albumList.map(a => [a.name, a.album_type])); - const albumGroups = trackList.reduce((acc, track) => { - if (!track.album_name) - return acc; - if (!acc[track.album_name]) { - acc[track.album_name] = { - count: 0, - tracks: [], - type: albumTypeMap.get(track.album_name) || "unknown" - }; - } - acc[track.album_name].count++; - acc[track.album_name].tracks.push(track); - return acc; - }, {} as Record); - return Object.entries(albumGroups).sort((a, b) => { - const dateA = a[1].tracks[0]?.release_date || ""; - const dateB = b[1].tracks[0]?.release_date || ""; - return dateB.localeCompare(dateA); - }); - }, [trackList, albumList]); - const formatAlbumFilterLabel = (value: string) => { - const count = albumFilterCounts.get(value) || 0; - if (value === "all") - return `All (${count})`; - const label = value - .split(/[_\s]+/) - .filter(Boolean) - .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) - .join(" "); - return `${label} (${count})`; - }; - const handleDownloadHeader = async () => { - if (!artistInfo.header) - return; - setDownloadingHeader(true); - try { - const settings = getSettings(); - const response = await downloadHeader({ - header_url: artistInfo.header, - artist_name: artistInfo.name, - output_dir: settings.downloadPath, - }); - if (response.success) { - if (response.already_exists) { - toast.info("Header already exists"); - } - else { - toast.success("Header downloaded successfully"); - } - } - else { - toast.error(response.error || "Failed to download header"); - } - } - catch (error) { - toast.error(`Error downloading header: ${error}`); - } - finally { - setDownloadingHeader(false); - } - }; - const handleDownloadAvatar = async () => { - if (!artistInfo.images) - return; - setDownloadingAvatar(true); - try { - const settings = getSettings(); - const response = await downloadAvatar({ - avatar_url: artistInfo.images, - artist_name: artistInfo.name, - output_dir: settings.downloadPath, - }); - if (response.success) { - if (response.already_exists) { - toast.info("Avatar already exists"); - } - else { - toast.success("Avatar downloaded successfully"); - } - } - else { - toast.error(response.error || "Failed to download avatar"); - } - } - catch (error) { - toast.error(`Error downloading avatar: ${error}`); - } - finally { - setDownloadingAvatar(false); - } - }; - const handleDownloadGalleryImage = async (imageUrl: string, index: number) => { - setDownloadingGalleryIndex(index); - try { - const settings = getSettings(); - const response = await downloadGalleryImage({ - image_url: imageUrl, - artist_name: artistInfo.name, - image_index: index, - output_dir: settings.downloadPath, - }); - if (response.success) { - if (response.already_exists) { - toast.info(`Gallery image ${index + 1} already exists`); - } - else { - toast.success(`Gallery image ${index + 1} downloaded successfully`); - } - } - else { - toast.error(response.error || `Failed to download gallery image ${index + 1}`); - } - } - catch (error) { - toast.error(`Error downloading gallery image ${index + 1}: ${error}`); - } - finally { - setDownloadingGalleryIndex(null); - } - }; - const handleDownloadAllGallery = async () => { - if (!artistInfo.gallery || artistInfo.gallery.length === 0) - return; - setDownloadingAllGallery(true); - try { - const settings = getSettings(); - let successCount = 0; - let existsCount = 0; - let failCount = 0; - for (let index = 0; index < artistInfo.gallery.length; index++) { - const imageUrl = artistInfo.gallery[index]; - try { - const response = await downloadGalleryImage({ - image_url: imageUrl, - artist_name: artistInfo.name, - image_index: index, - output_dir: settings.downloadPath, - }); - if (response.success) { - if (response.already_exists) { - existsCount++; - } - else { - successCount++; - } - } - else { - failCount++; - } - } - catch (error) { - failCount++; - } - } - if (failCount === 0) { - if (existsCount > 0 && successCount > 0) { - toast.success(`${successCount} images downloaded, ${existsCount} already existed`); - } - else if (existsCount > 0) { - toast.info(`All ${existsCount} images already exist`); - } - else { - toast.success(`All ${successCount} gallery images downloaded successfully`); - } - } - else { - toast.error(`${failCount} images failed to download`); - } - } - catch (error) { - toast.error(`Error downloading gallery images: ${error}`); - } - finally { - setDownloadingAllGallery(false); - } - }; - const hasGallery = artistInfo.gallery && artistInfo.gallery.length > 0; - return (
- - {artistInfo.header ? (<> -
-
-
- {onBack && (
- -
)} -
- - - - - -

Download Header

-
-
-
-
-
- {artistInfo.images && (
- {artistInfo.name} -
- - - - - -

Download Avatar

-
-
-
-
)} -
-

Artist

-
-

{artistInfo.name}

- {artistInfo.verified && ()} -
- {artistInfo.biography && (

{artistInfo.biography}

)} -
- {artistInfo.rank && (<> - #{artistInfo.rank} rank - - )} - {artistInfo.followers.toLocaleString()} {artistInfo.followers === 1 ? "follower" : "followers"} - {artistInfo.listeners && (<> - - {artistInfo.listeners.toLocaleString()} {artistInfo.listeners === 1 ? "listener" : "listeners"} - )} -
-
- {albumCountLabel} - - {trackCountLabel} - {artistInfo.genres.length > 0 && (<> - - {artistInfo.genres.join(", ")} - )} -
-
-
-
-
- ) : ( - {onBack && (
- -
)} -
- {artistInfo.images && (
- {artistInfo.name} -
- - - - - -

Download Avatar

-
-
-
-
)} -
-

Artist

-
-

{artistInfo.name}

- {artistInfo.verified && ()} -
- {artistInfo.biography && (

{artistInfo.biography}

)} -
- {artistInfo.rank && (<> - #{artistInfo.rank} rank - - )} - {artistInfo.followers.toLocaleString()} {artistInfo.followers === 1 ? "follower" : "followers"} - {artistInfo.listeners && (<> - - {artistInfo.listeners.toLocaleString()} {artistInfo.listeners === 1 ? "listener" : "listeners"} - )} -
-
- {albumCountLabel} - - {trackCountLabel} - {artistInfo.genres.length > 0 && (<> - - {artistInfo.genres.join(", ")} - )} -
-
-
-
)} - - -
-
- - - {hasGallery && ()} -
-
- - {activeTab === "gallery" && hasGallery && (
-
-

Gallery ({artistInfo.gallery!.length.toLocaleString()})

- - - - - -

Download All Gallery

-
-
-
-
- {artistInfo.gallery!.map((imageUrl, index) => (
-
- {`${artistInfo.name} -
- - - - - -

Download Image {index + 1}

-
-
-
-
-
))} -
-
)} - - {activeTab === "albums" && albumList.length > 0 && (
-
-

Discography

-
- - {selectedTracks.length > 0 && ()} -
-
- {albumFilters.length > 1 && (
- {albumFilters.map((filter) => ())} -
)} -
- {filteredAlbums.map((album) => { - const albumTracks = trackList.filter(t => t.album_name === album.name); - const tracksWithId = albumTracks.filter(t => t.spotify_id); - const isSelected = tracksWithId.length > 0 && tracksWithId.every(t => selectedTracks.includes(t.spotify_id!)); - const hasTracks = tracksWithId.length > 0; - return (
onAlbumClick({ - id: album.id, - name: album.name, - external_urls: album.external_urls, - })}> -
- - {hasTracks && (
e.stopPropagation()}> - onToggleSelectAll(albumTracks)} className="bg-black/50 border-white/70 data-[state=checked]:bg-primary data-[state=checked]:border-primary"/> -
)} - {album.images && ({album.name})} -
- - {album.album_type} - -
-
-

{album.name}

-
- {album.release_date?.split("-")[0]} - {album.total_tracks && (<> - - {album.total_tracks} {album.total_tracks === 1 ? "track" : "tracks"} - )} -
-
); - })} -
- {filteredAlbums.length === 0 && (
- No releases found for the selected discography filter. -
)} -
)} - - {activeTab === "tracks" && trackList.length > 0 && (
-
-

All Tracks

-
- - - - - - - Select Albums - - -
- {filteredAlbumGroups.map(([albumName, data]) => { - const tracksWithId = data.tracks.filter(t => t.spotify_id); - const isSelected = tracksWithId.length > 0 && tracksWithId.every(t => selectedTracks.includes(t.spotify_id!)); - return (
- onToggleSelectAll(data.tracks)} className="mt-1"/> -
- -
- - {data.type} - - - {data.count} tracks - - {data.tracks[0]?.release_date?.split('-')[0] || 'Unknown Year'} -
-
-
); - })} -
-
-
-
- - {selectedTracks.length > 0 && ()} - {onDownloadAllLyrics && ( - - - - -

Download All Lyrics

-
-
)} - {onDownloadAllCovers && ( - - - - -

Download All Separate Covers

-
-
)} - {downloadedTracks.size > 0 && ( - - - - -

Open Folder

-
-
)} -
-
- {isDownloading && ()} - - -
)} -
); -} diff --git a/frontend/src/components/AudioAnalysis.tsx b/frontend/src/components/AudioAnalysis.tsx deleted file mode 100644 index e2be418..0000000 --- a/frontend/src/components/AudioAnalysis.tsx +++ /dev/null @@ -1,179 +0,0 @@ -import { Card, CardContent, CardHeader } from "@/components/ui/card"; -import { Spinner } from "@/components/ui/spinner"; -import { Button } from "@/components/ui/button"; -import { Activity } from "lucide-react"; -import type { AnalysisResult } from "@/types/api"; -interface AudioAnalysisProps { - result: AnalysisResult | null; - analyzing: boolean; - onAnalyze?: () => void; - showAnalyzeButton?: boolean; - filePath?: string; -} -export function AudioAnalysis({ result, analyzing, onAnalyze, showAnalyzeButton = true, filePath }: AudioAnalysisProps) { - if (analyzing) { - return ( - -
- - Analyzing audio quality... -
-
-
); - } - if (!result && showAnalyzeButton) { - return ( - -
- -
-

Audio Quality Analysis

-

- Inspect spectral content and effective quality of FLAC, MP3, M4A, and AAC files -

-
- {onAnalyze && ()} -
-
-
); - } - if (!result) { - return null; - } - const formatDuration = (seconds: number) => { - const mins = Math.floor(seconds / 60); - const secs = Math.floor(seconds % 60); - return `${mins}:${secs.toString().padStart(2, "0")}`; - }; - const formatNumber = (num: number) => { - return num.toFixed(2); - }; - const formatFileSize = (bytes: number): string => { - if (bytes === 0) - return "0 B"; - const k = 1024; - const sizes = ["B", "KB", "MB", "GB"]; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i]; - }; - const nyquistFreq = result.sample_rate / 2; - const totalSamplesText = result.total_samples > 0 ? result.total_samples.toLocaleString() : "N/A"; - const freqResolutionLabel = result.file_type === "MP3" ? "Freq Res.:" : "Freq Resolution:"; - const hasCodecMeta = result.file_type === "MP3" && (Boolean(result.codec_mode) || - typeof result.bitrate_kbps === "number" || - typeof result.total_frames === "number" || - Boolean(result.codec_version)); - return ( - - {filePath && (

{filePath}

)} -
- - -
-
-

Format

-
    - {result.file_type && (
  • - Type: - {result.file_type} -
  • )} -
  • - Sample Rate: - {(result.sample_rate / 1000).toFixed(1)} kHz -
  • -
  • - Bit Depth: - {result.bit_depth} -
  • -
  • - Channels: - {result.channels === 2 ? "Stereo" : result.channels === 1 ? "Mono" : `${result.channels}`} -
  • -
  • - Duration: - {formatDuration(result.duration)} -
  • - {result.file_size > 0 && (
  • - Size: - {formatFileSize(result.file_size)} -
  • )} -
-
- -
-

Signal Analytics

-
    -
  • - Nyquist: - {(nyquistFreq / 1000).toFixed(1)} kHz -
  • -
  • - Dynamic Range: - {formatNumber(result.dynamic_range)} dB -
  • -
  • - Peak Amplitude: - {formatNumber(result.peak_amplitude)} dB -
  • -
  • - RMS Level: - {formatNumber(result.rms_level)} dB -
  • -
  • - Total Samples: - {totalSamplesText} -
  • -
-
- - {hasCodecMeta && (
-

MP3 Meta

-
    - {result.codec_mode && (
  • - Mode: - {result.codec_mode} -
  • )} - {typeof result.bitrate_kbps === "number" && (
  • - Bitrate: - {result.bitrate_kbps} kbps -
  • )} - {typeof result.total_frames === "number" && result.total_frames > 0 && (
  • - Frames: - {result.total_frames.toLocaleString()} -
  • )} - {result.codec_version && (
  • - Version: - {result.codec_version} -
  • )} -
-
)} - - {result.spectrum && (() => { - const frames = result.spectrum.time_slices.length; - const fftSize = (result.spectrum.freq_bins - 1) * 2; - const freqRes = result.sample_rate / fftSize; - return (
-

Spectrum Meta

-
    -
  • - Display Frames: - {frames.toLocaleString()} -
  • -
  • - FFT Size: - {fftSize.toLocaleString()} -
  • -
  • - {freqResolutionLabel} - {freqRes.toFixed(2)} Hz/bin -
  • -
-
); - })()} -
-
-
); -} diff --git a/frontend/src/components/AudioAnalysisPage.tsx b/frontend/src/components/AudioAnalysisPage.tsx deleted file mode 100644 index b31badf..0000000 --- a/frontend/src/components/AudioAnalysisPage.tsx +++ /dev/null @@ -1,884 +0,0 @@ -import { useState, useCallback, useRef, useEffect, type ChangeEvent, type CSSProperties, type DragEvent } from "react"; -import { Button } from "@/components/ui/button"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; -import { Progress } from "@/components/ui/progress"; -import { Spinner } from "@/components/ui/spinner"; -import { Upload, ArrowLeft, Trash2, Download, FolderOpen, X, AlertCircle, CheckCircle2, FileMusic, ChevronDown, Play, StopCircle } from "lucide-react"; -import { AudioAnalysis } from "@/components/AudioAnalysis"; -import { SpectrumVisualization, createSpectrogramDataURL, type SpectrumVisualizationHandle } from "@/components/SpectrumVisualization"; -import { useAudioAnalysis } from "@/hooks/useAudioAnalysis"; -import type { AnalysisResult } from "@/types/api"; -import { loadAudioAnalysisPreferences } from "@/lib/audio-analysis-preferences"; -import { toastWithSound as toast } from "@/lib/toast-with-sound"; -import { GetFileSizes, ListAudioFilesInDir, SaveSpectrumImage, SelectAudioFiles, SelectFolder } from "../../wailsjs/go/main/App"; -import { OnFileDrop, OnFileDropOff } from "../../wailsjs/runtime/runtime"; -interface AudioAnalysisPageProps { - onBack?: () => void; -} -type BatchItemStatus = "pending" | "analyzing" | "success" | "error"; -type BatchItemSource = "path" | "browser"; -interface BatchAnalysisItem { - id: string; - source: BatchItemSource; - path: string; - name: string; - size: number; - status: BatchItemStatus; - error?: string; - result?: AnalysisResult; - file?: File; -} -interface QueueProgressState { - completed: number; - total: number; - fileName: string; -} -const EMPTY_PROGRESS_STATE: QueueProgressState = { - completed: 0, - total: 0, - fileName: "", -}; -const SUPPORTED_AUDIO_EXTENSIONS = [".flac", ".mp3", ".m4a", ".aac"]; -const SUPPORTED_AUDIO_ACCEPT = [ - ".flac", - ".mp3", - ".m4a", - ".aac", - "audio/flac", - "audio/x-flac", - "audio/mpeg", - "audio/mp3", - "audio/mp4", - "audio/x-m4a", - "audio/aac", - "audio/aacp", -].join(","); -const SUPPORTED_AUDIO_LABEL = "FLAC, MP3, M4A, or AAC"; -function isSupportedAudioPath(filePath: string): boolean { - const normalized = filePath.toLowerCase(); - return SUPPORTED_AUDIO_EXTENSIONS.some((ext) => normalized.endsWith(ext)); -} -function isSupportedAudioFile(file: File): boolean { - const normalizedName = file.name.toLowerCase(); - const normalizedType = file.type.toLowerCase(); - return (SUPPORTED_AUDIO_EXTENSIONS.some((ext) => normalizedName.endsWith(ext)) || - normalizedType === "audio/flac" || - normalizedType === "audio/x-flac" || - normalizedType === "audio/mpeg" || - normalizedType === "audio/mp3" || - normalizedType === "audio/mp4" || - normalizedType === "audio/x-m4a" || - normalizedType === "audio/aac" || - normalizedType === "audio/aacp"); -} -function isAbsolutePath(filePath: string): boolean { - return /^(?:[a-zA-Z]:[\\/]|\\\\|\/)/.test(filePath); -} -function fileNameFromPath(filePath: string): string { - const parts = filePath.split(/[/\\]/); - return parts[parts.length - 1] || filePath; -} -function browserFileId(file: File): string { - return `browser:${file.name}:${file.size}:${file.lastModified}`; -} -function downloadDataURL(dataUrl: string, fileName: string): void { - const link = document.createElement("a"); - link.href = dataUrl; - link.download = fileName; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); -} -function formatFileSize(bytes: number): string { - if (bytes <= 0) { - return "0 B"; - } - const k = 1024; - const sizes = ["B", "KB", "MB", "GB"]; - const index = Math.min(sizes.length - 1, Math.floor(Math.log(bytes) / Math.log(k))); - return `${parseFloat((bytes / Math.pow(k, index)).toFixed(1))} ${sizes[index]}`; -} -function formatDuration(seconds: number): string { - const mins = Math.floor(seconds / 60); - const secs = Math.floor(seconds % 60); - return `${mins}:${secs.toString().padStart(2, "0")}`; -} -function itemMetaLine(item: BatchAnalysisItem): string { - if (item.result) { - const parts = [ - item.result.file_type ?? "Audio", - `${(item.result.sample_rate / 1000).toFixed(1)} kHz`, - formatDuration(item.result.duration), - ]; - if (typeof item.result.bitrate_kbps === "number" && item.result.bitrate_kbps > 0) { - parts.push(`${item.result.bitrate_kbps} kbps`); - } - return parts.join(" • "); - } - switch (item.status) { - case "analyzing": - return "Analyzing audio quality..."; - case "error": - return item.error || "Analysis failed"; - case "pending": - default: - return "Waiting to be analyzed"; - } -} -function statusIcon(status: BatchItemStatus) { - switch (status) { - case "analyzing": - return ; - case "success": - return ; - case "error": - return ; - case "pending": - default: - return ; - } -} -export function AudioAnalysisPage({ onBack }: AudioAnalysisPageProps) { - const { analysisProgress, spectrumLoading, spectrumProgress, analyzeFile, analyzeFilePath, cancelAnalysis, loadStoredAnalysis, clearStoredAnalysis, reAnalyzeSpectrum, clearResult, } = useAudioAnalysis(); - const [items, setItems] = useState([]); - const [activeItemId, setActiveItemId] = useState(null); - const [isDragging, setIsDragging] = useState(false); - const [isExportingSelected, setIsExportingSelected] = useState(false); - const [isExportingBatch, setIsExportingBatch] = useState(false); - const [isBatchRunning, setIsBatchRunning] = useState(false); - const [batchProgress, setBatchProgress] = useState(EMPTY_PROGRESS_STATE); - const [exportProgress, setExportProgress] = useState(EMPTY_PROGRESS_STATE); - const fileInputRef = useRef(null); - const spectrumRef = useRef(null); - const batchRunIdRef = useRef(0); - const itemsRef = useRef(items); - const activeItemIdRef = useRef(activeItemId); - useEffect(() => { - itemsRef.current = items; - }, [items]); - useEffect(() => { - activeItemIdRef.current = activeItemId; - }, [activeItemId]); - const setActiveSelection = useCallback((nextId: string | null) => { - activeItemIdRef.current = nextId; - setActiveItemId(nextId); - }, []); - const activeItem = items.find((item) => item.id === activeItemId) ?? null; - const successItems = items.filter((item) => item.status === "success" && item.result?.spectrum); - const pendingItems = items.filter((item) => item.status === "pending"); - const isSingleMode = items.length === 1; - const isBatchMode = items.length > 1; - const canResumeBatch = isBatchMode && !isBatchRunning && pendingItems.length > 0; - const batchPercent = batchProgress.total > 0 - ? Math.round(Math.max(0, Math.min(100, ((batchProgress.completed + (isBatchRunning ? analysisProgress.percent / 100 : 0)) / batchProgress.total) * 100))) - : 0; - const exportPercent = exportProgress.total > 0 - ? Math.round(Math.max(0, Math.min(100, (exportProgress.completed / exportProgress.total) * 100))) - : 0; - useEffect(() => { - if (!activeItem?.result) { - return; - } - loadStoredAnalysis(activeItem.id, activeItem.result, activeItem.path); - }, [activeItem, loadStoredAnalysis]); - const runBatchAnalysis = useCallback(async (entries: BatchAnalysisItem[]) => { - if (entries.length === 0) { - return; - } - const runId = batchRunIdRef.current + 1; - batchRunIdRef.current = runId; - setIsBatchRunning(true); - setBatchProgress({ - completed: 0, - total: entries.length, - fileName: entries[0]?.name ?? "", - }); - let successCount = 0; - let failCount = 0; - try { - for (let index = 0; index < entries.length; index++) { - if (batchRunIdRef.current !== runId) { - return; - } - const entry = entries[index]; - setBatchProgress({ - completed: index, - total: entries.length, - fileName: entry.name, - }); - setItems((prev) => prev.map((item) => item.id === entry.id - ? { ...item, status: "analyzing", error: undefined } - : item)); - const outcome = entry.source === "browser" && entry.file - ? await analyzeFile(entry.file, { - analysisKey: entry.id, - displayPath: entry.path, - suppressToast: true, - }) - : await analyzeFilePath(entry.path, { - analysisKey: entry.id, - displayPath: entry.path, - suppressToast: true, - }); - if (batchRunIdRef.current !== runId) { - return; - } - if (outcome.cancelled) { - return; - } - if (outcome.result) { - const analysisResult = outcome.result; - successCount++; - setItems((prev) => prev.map((item) => item.id === entry.id - ? { - ...item, - status: "success", - error: undefined, - result: analysisResult, - size: analysisResult.file_size || item.size, - } - : item)); - const hasSelectedSuccess = itemsRef.current.some((item) => item.id === activeItemIdRef.current && item.status === "success" && item.result); - if (!hasSelectedSuccess) { - setActiveSelection(entry.id); - } - } - else { - failCount++; - setItems((prev) => prev.map((item) => item.id === entry.id - ? { - ...item, - status: "error", - error: outcome.error || "Analysis failed", - } - : item)); - if (!activeItemIdRef.current) { - setActiveSelection(entry.id); - } - } - } - if (batchRunIdRef.current === runId) { - setBatchProgress({ - completed: entries.length, - total: entries.length, - fileName: "", - }); - if (successCount > 0) { - toast.success("Batch Analysis Complete", { - description: `Successfully analyzed ${successCount} file(s)${failCount > 0 ? `, ${failCount} failed` : ""}`, - }); - } - else if (failCount > 0) { - toast.error("Batch Analysis Failed", { - description: `All ${failCount} file(s) failed to analyze`, - }); - } - } - } - finally { - if (batchRunIdRef.current === runId) { - setIsBatchRunning(false); - } - } - }, [analyzeFile, analyzeFilePath, setActiveSelection]); - const ensureIdleQueue = useCallback(() => { - if (!isBatchRunning) { - return true; - } - toast.info("Analysis in progress", { - description: "Please wait for the current batch to finish or clear it first.", - }); - return false; - }, [isBatchRunning]); - const addPathItems = useCallback(async (paths: string[]) => { - if (!ensureIdleQueue()) { - return; - } - const uniquePaths = Array.from(new Set(paths.filter(Boolean))); - const invalidCount = uniquePaths.filter((path) => !isSupportedAudioPath(path)).length; - const validPaths = uniquePaths.filter(isSupportedAudioPath); - if (invalidCount > 0) { - toast.error("Unsupported format", { - description: `Only ${SUPPORTED_AUDIO_LABEL} files can be analyzed.`, - }); - } - if (validPaths.length === 0) { - return; - } - const existingIds = new Set(itemsRef.current.map((item) => item.id)); - const newPaths = validPaths.filter((path) => !existingIds.has(path)); - if (newPaths.length === 0) { - toast.info("No new files added", { - description: "All selected files were already in the batch queue.", - }); - return; - } - const fileSizes = await GetFileSizes(newPaths); - const newItems = newPaths.map((path) => ({ - id: path, - source: "path" as const, - path, - name: fileNameFromPath(path), - size: fileSizes[path] || 0, - status: "pending" as const, - })); - if (validPaths.length !== newPaths.length) { - toast.info("Some files skipped", { - description: `${validPaths.length - newPaths.length} file(s) were already queued.`, - }); - } - setItems((prev) => [...prev, ...newItems]); - if (!activeItemIdRef.current) { - setActiveSelection(newItems[0]?.id ?? null); - } - void runBatchAnalysis(newItems); - }, [ensureIdleQueue, runBatchAnalysis, setActiveSelection]); - const addBrowserFiles = useCallback(async (files: File[]) => { - if (!ensureIdleQueue()) { - return; - } - const validFiles = files.filter(isSupportedAudioFile); - const invalidCount = files.length - validFiles.length; - if (invalidCount > 0) { - toast.error("Unsupported format", { - description: `Only ${SUPPORTED_AUDIO_LABEL} files can be analyzed.`, - }); - } - if (validFiles.length === 0) { - return; - } - const existingIds = new Set(itemsRef.current.map((item) => item.id)); - const newItems = validFiles - .map((file) => ({ - id: browserFileId(file), - source: "browser" as const, - path: file.name, - name: file.name, - size: file.size, - status: "pending" as const, - file, - })) - .filter((item) => !existingIds.has(item.id)); - if (newItems.length === 0) { - toast.info("No new files added", { - description: "All selected files were already in the batch queue.", - }); - return; - } - if (validFiles.length !== newItems.length) { - toast.info("Some files skipped", { - description: `${validFiles.length - newItems.length} file(s) were already queued.`, - }); - } - setItems((prev) => [...prev, ...newItems]); - if (!activeItemIdRef.current) { - setActiveSelection(newItems[0]?.id ?? null); - } - void runBatchAnalysis(newItems); - }, [ensureIdleQueue, runBatchAnalysis, setActiveSelection]); - const handleSelectFiles = useCallback(async () => { - if (!ensureIdleQueue()) { - return; - } - try { - const selectedPaths = await SelectAudioFiles(); - if (selectedPaths && selectedPaths.length > 0) { - await addPathItems(selectedPaths); - } - return; - } - catch { - fileInputRef.current?.click(); - return; - } - }, [addPathItems, ensureIdleQueue]); - const handleSelectFolder = useCallback(async () => { - if (!ensureIdleQueue()) { - return; - } - try { - const selectedFolder = await SelectFolder(""); - if (!selectedFolder) { - return; - } - const folderFiles = await ListAudioFilesInDir(selectedFolder); - if (!folderFiles || folderFiles.length === 0) { - toast.info("No audio files found", { - description: `No ${SUPPORTED_AUDIO_LABEL} files were found in the selected folder.`, - }); - return; - } - await addPathItems(folderFiles.map((file) => file.path)); - } - catch (err) { - toast.error("Folder Selection Failed", { - description: err instanceof Error ? err.message : "Failed to select folder", - }); - } - }, [addPathItems, ensureIdleQueue]); - const handleInputChange = useCallback(async (event: ChangeEvent) => { - const files = Array.from(event.target.files ?? []); - event.target.value = ""; - if (files.length === 0) { - return; - } - await addBrowserFiles(files); - }, [addBrowserFiles]); - const handleHtmlDrop = useCallback(async (event: DragEvent) => { - event.preventDefault(); - setIsDragging(false); - const files = Array.from(event.dataTransfer.files ?? []); - if (files.length === 0) { - return; - } - await addBrowserFiles(files); - }, [addBrowserFiles]); - useEffect(() => { - OnFileDrop((_x, _y, paths) => { - setIsDragging(false); - if (!paths || paths.length === 0) { - return; - } - void addPathItems(paths); - }, true); - return () => { - OnFileDropOff(); - }; - }, [addPathItems]); - const handleSelectItem = useCallback((itemId: string) => { - setActiveSelection(itemId); - }, [setActiveSelection]); - const handleRemoveItem = useCallback((itemId: string) => { - if (isBatchRunning || isExportingBatch || isExportingSelected || spectrumLoading) { - return; - } - clearStoredAnalysis(itemId); - const nextItems = itemsRef.current.filter((item) => item.id !== itemId); - itemsRef.current = nextItems; - setItems(nextItems); - if (activeItemIdRef.current === itemId) { - const nextActive = nextItems.find((item) => item.status === "success" && item.result) ?? nextItems[0] ?? null; - setActiveSelection(nextActive?.id ?? null); - if (!nextActive) { - clearResult(); - } - } - }, [clearResult, clearStoredAnalysis, isBatchRunning, isExportingBatch, isExportingSelected, setActiveSelection, spectrumLoading]); - const handleClearAll = useCallback(() => { - if (isExportingBatch || isExportingSelected) { - return; - } - batchRunIdRef.current += 1; - itemsRef.current = []; - setItems([]); - setActiveSelection(null); - clearStoredAnalysis(); - clearResult(); - setIsBatchRunning(false); - setBatchProgress(EMPTY_PROGRESS_STATE); - setExportProgress(EMPTY_PROGRESS_STATE); - setIsDragging(false); - }, [clearResult, clearStoredAnalysis, isExportingBatch, isExportingSelected, setActiveSelection]); - const handleStopBatch = useCallback(() => { - if (!isBatchRunning) { - return; - } - batchRunIdRef.current += 1; - cancelAnalysis(); - setIsBatchRunning(false); - setBatchProgress(EMPTY_PROGRESS_STATE); - setItems((prev) => prev.map((item) => item.status === "analyzing" - ? { - ...item, - status: "pending", - } - : item)); - toast.info("Batch analysis stopped", { - description: "Click Analyze to continue the remaining files.", - }); - }, [cancelAnalysis, isBatchRunning]); - const handleAnalyzePending = useCallback(() => { - if (isBatchRunning || isExportingBatch || isExportingSelected || spectrumLoading) { - return; - } - const nextPendingItems = itemsRef.current.filter((item) => item.status === "pending"); - if (nextPendingItems.length === 0) { - return; - } - void runBatchAnalysis(nextPendingItems); - }, [isBatchRunning, isExportingBatch, isExportingSelected, runBatchAnalysis, spectrumLoading]); - const handleExportSelected = useCallback(async () => { - if (!activeItem?.result?.spectrum || !spectrumRef.current) { - return; - } - const dataUrl = spectrumRef.current.getCanvasDataURL(); - if (!dataUrl) { - toast.error("Export Failed", { - description: "Cannot get canvas data", - }); - return; - } - setIsExportingSelected(true); - try { - if (activeItem.source === "path" && isAbsolutePath(activeItem.path)) { - const outPath = await SaveSpectrumImage(activeItem.path, dataUrl); - toast.success("PNG Exported", { - description: `Saved to: ${outPath}`, - }); - return; - } - const baseName = activeItem.name.replace(/\.[^/.]+$/, "") || "spectrogram"; - downloadDataURL(dataUrl, `${baseName}_spectrogram.png`); - toast.success("PNG Exported", { - description: "Spectrogram image downloaded", - }); - } - catch (err) { - toast.error("Export Failed", { - description: err instanceof Error ? err.message : "Failed to export image", - }); - } - finally { - setIsExportingSelected(false); - } - }, [activeItem]); - const handleBatchExport = useCallback(async () => { - const exportableItems = itemsRef.current.filter((item) => item.status === "success" && item.result?.spectrum); - if (exportableItems.length === 0) { - toast.error("Nothing to export", { - description: "Analyze at least one file successfully before exporting PNGs.", - }); - return; - } - const preferences = loadAudioAnalysisPreferences(); - setIsExportingBatch(true); - setExportProgress({ - completed: 0, - total: exportableItems.length, - fileName: exportableItems[0]?.name ?? "", - }); - let successCount = 0; - let failCount = 0; - try { - for (let index = 0; index < exportableItems.length; index++) { - const item = exportableItems[index]; - const result = item.result; - if (!result?.spectrum) { - failCount++; - continue; - } - setExportProgress({ - completed: index, - total: exportableItems.length, - fileName: item.name, - }); - try { - const dataUrl = await createSpectrogramDataURL({ - spectrumData: result.spectrum, - sampleRate: result.sample_rate, - duration: result.duration, - freqScale: preferences.freqScale, - colorScheme: preferences.colorScheme, - fileName: item.name, - }); - if (item.source === "path" && isAbsolutePath(item.path)) { - await SaveSpectrumImage(item.path, dataUrl); - } - else { - const baseName = item.name.replace(/\.[^/.]+$/, "") || "spectrogram"; - downloadDataURL(dataUrl, `${baseName}_spectrogram.png`); - } - successCount++; - } - catch { - failCount++; - } - await new Promise((resolve) => setTimeout(resolve, 0)); - } - setExportProgress({ - completed: exportableItems.length, - total: exportableItems.length, - fileName: "", - }); - if (successCount > 0) { - toast.success("Batch PNG Export Complete", { - description: `Exported ${successCount} spectrogram PNG file(s)${failCount > 0 ? `, ${failCount} failed` : ""}`, - }); - } - else { - toast.error("Batch PNG Export Failed", { - description: "No spectrogram PNG files were exported.", - }); - } - } - finally { - setIsExportingBatch(false); - } - }, []); - const handleReAnalyzeSelectedSpectrum = useCallback(async (fftSize: number, windowFunction: string) => { - if (!activeItem?.result) { - return; - } - const nextResult = await reAnalyzeSpectrum(fftSize, windowFunction); - if (!nextResult) { - return; - } - setItems((prev) => prev.map((item) => item.id === activeItem.id - ? { - ...item, - result: nextResult, - status: "success", - error: undefined, - } - : item)); - }, [activeItem, reAnalyzeSpectrum]); - const batchDetailContent = !activeItem ? ( - -

- Select a file from the batch queue to inspect its analysis result. -

-
-
) : activeItem.status !== "success" || !activeItem.result ? ( - - {activeItem.name} -

{activeItem.path}

-
- - {activeItem.status === "analyzing" && (
-
- - Analyzing audio quality... -
- -

{analysisProgress.message}

-
)} - {activeItem.status === "pending" && (

- This file is queued and waiting for batch analysis to start. -

)} - {activeItem.status === "error" && (
- {activeItem.error || "Analysis failed"} -
)} -
-
) : (
- - - -
); - const singleModeContent = !activeItem ? null : activeItem.status === "success" && activeItem.result ? (
- - - -
) : activeItem.status === "analyzing" || activeItem.status === "pending" ? (
-
-
- {activeItem.status === "pending" ? "Preparing..." : "Processing..."} - {analysisProgress.percent}% -
- -

{analysisProgress.message}

-
-
) : (
-
- {activeItem.error || "Analysis failed"} -
-
); - const showSingleModeActions = isSingleMode && activeItem?.status === "success" && activeItem.result; - return (
- - -
-
- {onBack && ()} -

Audio Quality Analyzer

-
- -
- {isBatchMode && isBatchRunning && ()} - {canResumeBatch && ()} - {isBatchMode && ( - - - - - - - Add Files - - - - Add Folder - - - )} - {showSingleModeActions && ()} - {isBatchMode && ( - - - - - - - Export Selected PNG - - - - Export All PNG - - - )} - {showSingleModeActions && ()} - {isBatchMode && ()} -
-
- - {items.length === 0 && (
{ - event.preventDefault(); - setIsDragging(true); - }} onDragLeave={(event) => { - event.preventDefault(); - setIsDragging(false); - }} onDrop={handleHtmlDrop} style={{ "--wails-drop-target": "drop" } as CSSProperties}> -
- -
-

- {isDragging - ? "Drop your audio files here" - : "Drag and drop audio files here, or click the button below to select"} -

-
- - -
-

- Supported formats: FLAC, MP3, M4A, AAC -

-
)} - - {isSingleMode && (
- {singleModeContent} -
)} - - {isBatchMode && (
-
- {(isBatchRunning || isExportingBatch) && ( - - - {isExportingBatch ? "Batch PNG Export" : "Batch Analysis"} - - - -
- - {isExportingBatch - ? exportProgress.fileName || "Preparing export..." - : batchProgress.fileName || analysisProgress.message} - - - {isExportingBatch - ? `${exportProgress.completed}/${exportProgress.total}` - : `${Math.min(batchProgress.completed + (isBatchRunning ? 1 : 0), batchProgress.total)}/${batchProgress.total}`} - -
- - {!isExportingBatch && (
- {analysisProgress.message} - {analysisProgress.percent}% -
)} -
-
)} - - - -
- Batch Queue -

- {items.length} queued • {successItems.length} ready -

-
-
- -
- {items.map((item) => { - const isActive = item.id === activeItemId; - const isSelectable = item.status !== "pending"; - return (
{ - if (!isSelectable) { - return; - } - handleSelectItem(item.id); - }} onKeyDown={(event) => { - if (!isSelectable) { - return; - } - if (event.key === "Enter" || event.key === " ") { - event.preventDefault(); - handleSelectItem(item.id); - } - }}> -
{statusIcon(item.status)}
-
-

{item.name}

-

- {itemMetaLine(item)} -

-
- {formatFileSize(item.size)} - {fileNameFromPath(item.path).split(".").pop()?.toUpperCase() || "AUDIO"} -
-
- -
); - })} -
-
-
-
- -
- {batchDetailContent} -
-
)} -
); -} diff --git a/frontend/src/components/AudioConverterPage.tsx b/frontend/src/components/AudioConverterPage.tsx deleted file mode 100644 index 8c2a4f2..0000000 --- a/frontend/src/components/AudioConverterPage.tsx +++ /dev/null @@ -1,460 +0,0 @@ -import { useState, useCallback, useEffect } from "react"; -import { Button } from "@/components/ui/button"; -import { Label } from "@/components/ui/label"; -import { ToggleGroup, ToggleGroupItem, } from "@/components/ui/toggle-group"; -import { Upload, X, CheckCircle2, AlertCircle, Trash2, FileMusic, WandSparkles, } from "lucide-react"; -import { Spinner } from "@/components/ui/spinner"; -import { ConvertAudio, SelectAudioFiles, SelectFolder, ListAudioFilesInDir, } from "../../wailsjs/go/main/App"; -import { toastWithSound as toast } from "@/lib/toast-with-sound"; -import { OnFileDrop, OnFileDropOff } from "../../wailsjs/runtime/runtime"; -interface AudioFile { - path: string; - name: string; - format: string; - size: number; - status: "pending" | "converting" | "success" | "error"; - error?: string; - outputPath?: string; -} -function formatFileSize(bytes: number): string { - if (bytes === 0) - return "0 B"; - const k = 1024; - const sizes = ["B", "KB", "MB", "GB"]; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i]; -} -const BITRATE_OPTIONS = [ - { value: "320k", label: "320k" }, - { value: "256k", label: "256k" }, - { value: "192k", label: "192k" }, - { value: "128k", label: "128k" }, -]; -const M4A_CODEC_OPTIONS = [ - { value: "aac", label: "AAC" }, - { value: "alac", label: "ALAC" }, -]; -const STORAGE_KEY = "spotiflac_audio_converter_state"; -export function AudioConverterPage() { - const [files, setFiles] = useState(() => { - try { - const saved = sessionStorage.getItem(STORAGE_KEY); - if (saved) { - const parsed = JSON.parse(saved); - if (parsed.files && Array.isArray(parsed.files) && parsed.files.length > 0) { - return parsed.files; - } - } - } - catch (err) { - console.error("Failed to load saved state:", err); - } - return []; - }); - const [outputFormat, setOutputFormat] = useState<"mp3" | "m4a">(() => { - try { - const saved = sessionStorage.getItem(STORAGE_KEY); - if (saved) { - const parsed = JSON.parse(saved); - if (parsed.outputFormat === "mp3" || parsed.outputFormat === "m4a") { - return parsed.outputFormat; - } - } - } - catch (err) { - } - return "mp3"; - }); - const [bitrate, setBitrate] = useState(() => { - try { - const saved = sessionStorage.getItem(STORAGE_KEY); - if (saved) { - const parsed = JSON.parse(saved); - if (parsed.bitrate) { - return parsed.bitrate; - } - } - } - catch (err) { - } - return "320k"; - }); - const [m4aCodec, setM4aCodec] = useState<"aac" | "alac">(() => { - try { - const saved = sessionStorage.getItem(STORAGE_KEY); - if (saved) { - const parsed = JSON.parse(saved); - if (parsed.m4aCodec === "aac" || parsed.m4aCodec === "alac") { - return parsed.m4aCodec; - } - } - } - catch (err) { - } - return "aac"; - }); - const [converting, setConverting] = useState(false); - const [isDragging, setIsDragging] = useState(false); - const [isFullscreen, setIsFullscreen] = useState(false); - const saveState = useCallback((stateToSave: { - files: AudioFile[]; - outputFormat: "mp3" | "m4a"; - bitrate: string; - m4aCodec: "aac" | "alac"; - }) => { - try { - sessionStorage.setItem(STORAGE_KEY, JSON.stringify(stateToSave)); - } - catch (err) { - console.error("Failed to save state:", err); - } - }, []); - useEffect(() => { - saveState({ files, outputFormat, bitrate, m4aCodec }); - }, [files, outputFormat, bitrate, m4aCodec, saveState]); - useEffect(() => { - if (files.length === 0) - return; - const allMP3 = files.every((f) => f.format === "mp3"); - if (allMP3 && outputFormat !== "m4a") { - setOutputFormat("m4a"); - } - const hasFlac = files.some((f) => f.format === "flac"); - if (!hasFlac && m4aCodec === "alac") { - setM4aCodec("aac"); - } - }, [files, outputFormat, m4aCodec]); - const isFormatDisabled = files.length > 0 && files.every((f) => f.format === "mp3"); - const hasFlacFiles = files.some((f) => f.format === "flac"); - useEffect(() => { - const checkFullscreen = () => { - const isMaximized = window.innerHeight >= window.screen.height * 0.9; - setIsFullscreen(isMaximized); - }; - checkFullscreen(); - window.addEventListener("resize", checkFullscreen); - window.addEventListener("focus", checkFullscreen); - return () => { - window.removeEventListener("resize", checkFullscreen); - window.removeEventListener("focus", checkFullscreen); - }; - }, []); - const handleSelectFiles = async () => { - try { - const selectedFiles = await SelectAudioFiles(); - if (selectedFiles && selectedFiles.length > 0) { - addFiles(selectedFiles); - } - } - catch (err) { - toast.error("File Selection Failed", { - description: err instanceof Error ? err.message : "Failed to select files", - }); - } - }; - const handleSelectFolder = async () => { - try { - const selectedFolder = await SelectFolder(""); - if (selectedFolder) { - const folderFiles = await ListAudioFilesInDir(selectedFolder); - if (folderFiles && folderFiles.length > 0) { - addFiles(folderFiles.map((f) => f.path)); - } - else { - toast.info("No audio files found", { - description: "No FLAC or MP3 files found in the selected folder.", - }); - } - } - } - catch (err) { - toast.error("Folder Selection Failed", { - description: err instanceof Error ? err.message : "Failed to select folder", - }); - } - }; - const addFiles = useCallback(async (paths: string[]) => { - const validExtensions = [".mp3", ".flac"]; - const m4aFiles = paths.filter((path) => { - const ext = path.toLowerCase().slice(path.lastIndexOf(".")); - return ext === ".m4a"; - }); - if (m4aFiles.length > 0) { - toast.error("M4A files not supported", { - description: "Only FLAC and MP3 files are supported as input. Please convert M4A files first.", - }); - } - const GetFileSizes = (files: string[]): Promise> => (window as any)["go"]["main"]["App"]["GetFileSizes"](files); - const validPaths = paths.filter((path) => { - const ext = path.toLowerCase().slice(path.lastIndexOf(".")); - return validExtensions.includes(ext); - }); - const fileSizes = validPaths.length > 0 ? await GetFileSizes(validPaths) : {}; - setFiles((prev) => { - const newFiles: AudioFile[] = validPaths - .filter((path) => !prev.some((f) => f.path === path)) - .map((path) => { - const name = path.split(/[/\\]/).pop() || path; - const ext = name.slice(name.lastIndexOf(".") + 1).toLowerCase(); - return { - path, - name, - format: ext, - size: fileSizes[path] || 0, - status: "pending" as const, - }; - }); - if (newFiles.length > 0) { - if (paths.length > newFiles.length) { - const skipped = paths.length - newFiles.length; - toast.info("Some files skipped", { - description: `${skipped} file(s) were skipped (unsupported format or already added)`, - }); - } - return [...prev, ...newFiles]; - } - if (paths.length > 0 && m4aFiles.length === 0) { - toast.info("No new files added", { - description: "All files were already added or have unsupported format", - }); - } - return prev; - }); - }, []); - const handleFileDrop = useCallback(async (_x: number, _y: number, paths: string[]) => { - setIsDragging(false); - if (paths.length === 0) - return; - addFiles(paths); - }, [addFiles]); - useEffect(() => { - OnFileDrop((x, y, paths) => { - handleFileDrop(x, y, paths); - }, true); - return () => { - OnFileDropOff(); - }; - }, [handleFileDrop]); - const removeFile = (path: string) => { - setFiles((prev) => prev.filter((f) => f.path !== path)); - }; - const clearFiles = () => { - setFiles([]); - }; - const handleConvert = async () => { - if (files.length === 0) { - toast.error("No files selected", { - description: "Please add audio files to convert", - }); - return; - } - setConverting(true); - try { - const inputPaths = files.map((f) => f.path); - setFiles((prev) => prev.map((f) => { - if (inputPaths.includes(f.path)) { - return { ...f, status: "converting" as const, error: undefined }; - } - return f; - })); - const results = await ConvertAudio({ - input_files: inputPaths, - output_format: outputFormat, - bitrate: bitrate, - codec: outputFormat === "m4a" ? m4aCodec : "", - }); - setFiles((prev) => prev.map((f) => { - const result = results.find((r) => r.input_file === f.path || r.input_file.toLowerCase() === f.path.toLowerCase()); - if (result) { - return { - ...f, - status: result.success ? "success" : "error", - error: result.error, - outputPath: result.output_file, - }; - } - return f; - })); - const successCount = results.filter((r) => r.success).length; - const failCount = results.filter((r) => !r.success).length; - if (successCount > 0) { - toast.success("Conversion Complete", { - description: `Successfully converted ${successCount} file(s)${failCount > 0 ? `, ${failCount} failed` : ""}`, - }); - } - else if (failCount > 0) { - toast.error("Conversion Failed", { - description: `All ${failCount} file(s) failed to convert`, - }); - } - } - catch (err) { - toast.error("Conversion Error", { - description: err instanceof Error ? err.message : "Unknown error", - }); - setFiles((prev) => prev.map((f) => ({ ...f, status: "error" as const, error: "Conversion failed" }))); - } - finally { - setConverting(false); - } - }; - const getStatusIcon = (status: AudioFile["status"]) => { - switch (status) { - case "converting": - return ; - case "success": - return ; - case "error": - return ; - default: - return ; - } - }; - const convertableCount = files.filter((f) => f.status === "pending" || f.status === "success").length; - const successCount = files.filter((f) => f.status === "success").length; - return (
- -
-

Audio Converter

- {files.length > 0 && (
- - - -
)} -
- - -
{ - e.preventDefault(); - setIsDragging(true); - }} onDragLeave={(e) => { - e.preventDefault(); - setIsDragging(false); - }} onDrop={(e) => { - e.preventDefault(); - setIsDragging(false); - }} style={{ "--wails-drop-target": "drop" } as React.CSSProperties}> - {files.length === 0 ? (<> -
- -
-

- {isDragging - ? "Drop your audio files here" - : "Drag and drop audio files here, or click the button below to select"} -

-
- - -
-

- Supported formats: FLAC, MP3 -

- ) : (
- -
- -
-
- - { - if (value && !isFormatDisabled) - setOutputFormat(value as "mp3" | "m4a"); - }} disabled={isFormatDisabled}> - {!isFormatDisabled && ( - MP3 - )} - - M4A - - -
- - {outputFormat === "m4a" && hasFlacFiles && (
- - { - if (value) - setM4aCodec(value as "aac" | "alac"); - }}> - {M4A_CODEC_OPTIONS.map((option) => ( - {option.label} - ))} - -
)} - - {!(outputFormat === "m4a" && m4aCodec === "alac") && (
- - { - if (value) - setBitrate(value); - }}> - {BITRATE_OPTIONS.map((option) => ( - {option.label} - ))} - -
)} -
-
- - -
-
- {files.length} file(s) • {successCount} converted -
-
- - -
- {files.map((file) => (
- {getStatusIcon(file.status)} -
-

{file.name}

- {file.error && (

- {file.error} -

)} -
- - {formatFileSize(file.size)} - - - {file.format} - - {file.status !== "converting" && ()} -
))} -
- - -
- -
-
)} -
-
); -} diff --git a/frontend/src/components/AudioResamplerPage.tsx b/frontend/src/components/AudioResamplerPage.tsx deleted file mode 100644 index 55a0bc7..0000000 --- a/frontend/src/components/AudioResamplerPage.tsx +++ /dev/null @@ -1,468 +0,0 @@ -import { useState, useCallback, useEffect } from "react"; -import { Button } from "@/components/ui/button"; -import { Label } from "@/components/ui/label"; -import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; -import { Upload, X, CheckCircle2, AlertCircle, Trash2, FileMusic } from "lucide-react"; -import { Spinner } from "@/components/ui/spinner"; -import { SelectAudioFiles, SelectFolder, ListAudioFilesInDir, ResampleAudio } from "../../wailsjs/go/main/App"; -import { toastWithSound as toast } from "@/lib/toast-with-sound"; -import { OnFileDrop, OnFileDropOff } from "../../wailsjs/runtime/runtime"; -import { AudioLinesIcon } from "@/components/ui/audio-lines"; -interface AudioFile { - path: string; - name: string; - format: string; - size: number; - status: "pending" | "resampling" | "success" | "error"; - error?: string; - outputPath?: string; - srcSampleRate?: number; - srcBitDepth?: number; -} -function formatFileSize(bytes: number): string { - if (bytes === 0) - return "0 B"; - const k = 1024; - const sizes = ["B", "KB", "MB", "GB"]; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i]; -} -function formatSampleRate(sr: number): string { - if (!sr) - return ""; - if (sr === 44100) - return "44.1kHz"; - if (sr >= 1000) - return `${sr / 1000}kHz`; - return `${sr}Hz`; -} -const SAMPLE_RATE_OPTIONS = [ - { value: "44100", label: "44.1kHz" }, - { value: "48000", label: "48kHz" }, - { value: "96000", label: "96kHz" }, - { value: "192000", label: "192kHz" }, -]; -const BIT_DEPTH_OPTIONS = [ - { value: "16", label: "16-bit" }, - { value: "24", label: "24-bit" }, -]; -const STORAGE_KEY = "spotiflac_audio_resampler_state"; -export function AudioResamplerPage() { - const [files, setFiles] = useState(() => { - try { - const saved = sessionStorage.getItem(STORAGE_KEY); - if (saved) { - const parsed = JSON.parse(saved); - if (parsed.files && Array.isArray(parsed.files) && parsed.files.length > 0) { - return parsed.files; - } - } - } - catch (err) { - console.error("Failed to load saved state:", err); - } - return []; - }); - const [sampleRate, setSampleRate] = useState(() => { - try { - const saved = sessionStorage.getItem(STORAGE_KEY); - if (saved) { - const parsed = JSON.parse(saved); - if (parsed.sampleRate) - return parsed.sampleRate; - } - } - catch (err) { - } - return "44100"; - }); - const [bitDepth, setBitDepth] = useState(() => { - try { - const saved = sessionStorage.getItem(STORAGE_KEY); - if (saved) { - const parsed = JSON.parse(saved); - if (parsed.bitDepth) - return parsed.bitDepth; - } - } - catch (err) { - } - return "16"; - }); - const [resampling, setResampling] = useState(false); - const [isDragging, setIsDragging] = useState(false); - const [isFullscreen, setIsFullscreen] = useState(false); - const saveState = useCallback((stateToSave: { - files: AudioFile[]; - sampleRate: string; - bitDepth: string; - }) => { - try { - sessionStorage.setItem(STORAGE_KEY, JSON.stringify(stateToSave)); - } - catch (err) { - console.error("Failed to save state:", err); - } - }, []); - useEffect(() => { - saveState({ files, sampleRate, bitDepth }); - }, [files, sampleRate, bitDepth, saveState]); - useEffect(() => { - const checkFullscreen = () => { - const isMaximized = window.innerHeight >= window.screen.height * 0.9; - setIsFullscreen(isMaximized); - }; - checkFullscreen(); - window.addEventListener("resize", checkFullscreen); - window.addEventListener("focus", checkFullscreen); - return () => { - window.removeEventListener("resize", checkFullscreen); - window.removeEventListener("focus", checkFullscreen); - }; - }, []); - const fetchAudioInfo = useCallback(async (paths: string[]) => { - if (paths.length === 0) - return; - try { - const GetFlacInfoBatch = (window as any)["go"]["main"]["App"]["GetFlacInfoBatch"]; - const infos: Array<{ - path: string; - sample_rate: number; - bits_per_sample: number; - }> = await GetFlacInfoBatch(paths); - setFiles((prev) => prev.map((f) => { - const info = infos.find((i) => i.path === f.path || i.path.toLowerCase() === f.path.toLowerCase()); - if (info) { - return { - ...f, - srcSampleRate: info.sample_rate || undefined, - srcBitDepth: info.bits_per_sample || undefined, - }; - } - return f; - })); - } - catch (err) { - console.error("Failed to fetch audio info:", err); - } - }, []); - const handleSelectFiles = async () => { - try { - const selectedFiles = await SelectAudioFiles(); - if (selectedFiles && selectedFiles.length > 0) { - addFiles(selectedFiles); - } - } - catch (err) { - toast.error("File Selection Failed", { - description: err instanceof Error ? err.message : "Failed to select files", - }); - } - }; - const handleSelectFolder = async () => { - try { - const selectedFolder = await SelectFolder(""); - if (selectedFolder) { - const folderFiles = await ListAudioFilesInDir(selectedFolder); - if (folderFiles && folderFiles.length > 0) { - addFiles(folderFiles.map((f) => f.path)); - } - else { - toast.info("No audio files found", { - description: "No FLAC files found in the selected folder.", - }); - } - } - } - catch (err) { - toast.error("Folder Selection Failed", { - description: err instanceof Error ? err.message : "Failed to select folder", - }); - } - }; - const addFiles = useCallback(async (paths: string[]) => { - const validExtensions = [".flac"]; - const invalidFiles = paths.filter((path) => { - const ext = path.toLowerCase().slice(path.lastIndexOf(".")); - return !validExtensions.includes(ext); - }); - if (invalidFiles.length > 0) { - toast.error("Unsupported format", { - description: "Only FLAC files are supported for resampling.", - }); - } - const GetFileSizes = (files: string[]): Promise> => (window as any)["go"]["main"]["App"]["GetFileSizes"](files); - const validPaths = paths.filter((path) => { - const ext = path.toLowerCase().slice(path.lastIndexOf(".")); - return validExtensions.includes(ext); - }); - const fileSizes = validPaths.length > 0 ? await GetFileSizes(validPaths) : {}; - let newlyAddedPaths: string[] = []; - setFiles((prev) => { - const newFiles: AudioFile[] = validPaths - .filter((path) => !prev.some((f) => f.path === path)) - .map((path) => { - const name = path.split(/[/\\]/).pop() || path; - const ext = name.slice(name.lastIndexOf(".") + 1).toLowerCase(); - return { - path, - name, - format: ext, - size: fileSizes[path] || 0, - status: "pending" as const, - }; - }); - newlyAddedPaths = newFiles.map((f) => f.path); - if (newFiles.length > 0) { - if (paths.length > newFiles.length + invalidFiles.length) { - const skipped = paths.length - newFiles.length - invalidFiles.length; - toast.info("Some files skipped", { - description: `${skipped} file(s) were already added`, - }); - } - return [...prev, ...newFiles]; - } - if (validPaths.length > 0 && newFiles.length === 0) { - toast.info("No new files added", { - description: "All valid files were already added", - }); - } - return prev; - }); - setTimeout(() => { - if (newlyAddedPaths.length > 0) { - fetchAudioInfo(newlyAddedPaths); - } - }, 50); - }, [fetchAudioInfo]); - const handleFileDrop = useCallback(async (_x: number, _y: number, paths: string[]) => { - setIsDragging(false); - if (paths.length === 0) - return; - addFiles(paths); - }, [addFiles]); - useEffect(() => { - OnFileDrop((x, y, paths) => { - handleFileDrop(x, y, paths); - }, true); - return () => { - OnFileDropOff(); - }; - }, [handleFileDrop]); - const removeFile = (path: string) => { - setFiles((prev) => prev.filter((f) => f.path !== path)); - }; - const clearFiles = () => { - setFiles([]); - }; - const handleResample = async () => { - if (files.length === 0) { - toast.error("No files selected", { - description: "Please add FLAC files to resample", - }); - return; - } - setResampling(true); - try { - const inputPaths = files.map((f) => f.path); - setFiles((prev) => prev.map((f) => { - if (inputPaths.includes(f.path)) { - return { ...f, status: "resampling" as const, error: undefined }; - } - return f; - })); - const results = await ResampleAudio({ - input_files: inputPaths, - sample_rate: sampleRate, - bit_depth: bitDepth, - }); - setFiles((prev) => prev.map((f) => { - const result = results.find((r: any) => r.input_file === f.path || r.input_file.toLowerCase() === f.path.toLowerCase()); - if (result) { - return { - ...f, - status: result.success ? "success" : "error", - error: result.error, - outputPath: result.output_file, - }; - } - return f; - })); - const successCount = results.filter((r: any) => r.success).length; - const failCount = results.filter((r: any) => !r.success).length; - if (successCount > 0) { - toast.success("Resampling Complete", { - description: `Successfully resampled ${successCount} file(s)${failCount > 0 ? `, ${failCount} failed` : ""}`, - }); - } - else if (failCount > 0) { - toast.error("Resampling Failed", { - description: `All ${failCount} file(s) failed to resample`, - }); - } - } - catch (err) { - toast.error("Resampling Error", { - description: err instanceof Error ? err.message : "Unknown error", - }); - setFiles((prev) => prev.map((f) => ({ ...f, status: "error" as const, error: "Resampling failed" }))); - } - finally { - setResampling(false); - } - }; - const getStatusIcon = (status: AudioFile["status"]) => { - switch (status) { - case "resampling": - return ; - case "success": - return ; - case "error": - return ; - default: - return ; - } - }; - const resampleableCount = files.filter((f) => f.status === "pending" || f.status === "success").length; - const successCount = files.filter((f) => f.status === "success").length; - return (
- -
-

Audio Resampler

- {files.length > 0 && (
- - - -
)} -
- -
{ - e.preventDefault(); - setIsDragging(true); - }} onDragLeave={(e) => { - e.preventDefault(); - setIsDragging(false); - }} onDrop={(e) => { - e.preventDefault(); - setIsDragging(false); - }} style={{ "--wails-drop-target": "drop" } as React.CSSProperties}> - {files.length === 0 ? (<> -
- -
-

- {isDragging - ? "Drop your audio files here" - : "Drag and drop audio files here, or click the button below to select"} -

-
- - -
-

- Supported format: FLAC -

- ) : (
-
-
-
- - { - if (value) - setBitDepth(value); - }}> - {BIT_DEPTH_OPTIONS.map((option) => ( - {option.label} - ))} - -
- -
- - { - if (value) - setSampleRate(value); - }}> - {SAMPLE_RATE_OPTIONS.map((option) => ( - {option.label} - ))} - -
-
-
- -
-
- {files.length} file(s) • {successCount} resampled -
-
- -
- {files.map((file) => { - const srcParts: string[] = []; - if (file.srcBitDepth) - srcParts.push(`${file.srcBitDepth}-bit`); - if (file.srcSampleRate) - srcParts.push(formatSampleRate(file.srcSampleRate)); - const srcSpec = srcParts.join(" / "); - return (
- {getStatusIcon(file.status)} -
-

{file.name}

- {file.error && (

- {file.error} -

)} -
- - {srcSpec ? ( - {srcSpec} - ) : file.status === "pending" ? ( - reading... - ) : null} - - - {formatFileSize(file.size)} - - - {file.format} - - {file.status !== "resampling" && ()} -
); - })} -
- -
- -
-
)} -
-
); -} diff --git a/frontend/src/components/AvailabilityLinks.tsx b/frontend/src/components/AvailabilityLinks.tsx deleted file mode 100644 index 58791d9..0000000 --- a/frontend/src/components/AvailabilityLinks.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import type { ReactNode } from "react"; -import type { TrackAvailability } from "@/types/api"; -import { openExternal } from "@/lib/utils"; -import { AmazonAvailabilityIcon, QobuzAvailabilityIcon, TidalAvailabilityIcon } from "./PlatformIcons"; -interface AvailabilityLinkEntry { - id: string; - found: boolean; - url?: string; - icon: ReactNode; -} -function getAvailabilityLinkEntries(availability: TrackAvailability): AvailabilityLinkEntry[] { - const tidalUrl = availability.tidal_url?.trim() || ""; - const qobuzUrl = availability.qobuz_url?.trim() || ""; - const amazonUrl = availability.amazon_url?.trim() || ""; - return [ - { - id: "tidal", - found: tidalUrl !== "", - url: tidalUrl, - icon: , - }, - { - id: "qobuz", - found: qobuzUrl !== "", - url: qobuzUrl, - icon: , - }, - { - id: "amazon", - found: amazonUrl !== "", - url: amazonUrl, - icon: , - }, - ]; -} -export function hasAvailabilityLinks(availability?: TrackAvailability): boolean { - if (!availability) { - return false; - } - return getAvailabilityLinkEntries(availability).some((entry) => entry.found); -} -export function AvailabilityLinks({ availability }: { - availability?: TrackAvailability; -}) { - if (!availability) { - return

Check Availability

; - } - const entries = getAvailabilityLinkEntries(availability); - return (
- {entries.map((entry) => entry.found ? () : (
- {entry.icon} - - Not Found - -
))} -
); -} diff --git a/frontend/src/components/DebugLoggerPage.tsx b/frontend/src/components/DebugLoggerPage.tsx deleted file mode 100644 index ec463cd..0000000 --- a/frontend/src/components/DebugLoggerPage.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { useState, useEffect, useRef } from "react"; -import { Trash2, Copy, Check, FileDown } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { logger, type LogEntry } from "@/lib/logger"; -import { useDownloadQueueData } from "@/hooks/useDownloadQueueData"; -import { ExportFailedDownloads } from "../../wailsjs/go/main/App"; -import { toastWithSound as toast } from "@/lib/toast-with-sound"; -const levelColors: Record = { - info: "text-blue-500", - success: "text-green-500", - warning: "text-yellow-500", - error: "text-red-500", - debug: "text-gray-500", -}; -function formatTime(date: Date): string { - return date.toLocaleTimeString("en-US", { - hour12: false, - hour: "2-digit", - minute: "2-digit", - second: "2-digit", - }); -} -export function DebugLoggerPage() { - const [logs, setLogs] = useState([]); - const [copied, setCopied] = useState(false); - const scrollRef = useRef(null); - const queueInfo = useDownloadQueueData(); - const hasDownloadActivity = queueInfo.queue.length > 0 || - queueInfo.queued_count > 0 || - queueInfo.completed_count > 0 || - queueInfo.failed_count > 0 || - queueInfo.skipped_count > 0; - const canExportFailed = hasDownloadActivity && queueInfo.failed_count > 0; - useEffect(() => { - const unsubscribe = logger.subscribe(() => { - setLogs(logger.getLogs()); - }); - setLogs(logger.getLogs()); - return () => { - unsubscribe(); - }; - }, []); - useEffect(() => { - if (scrollRef.current) { - scrollRef.current.scrollTop = scrollRef.current.scrollHeight; - } - }, [logs]); - const handleClear = () => { - logger.clear(); - }; - const handleCopy = async () => { - const logText = logs - .map((log) => `[${formatTime(log.timestamp)}] [${log.level}] ${log.message}`) - .join("\n"); - try { - await navigator.clipboard.writeText(logText); - setCopied(true); - setTimeout(() => setCopied(false), 500); - } - catch (err) { - console.error("Failed to copy logs:", err); - } - }; - const handleExportFailed = async () => { - if (!canExportFailed) { - return; - } - try { - const message = await ExportFailedDownloads(); - if (message.startsWith("Successfully")) { - toast.success(message); - } - else if (message !== "Export cancelled") { - toast.info(message); - } - } - catch (error) { - console.error("Failed to export:", error); - toast.error(`Failed to export: ${error}`); - } - }; - return (
-
-

Debug Logs

-
- - - -
-
- -
- {logs.length === 0 ? (

no logs yet...

) : (logs.map((log, i) => (
- - [{formatTime(log.timestamp)}] - - - [{log.level}] - - {log.message} -
)))} -
-
); -} diff --git a/frontend/src/components/DownloadProgress.tsx b/frontend/src/components/DownloadProgress.tsx deleted file mode 100644 index d790e4a..0000000 --- a/frontend/src/components/DownloadProgress.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Button } from "@/components/ui/button"; -import { Progress } from "@/components/ui/progress"; -import { StopCircle } from "lucide-react"; -interface DownloadProgressProps { - progress: number; - remainingCount?: number; - currentTrack: { - name: string; - artists: string; - } | null; - onStop: () => void; -} -export function DownloadProgress({ progress, remainingCount = 0, currentTrack, onStop }: DownloadProgressProps) { - const clampedProgress = Math.min(100, Math.max(0, progress)); - const safeRemainingCount = Math.max(0, remainingCount); - const remainingLabel = `${safeRemainingCount.toLocaleString()} ${safeRemainingCount === 1 ? "track" : "tracks"} left`; - return (
-
- - -
-

- {clampedProgress}% • {remainingLabel} -{" "} - {currentTrack - ? `${currentTrack.name} - ${currentTrack.artists}` - : "Preparing download..."} -

-
); -} diff --git a/frontend/src/components/DownloadProgressToast.tsx b/frontend/src/components/DownloadProgressToast.tsx deleted file mode 100644 index 50ee002..0000000 --- a/frontend/src/components/DownloadProgressToast.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { useDownloadProgress } from "@/hooks/useDownloadProgress"; -import { useDownloadQueueData } from "@/hooks/useDownloadQueueData"; -import { Download, ChevronRight } from "lucide-react"; -import { Button } from "@/components/ui/button"; -interface DownloadProgressToastProps { - onClick: () => void; -} -export function DownloadProgressToast({ onClick }: DownloadProgressToastProps) { - const progress = useDownloadProgress(); - const queueInfo = useDownloadQueueData(); - const hasActiveDownloads = queueInfo.queue.some(item => item.status === "queued" || item.status === "downloading"); - if (!hasActiveDownloads) { - return null; - } - return (
- -
); -} diff --git a/frontend/src/components/DownloadQueue.tsx b/frontend/src/components/DownloadQueue.tsx deleted file mode 100644 index d806aac..0000000 --- a/frontend/src/components/DownloadQueue.tsx +++ /dev/null @@ -1,274 +0,0 @@ -import { useEffect, useState } from "react"; -import { X, Download, CheckCircle2, XCircle, Clock, FileCheck, Trash2, HardDrive, Zap, Timer, FileDown } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; -import { Badge } from "@/components/ui/badge"; -import { GetDownloadQueue, ClearCompletedDownloads, ClearAllDownloads, ExportFailedDownloads } from "../../wailsjs/go/main/App"; -import { toastWithSound as toast } from "@/lib/toast-with-sound"; -import { backend } from "../../wailsjs/go/models"; -interface DownloadQueueProps { - isOpen: boolean; - onClose: () => void; -} -export function DownloadQueue({ isOpen, onClose }: DownloadQueueProps) { - const [queueInfo, setQueueInfo] = useState(new backend.DownloadQueueInfo({ - is_downloading: false, - queue: [], - current_speed: 0, - total_downloaded: 0, - session_start_time: 0, - queued_count: 0, - completed_count: 0, - failed_count: 0, - skipped_count: 0, - })); - useEffect(() => { - if (!isOpen) - return; - const fetchQueue = async () => { - try { - const info = await GetDownloadQueue(); - setQueueInfo(info); - } - catch (error) { - console.error("Failed to get download queue:", error); - } - }; - fetchQueue(); - const interval = setInterval(fetchQueue, 500); - return () => clearInterval(interval); - }, [isOpen]); - const handleClearHistory = async () => { - try { - await ClearCompletedDownloads(); - const info = await GetDownloadQueue(); - setQueueInfo(info); - } - catch (error) { - console.error("Failed to clear history:", error); - } - }; - const handleReset = async () => { - try { - await ClearAllDownloads(); - const info = await GetDownloadQueue(); - setQueueInfo(info); - toast.success("Download queue reset"); - } - catch (error) { - console.error("Failed to reset queue:", error); - } - }; - const handleExportFailed = async () => { - try { - const message = await ExportFailedDownloads(); - if (message.startsWith("Successfully")) { - toast.success(message); - } - else if (message !== "Export cancelled") { - toast.info(message); - } - } - catch (error) { - console.error("Failed to export:", error); - toast.error(`Failed to export: ${error}`); - } - }; - const getStatusIcon = (status: string) => { - switch (status) { - case "downloading": - return ; - case "completed": - return ; - case "failed": - return ; - case "skipped": - return ; - case "queued": - return ; - default: - return null; - } - }; - const getStatusBadge = (status: string) => { - const variants: Record = { - downloading: "default", - completed: "outline", - failed: "destructive", - skipped: "secondary", - queued: "outline", - }; - return ( - {status} - ); - }; - const formatDuration = (startTimestamp: number) => { - if (startTimestamp === 0) - return "—"; - const now = Math.floor(Date.now() / 1000); - const durationSeconds = now - startTimestamp; - const hours = Math.floor(durationSeconds / 3600); - const minutes = Math.floor((durationSeconds % 3600) / 60); - const seconds = durationSeconds % 60; - if (hours > 0) { - return `${hours}h ${minutes}m ${seconds}s`; - } - else if (minutes > 0) { - return `${minutes}m ${seconds}s`; - } - else { - return `${seconds}s`; - } - }; - const [filterStatus, setFilterStatus] = useState("all"); - const toggleFilter = (status: string) => { - setFilterStatus(prev => prev === status ? "all" : status); - }; - const filteredQueue = queueInfo.queue.filter((item: any) => { - if (filterStatus === "all") - return true; - return item.status === filterStatus; - }); - return ( - - -
- Download Queue -
- {(queueInfo.completed_count > 0 || queueInfo.failed_count > 0 || queueInfo.skipped_count > 0) && ()} - {queueInfo.failed_count > 0 && ()} - -
-
- - -
-
toggleFilter('queued')}> - - Queued: - {queueInfo.queued_count} -
-
toggleFilter('completed')}> - - Completed: - {queueInfo.completed_count} -
-
toggleFilter('skipped')}> - - Skipped: - {queueInfo.skipped_count} -
-
toggleFilter('failed')}> - - Failed: - {queueInfo.failed_count} -
-
- - -
-
- - Downloaded: - - {queueInfo.total_downloaded > 0 ? `${queueInfo.total_downloaded.toFixed(2)} MB` : "0.00 MB"} - -
-
- - Speed: - - {queueInfo.current_speed > 0 && queueInfo.is_downloading - ? `${queueInfo.current_speed.toFixed(2)} MB/s` - : "—"} - -
-
- - Duration: - - {queueInfo.session_start_time > 0 ? formatDuration(queueInfo.session_start_time) : "—"} - -
-
- -
- - -
-
- {queueInfo.queue.length === 0 ? (
- -

No downloads in queue

-
) : filteredQueue.length === 0 ? (
-

No downloads with status "{filterStatus}"

- -
) : (filteredQueue.map((item: any) => (
-
-
{getStatusIcon(item.status)}
- -
-
-
-

{item.track_name}

-

- {item.artist_name} - {item.album_name && ` • ${item.album_name}`} -

-
- {getStatusBadge(item.status)} -
- - - {item.status === "downloading" && (
- - {item.progress > 0 - ? `${item.progress.toFixed(2)} MB` - : queueInfo.is_downloading && queueInfo.current_speed > 0 - ? "Downloading..." - : "Starting..."} - - - {item.speed > 0 - ? `${item.speed.toFixed(2)} MB/s` - : queueInfo.current_speed > 0 - ? `${queueInfo.current_speed.toFixed(2)} MB/s` - : "—"} - -
)} - - - {item.status === "completed" && (
- {item.progress.toFixed(2)} MB -
)} - - - {item.status === "skipped" && (
- File already exists -
)} - - - {item.status === "failed" && item.error_message && (
- {item.error_message} -
)} - - - {(item.status === "completed" || item.status === "skipped") && item.file_path && (
- {item.file_path} -
)} -
-
-
)))} -
-
-
-
); -} diff --git a/frontend/src/components/FetchHistory.tsx b/frontend/src/components/FetchHistory.tsx deleted file mode 100644 index 774b3a0..0000000 --- a/frontend/src/components/FetchHistory.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { X, Music2, Disc3, ListMusic, UserRound } from "lucide-react"; -export interface HistoryItem { - id: string; - url: string; - type: "track" | "album" | "playlist" | "artist"; - name: string; - artist: string; - image: string; - timestamp: number; -} -interface FetchHistoryProps { - history: HistoryItem[]; - onSelect: (item: HistoryItem) => void; - onRemove: (id: string) => void; -} -export function FetchHistory({ history, onSelect, onRemove }: FetchHistoryProps) { - if (history.length === 0) - return null; - const getTypeLabel = (type: string) => { - switch (type) { - case "track": - return "Track"; - case "album": - return "Album"; - case "playlist": - return "Playlist"; - case "artist": - return "Artist"; - default: - return type; - } - }; - const getTypeIcon = (type: string) => { - switch (type) { - case "track": - return Music2; - case "album": - return Disc3; - case "playlist": - return ListMusic; - case "artist": - return UserRound; - default: - return null; - } - }; - const getTypeBadgeClass = (type: string) => { - switch (type) { - case "track": - return "bg-blue-500/10 text-blue-600 dark:bg-blue-500/20 dark:text-blue-400"; - case "album": - return "bg-green-500/10 text-green-600 dark:bg-green-500/20 dark:text-green-400"; - case "playlist": - return "bg-purple-500/10 text-purple-600 dark:bg-purple-500/20 dark:text-purple-400"; - case "artist": - return "bg-orange-500/10 text-orange-600 dark:bg-orange-500/20 dark:text-orange-400"; - default: - return "bg-muted text-muted-foreground"; - } - }; - return (
- {history.length === 1 ? "Recent Fetch" : "Recent Fetches"} -
- {history.map((item) => (
onSelect(item)}> - -
-
- {item.image ? ({item.name}) : (
- No Image -
)} -
-
-

- {item.name} -

-

- {item.artist} -

- {(() => { - const IconComponent = getTypeIcon(item.type); - return ( - {IconComponent ? : null} - {getTypeLabel(item.type)} - ); - })()} -
-
-
))} -
-
); -} diff --git a/frontend/src/components/FileManagerPage.tsx b/frontend/src/components/FileManagerPage.tsx deleted file mode 100644 index 5deba40..0000000 --- a/frontend/src/components/FileManagerPage.tsx +++ /dev/null @@ -1,743 +0,0 @@ -import { useState, useEffect, useCallback } from "react"; -import { Button } from "@/components/ui/button"; -import { Label } from "@/components/ui/label"; -import { InputWithContext } from "@/components/ui/input-with-context"; -import { Checkbox } from "@/components/ui/checkbox"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; -import { FolderOpen, RefreshCw, FileMusic, ChevronRight, ChevronDown, Pencil, Eye, Folder, Info, RotateCcw, FileText, Image, Copy, Check, } from "lucide-react"; -import { Tooltip, TooltipTrigger, TooltipContent } from "@/components/ui/tooltip"; -import { Spinner } from "@/components/ui/spinner"; -import { Badge } from "@/components/ui/badge"; -import { SelectFolder } from "../../wailsjs/go/main/App"; -import { backend } from "../../wailsjs/go/models"; -import { toastWithSound as toast } from "@/lib/toast-with-sound"; -import { getSettings } from "@/lib/settings"; -import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; -const ListDirectoryFiles = (path: string): Promise => (window as any)['go']['main']['App']['ListDirectoryFiles'](path); -const PreviewRenameFiles = (files: string[], format: string): Promise => (window as any)['go']['main']['App']['PreviewRenameFiles'](files, format); -const RenameFilesByMetadata = (files: string[], format: string): Promise => (window as any)['go']['main']['App']['RenameFilesByMetadata'](files, format); -const ReadFileMetadata = (path: string): Promise => (window as any)['go']['main']['App']['ReadFileMetadata'](path); -const ReadTextFile = (path: string): Promise => (window as any)['go']['main']['App']['ReadTextFile'](path); -const RenameFileTo = (oldPath: string, newName: string): Promise => (window as any)['go']['main']['App']['RenameFileTo'](oldPath, newName); -const ReadImageAsBase64 = (path: string): Promise => (window as any)['go']['main']['App']['ReadImageAsBase64'](path); -interface FileNode { - name: string; - path: string; - is_dir: boolean; - size: number; - children?: FileNode[]; - expanded?: boolean; -} -interface FileMetadata { - title: string; - artist: string; - album: string; - album_artist: string; - track_number: number; - disc_number: number; - year: string; - upc?: string; - isrc?: string; -} -type TabType = "track" | "lyric" | "cover"; -const FORMAT_PRESETS: Record = { - "title": { label: "Title", template: "{title}" }, - "title-artist": { label: "Title - Artist", template: "{title} - {artist}" }, - "artist-title": { label: "Artist - Title", template: "{artist} - {title}" }, - "track-title": { label: "Track. Title", template: "{track}. {title}" }, - "track-title-artist": { label: "Track. Title - Artist", template: "{track}. {title} - {artist}" }, - "track-artist-title": { label: "Track. Artist - Title", template: "{track}. {artist} - {title}" }, - "title-album-artist": { label: "Title - Album Artist", template: "{title} - {album_artist}" }, - "track-title-album-artist": { label: "Track. Title - Album Artist", template: "{track}. {title} - {album_artist}" }, - "artist-album-title": { label: "Artist - Album - Title", template: "{artist} - {album} - {title}" }, - "track-dash-title": { label: "Track - Title", template: "{track} - {title}" }, - "disc-track-title": { label: "Disc-Track. Title", template: "{disc}-{track}. {title}" }, - "disc-track-title-artist": { label: "Disc-Track. Title - Artist", template: "{disc}-{track}. {title} - {artist}" }, - "custom": { label: "Custom...", template: "{title} - {artist}" }, -}; -const STORAGE_KEY = "spotiflac_file_manager_state"; -const DEFAULT_PRESET = "title-artist"; -const DEFAULT_CUSTOM_FORMAT = "{title} - {artist}"; -function formatFileSize(bytes: number): string { - if (bytes === 0) - return "0 B"; - const k = 1024; - const sizes = ["B", "KB", "MB", "GB"]; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i]; -} -export function FileManagerPage() { - const [rootPath, setRootPath] = useState(() => { - const settings = getSettings(); - return settings.downloadPath || ""; - }); - const [allFiles, setAllFiles] = useState([]); - const [selectedFiles, setSelectedFiles] = useState>(new Set()); - const [loading, setLoading] = useState(false); - const [activeTab, setActiveTab] = useState("track"); - const [formatPreset, setFormatPreset] = useState(() => { - try { - const saved = localStorage.getItem(STORAGE_KEY); - if (saved) { - const parsed = JSON.parse(saved); - if (parsed.formatPreset && FORMAT_PRESETS[parsed.formatPreset]) { - return parsed.formatPreset; - } - } - } - catch { } - return DEFAULT_PRESET; - }); - const [customFormat, setCustomFormat] = useState(() => { - try { - const saved = localStorage.getItem(STORAGE_KEY); - if (saved) { - const parsed = JSON.parse(saved); - if (parsed.customFormat) - return parsed.customFormat; - } - } - catch { } - return DEFAULT_CUSTOM_FORMAT; - }); - const renameFormat = formatPreset === "custom" ? (customFormat || FORMAT_PRESETS["custom"].template) : FORMAT_PRESETS[formatPreset].template; - const [showPreview, setShowPreview] = useState(false); - const [previewData, setPreviewData] = useState([]); - const [renaming, setRenaming] = useState(false); - const [previewOnly, setPreviewOnly] = useState(false); - const [isFullscreen, setIsFullscreen] = useState(false); - const [showResetConfirm, setShowResetConfirm] = useState(false); - const [showMetadata, setShowMetadata] = useState(false); - const [metadataFile, setMetadataFile] = useState(""); - const [metadataInfo, setMetadataInfo] = useState(null); - const [loadingMetadata, setLoadingMetadata] = useState(false); - const [showLyricsPreview, setShowLyricsPreview] = useState(false); - const [lyricsContent, setLyricsContent] = useState(""); - const [lyricsFile, setLyricsFile] = useState(""); - const [lyricsTab, setLyricsTab] = useState<"synced" | "plain">("synced"); - const [copySuccess, setCopySuccess] = useState(false); - const [showCoverPreview, setShowCoverPreview] = useState(false); - const [coverFile, setCoverFile] = useState(""); - const [coverData, setCoverData] = useState(""); - const [showManualRename, setShowManualRename] = useState(false); - const [manualRenameFile, setManualRenameFile] = useState(""); - const [manualRenameName, setManualRenameName] = useState(""); - const [manualRenaming, setManualRenaming] = useState(false); - useEffect(() => { - try { - localStorage.setItem(STORAGE_KEY, JSON.stringify({ formatPreset, customFormat })); - } - catch { } - }, [formatPreset, customFormat]); - useEffect(() => { - const checkFullscreen = () => { - const isMaximized = window.innerHeight >= window.screen.height * 0.9; - setIsFullscreen(isMaximized); - }; - checkFullscreen(); - window.addEventListener("resize", checkFullscreen); - window.addEventListener("focus", checkFullscreen); - return () => { - window.removeEventListener("resize", checkFullscreen); - window.removeEventListener("focus", checkFullscreen); - }; - }, []); - const filterFilesByType = (nodes: FileNode[], type: TabType): FileNode[] => { - return nodes - .map((node) => { - if (node.is_dir && node.children) { - const filteredChildren = filterFilesByType(node.children, type); - if (filteredChildren.length > 0) { - return { ...node, children: filteredChildren }; - } - return null; - } - const ext = node.name.toLowerCase(); - if (type === "track" && (ext.endsWith(".flac") || ext.endsWith(".mp3") || ext.endsWith(".m4a"))) - return node; - if (type === "lyric" && ext.endsWith(".lrc")) - return node; - if (type === "cover" && (ext.endsWith(".jpg") || ext.endsWith(".jpeg") || ext.endsWith(".png"))) - return node; - return null; - }) - .filter((node): node is FileNode => node !== null); - }; - const loadFiles = useCallback(async () => { - if (!rootPath) - return; - setLoading(true); - try { - const result = await ListDirectoryFiles(rootPath); - if (!result || !Array.isArray(result)) { - setAllFiles([]); - setSelectedFiles(new Set()); - return; - } - setAllFiles(result as FileNode[]); - setSelectedFiles(new Set()); - } - catch (err) { - const errorMsg = err instanceof Error ? err.message : String(err || ""); - if (!errorMsg.toLowerCase().includes("empty") && !errorMsg.toLowerCase().includes("no file")) { - toast.error("Failed to load files", { description: errorMsg || "Unknown error" }); - } - setAllFiles([]); - setSelectedFiles(new Set()); - } - finally { - setLoading(false); - } - }, [rootPath]); - useEffect(() => { - if (rootPath) - loadFiles(); - }, [rootPath, loadFiles]); - const filteredFiles = filterFilesByType(allFiles, activeTab); - const getAllFilesFlat = (nodes: FileNode[]): FileNode[] => { - const result: FileNode[] = []; - for (const node of nodes) { - if (!node.is_dir) - result.push(node); - if (node.children) - result.push(...getAllFilesFlat(node.children)); - } - return result; - }; - const allAudioFiles = getAllFilesFlat(filterFilesByType(allFiles, "track")); - const allLyricFiles = getAllFilesFlat(filterFilesByType(allFiles, "lyric")); - const allCoverFiles = getAllFilesFlat(filterFilesByType(allFiles, "cover")); - const handleSelectFolder = async () => { - try { - const path = await SelectFolder(rootPath); - if (path) - setRootPath(path); - } - catch (err) { - toast.error("Failed to select folder", { description: err instanceof Error ? err.message : "Unknown error" }); - } - }; - const toggleExpand = (path: string) => { - setAllFiles((prev) => toggleNodeExpand(prev, path)); - }; - const toggleNodeExpand = (nodes: FileNode[], path: string): FileNode[] => { - return nodes.map((node) => { - if (node.path === path) - return { ...node, expanded: !node.expanded }; - if (node.children) - return { ...node, children: toggleNodeExpand(node.children, path) }; - return node; - }); - }; - const toggleSelect = (path: string) => { - setSelectedFiles((prev) => { - const newSet = new Set(prev); - if (newSet.has(path)) - newSet.delete(path); - else - newSet.add(path); - return newSet; - }); - }; - const toggleFolderSelect = (node: FileNode) => { - const folderFiles = getAllFilesFlat([node]); - const allSelected = folderFiles.every((f) => selectedFiles.has(f.path)); - setSelectedFiles((prev) => { - const newSet = new Set(prev); - if (allSelected) - folderFiles.forEach((f) => newSet.delete(f.path)); - else - folderFiles.forEach((f) => newSet.add(f.path)); - return newSet; - }); - }; - const isFolderSelected = (node: FileNode): boolean | "indeterminate" => { - const folderFiles = getAllFilesFlat([node]); - if (folderFiles.length === 0) - return false; - const selectedCount = folderFiles.filter((f) => selectedFiles.has(f.path)).length; - if (selectedCount === 0) - return false; - if (selectedCount === folderFiles.length) - return true; - return "indeterminate"; - }; - const selectAll = () => setSelectedFiles(new Set(allAudioFiles.map((f) => f.path))); - const deselectAll = () => setSelectedFiles(new Set()); - const resetToDefault = () => { setFormatPreset(DEFAULT_PRESET); setCustomFormat(DEFAULT_CUSTOM_FORMAT); setShowResetConfirm(false); }; - const handlePreview = async (isPreviewOnly: boolean) => { - if (selectedFiles.size === 0) { - toast.error("No files selected"); - return; - } - try { - const result = await PreviewRenameFiles(Array.from(selectedFiles), renameFormat); - setPreviewData(result); - setPreviewOnly(isPreviewOnly); - setShowPreview(true); - } - catch (err) { - toast.error("Failed to generate preview", { description: err instanceof Error ? err.message : "Unknown error" }); - } - }; - const handleShowMetadata = async (filePath: string, e: React.MouseEvent) => { - e.stopPropagation(); - setMetadataFile(filePath); - setLoadingMetadata(true); - try { - const metadata = await ReadFileMetadata(filePath); - setMetadataInfo(metadata as FileMetadata); - setShowMetadata(true); - } - catch (err) { - toast.error("Failed to read metadata", { description: err instanceof Error ? err.message : "Unknown error" }); - setMetadataInfo(null); - } - finally { - setLoadingMetadata(false); - } - }; - const handleShowLyrics = async (filePath: string, e: React.MouseEvent) => { - e.stopPropagation(); - setLyricsFile(filePath); - setLyricsTab("synced"); - try { - const content = await ReadTextFile(filePath); - setLyricsContent(content); - setShowLyricsPreview(true); - } - catch (err) { - toast.error("Failed to read lyrics file", { description: err instanceof Error ? err.message : "Unknown error" }); - } - }; - const handleShowCover = async (filePath: string, e: React.MouseEvent) => { - e.stopPropagation(); - setCoverFile(filePath); - try { - const data = await ReadImageAsBase64(filePath); - setCoverData(data); - setShowCoverPreview(true); - } - catch (err) { - toast.error("Failed to load image", { description: err instanceof Error ? err.message : "Unknown error" }); - } - }; - const getPlainLyrics = (content: string) => { - return content.split('\n').map(line => line.replace(/^\[[\d:.]+\]\s*/, '')).filter(line => !line.startsWith('[') || line.includes(']')).map(line => line.startsWith('[') ? '' : line).join('\n').trim(); - }; - const formatTimestamp = (timestamp: string): string => { - const match = timestamp.match(/\[(\d+):(\d+)(?:\.(\d+))?\]/); - if (!match) - return timestamp; - const minutes = parseInt(match[1], 10); - const seconds = match[2]; - return `${minutes}:${seconds}`; - }; - const renderSyncedLyrics = (content: string) => { - if (!content) - return
No lyrics content
; - const lines = content.split('\n'); - return lines.map((line, index) => { - if (line.match(/^\[(ti|ar|al|by|length|offset):/i)) - return null; - const match = line.match(/^(\[[\d:.]+\])(.*)$/); - if (match) { - const timestamp = match[1]; - const text = match[2].trim(); - if (!text) - return null; - return (
- - {formatTimestamp(timestamp)} - - {text} -
); - } - if (!line.trim()) - return null; - return (
- {line} -
); - }).filter(item => item !== null); - }; - const handleCopyLyrics = async () => { - try { - const textToCopy = lyricsTab === "synced" ? lyricsContent : getPlainLyrics(lyricsContent); - await navigator.clipboard.writeText(textToCopy); - setCopySuccess(true); - setTimeout(() => setCopySuccess(false), 500); - } - catch { - toast.error("Failed to copy lyrics"); - } - }; - const handleManualRename = (filePath: string, e: React.MouseEvent) => { - e.stopPropagation(); - const fileName = filePath.split(/[/\\]/).pop() || ""; - const nameWithoutExt = fileName.replace(/\.[^.]+$/, ""); - setManualRenameFile(filePath); - setManualRenameName(nameWithoutExt); - setShowManualRename(true); - }; - const handleConfirmManualRename = async () => { - if (!manualRenameFile || !manualRenameName.trim()) - return; - setManualRenaming(true); - try { - await RenameFileTo(manualRenameFile, manualRenameName.trim()); - toast.success("File renamed successfully"); - setShowManualRename(false); - loadFiles(); - } - catch (err) { - toast.error("Failed to rename file", { description: err instanceof Error ? err.message : "Unknown error" }); - } - finally { - setManualRenaming(false); - } - }; - const handleRename = async () => { - if (selectedFiles.size === 0) - return; - setRenaming(true); - try { - const result = await RenameFilesByMetadata(Array.from(selectedFiles), renameFormat); - const successCount = result.filter((r: backend.RenameResult) => r.success).length; - const failCount = result.filter((r: backend.RenameResult) => !r.success).length; - if (successCount > 0) - toast.success("Rename Complete", { description: `${successCount} file(s) renamed${failCount > 0 ? `, ${failCount} failed` : ""}` }); - else - toast.error("Rename Failed", { description: `All ${failCount} file(s) failed to rename` }); - setShowPreview(false); - setSelectedFiles(new Set()); - loadFiles(); - } - catch (err) { - toast.error("Rename Failed", { description: err instanceof Error ? err.message : "Unknown error" }); - } - finally { - setRenaming(false); - } - }; - const renderTrackTree = (nodes: FileNode[], depth = 0) => { - return nodes.map((node) => (
-
(node.is_dir ? toggleExpand(node.path) : toggleSelect(node.path))}> - {node.is_dir ? (<> - { - if (el) - (el as HTMLButtonElement).dataset.state = isFolderSelected(node) === "indeterminate" ? "indeterminate" : isFolderSelected(node) ? "checked" : "unchecked"; - }} onCheckedChange={() => toggleFolderSelect(node)} onClick={(e) => e.stopPropagation()} className="shrink-0 data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground"/> - {node.expanded ? : } - - ) : (<> - toggleSelect(node.path)} onClick={(e) => e.stopPropagation()} className="shrink-0"/> - - )} - - {node.name} - {node.is_dir && ({getAllFilesFlat([node]).length})} - - {!node.is_dir && (<> - {formatFileSize(node.size)} - - - - - View Metadata - - )} -
- {node.is_dir && node.expanded && node.children &&
{renderTrackTree(node.children, depth + 1)}
} -
)); - }; - const renderLyricTree = (nodes: FileNode[], depth = 0) => { - return nodes.map((node) => (
-
node.is_dir ? toggleExpand(node.path) : handleShowLyrics(node.path, e)}> - {node.is_dir ? (<> - {node.expanded ? : } - - ) : ()} - - {node.name} - {node.is_dir && ({getAllFilesFlat([node]).length})} - - {!node.is_dir && (<> - {formatFileSize(node.size)} - - - - - Rename - - )} -
- {node.is_dir && node.expanded && node.children &&
{renderLyricTree(node.children, depth + 1)}
} -
)); - }; - const renderCoverTree = (nodes: FileNode[], depth = 0) => { - return nodes.map((node) => (
-
node.is_dir ? toggleExpand(node.path) : handleShowCover(node.path, e)}> - {node.is_dir ? (<> - {node.expanded ? : } - - ) : ()} - - {node.name} - {node.is_dir && ({getAllFilesFlat([node]).length})} - - {!node.is_dir && (<> - {formatFileSize(node.size)} - - - - - Rename - - )} -
- {node.is_dir && node.expanded && node.children &&
{renderCoverTree(node.children, depth + 1)}
} -
)); - }; - const allSelected = allAudioFiles.length > 0 && selectedFiles.size === allAudioFiles.length; - return (
-
-

File Manager

-
- - -
- setRootPath(e.target.value)} placeholder="Select a folder..." className="flex-1"/> - - -
- - -
- - - -
- - - {activeTab === "track" && (
-
- - - - - - -

Variables: {"{title}"}, {"{artist}"}, {"{album}"}, {"{album_artist}"}, {"{track}"}, {"{disc}"}, {"{year}"}, {"{date}"}, {"{isrc}"}

-
-
-
-
- - {formatPreset === "custom" && ( setCustomFormat(e.target.value)} placeholder="{artist} - {title}" className="flex-1"/>)} - - - - - Reset to Default - -
-

- Preview: {renameFormat.replace(/\{title\}/g, "All The Stars").replace(/\{artist\}/g, "Kendrick Lamar, SZA").replace(/\{album\}/g, "Black Panther").replace(/\{album_artist\}/g, "Kendrick Lamar").replace(/\{track\}/g, "01").replace(/\{disc\}/g, "1").replace(/\{year\}/g, "2018").replace(/\{date\}/g, "2018-02-09").replace(/\{isrc\}/g, "USUM71801234")}.flac -

-
)} - - -
- {activeTab === "track" && (
-
- - {selectedFiles.size} of {allAudioFiles.length} file(s) selected -
-
- - -
-
)} - -
- {loading ? (
) : filteredFiles.length === 0 ? (
- {rootPath ? `No ${activeTab} files found` : "Select a folder to browse"} -
) : (activeTab === "track" ? renderTrackTree(filteredFiles) : - activeTab === "lyric" ? renderLyricTree(filteredFiles) : - renderCoverTree(filteredFiles))} -
-
- - - - - - Reset to Default? - This will reset the rename format to "Title - Artist". Your custom format will be lost. - - - - - - - - - - - - - Rename Preview - Review the changes before renaming. Files with errors will be skipped. - -
- {previewData.map((item, index) => (
-
-
{item.old_name}
- {item.error ?
{item.error}
:
→ {item.new_name}
} -
-
))} -
- - {previewOnly ? () : (<> - - - )} - -
-
- - - - - - File Metadata - {metadataFile.split(/[/\\]/).pop()} - - {loadingMetadata ? (
) : metadataInfo ? (
-
Title{metadataInfo.title || "-"}
-
Artist{metadataInfo.artist || "-"}
-
Album{metadataInfo.album || "-"}
-
Album Artist{metadataInfo.album_artist || "-"}
-
Track{metadataInfo.track_number || "-"}
-
Disc{metadataInfo.disc_number || "-"}
-
Year{metadataInfo.year ? metadataInfo.year.substring(0, 4) : "-"}
-
UPC{metadataInfo.upc || "-"}
-
ISRC{metadataInfo.isrc || "-"}
-
) : (
No metadata available
)} - -
-
- - - - - - - - - Lyrics Preview - {lyricsFile.split(/[/\\]/).pop()} - -
- - -
-
- {lyricsTab === "synced" ? (
- {renderSyncedLyrics(lyricsContent)} -
) : (
-            {getPlainLyrics(lyricsContent) || "No lyrics content"}
-          
)} -
- - - - -
-
- - - - - - Cover Preview - {coverFile.split(/[/\\]/).pop()} - -
- {coverData ? Cover :
Loading...
} -
- -
-
- - - - - - Rename File - {manualRenameFile.split(/[/\\]/).pop()} - -
- -
- setManualRenameName(e.target.value)} placeholder="Enter new name" className="flex-1" onKeyDown={(e) => { - if (e.key === "Enter" && !manualRenaming) - handleConfirmManualRename(); - }}/> - {manualRenameFile.match(/\.[^.]+$/)?.[0] || ""} -
-
- - - - -
-
-
); -} diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx deleted file mode 100644 index 9004e26..0000000 --- a/frontend/src/components/Header.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { Badge } from "@/components/ui/badge"; -import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; -import { openExternal } from "@/lib/utils"; -import { formatRelativeTime } from "@/lib/relative-time"; -interface HeaderProps { - version: string; - hasUpdate: boolean; - releaseDate?: string | null; -} -export function Header({ version, hasUpdate, releaseDate }: HeaderProps) { - return (
-
-
- SpotiFLAC window.location.reload()}/> -

window.location.reload()}> - SpotiFLAC -

-
- - - - - - - {hasUpdate && releaseDate && ( -

{formatRelativeTime(releaseDate)}

-
)} -
- {hasUpdate && ( - - - )} -
-
-

- Get Spotify tracks in true FLAC from Tidal, Qobuz & Amazon Music — no account required. -

-
-
); -} diff --git a/frontend/src/components/HistoryPage.tsx b/frontend/src/components/HistoryPage.tsx deleted file mode 100644 index 499cd4d..0000000 --- a/frontend/src/components/HistoryPage.tsx +++ /dev/null @@ -1,706 +0,0 @@ -import { useEffect, useState, useRef } from "react"; -import { Button } from "@/components/ui/button"; -import { Trash2, ExternalLink, Search, ArrowUpDown, History, Play, Pause, Database, CloudUpload, Music2, Disc3, ListMusic, UserRound } from "lucide-react"; -import { Badge } from "@/components/ui/badge"; -import { Input } from "@/components/ui/input"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; -import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; -import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from "@/components/ui/pagination"; -import { GetDownloadHistory, ClearDownloadHistory, GetPreviewURL, GetFetchHistory, DeleteDownloadHistoryItem, DeleteFetchHistoryItem, ClearFetchHistoryByType } from "../../wailsjs/go/main/App"; -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; -import { openExternal } from "@/lib/utils"; -import { getPreviewVolume } from "@/lib/preview"; -import { createPreviewPlayback, type PreviewPlayback } from "@/lib/preview-player"; -import { TidalIcon, QobuzIcon, AmazonIcon } from "./PlatformIcons"; -const formatDate = (timestamp: number) => { - const date = new Date(timestamp * 1000); - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); - const hours = String(date.getHours()).padStart(2, '0'); - const minutes = String(date.getMinutes()).padStart(2, '0'); - const seconds = String(date.getSeconds()).padStart(2, '0'); - return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; -}; -const getHistoryFormatLabel = (item: DownloadHistoryItem) => { - const normalizedPath = (item.path || "").trim().toLowerCase(); - if (normalizedPath.endsWith(".flac")) - return "FLAC"; - if (normalizedPath.endsWith(".mp3")) - return "MP3"; - if (normalizedPath.endsWith(".m4a")) - return "M4A"; - const normalizedFormat = (item.format || "").trim().toLowerCase(); - switch (normalizedFormat) { - case "hi_res": - case "hi_res_lossless": - case "lossless": - case "flac": - case "6": - case "7": - case "27": - return "FLAC"; - case "alac": - case "apple": - case "atmos": - case "m4a": - case "m4a-aac": - case "m4a-alac": - return "M4A"; - case "mp3": - return "MP3"; - default: - return (item.format || "-").toUpperCase(); - } -}; -interface DownloadHistoryItem { - id: string; - spotify_id: string; - title: string; - artists: string; - album: string; - duration_str: string; - cover_url: string; - quality: string; - format: string; - path: string; - source: string; - timestamp: number; -} -interface FetchHistoryItem { - id: string; - url: string; - type: string; - name: string; - info: string; - image: string; - data: string; - timestamp: number; -} -interface HistoryPageProps { - onHistorySelect?: (cachedData: string) => void; -} -export function HistoryPage({ onHistorySelect }: HistoryPageProps) { - const [activeTab, setActiveTab] = useState("downloads"); - const [downloadHistory, setDownloadHistory] = useState([]); - const [filteredDownloadHistory, setFilteredDownloadHistory] = useState([]); - const [showClearDownloadConfirm, setShowClearDownloadConfirm] = useState(false); - const [downloadSearchQuery, setDownloadSearchQuery] = useState(""); - const [downloadSortBy, setDownloadSortBy] = useState("default"); - const [downloadCurrentPage, setDownloadCurrentPage] = useState(1); - const [playingPreviewId, setPlayingPreviewId] = useState(null); - const playbackRef = useRef(null); - const [fetchHistory, setFetchHistory] = useState([]); - const [filteredFetchHistory, setFilteredFetchHistory] = useState([]); - const [activeFetchTab, setActiveFetchTab] = useState("track"); - const [showClearFetchConfirm, setShowClearFetchConfirm] = useState(false); - const [fetchSearchQuery, setFetchSearchQuery] = useState(""); - const [fetchCurrentPage, setFetchCurrentPage] = useState(1); - const ITEMS_PER_PAGE = 50; - const getTrackLink = (spotifyId: string) => { - if (spotifyId?.startsWith("tidal_")) - return { url: `https://listen.tidal.com/track/${spotifyId.replace("tidal_", "")}`, label: "Open in Tidal" }; - if (spotifyId?.startsWith("qobuz_")) - return { url: `https://www.qobuz.com/track/${spotifyId.replace("qobuz_", "")}`, label: "Open in Qobuz" }; - if (spotifyId?.startsWith("amazon_")) - return { url: `https://music.amazon.com/tracks/${spotifyId.replace("amazon_", "")}`, label: "Open in Amazon Music" }; - if (spotifyId?.startsWith("deezer_")) - return { url: `https://www.deezer.com/track/${spotifyId.replace("deezer_", "")}`, label: "Open in Deezer" }; - return { url: `https://open.spotify.com/track/${spotifyId}`, label: "Open in Spotify" }; - }; - const getSourceIcon = (source: string) => { - const s = source?.toLowerCase() || ""; - if (s.includes("tidal")) - return ; - if (s.includes("qobuz")) - return ; - if (s.includes("amazon")) - return ; - if (s.includes("deezer")) - return ; - if (s.includes("spotify")) - return ; - return ; - }; - const fetchDownloadHistory = async () => { - try { - const items = await GetDownloadHistory(); - setDownloadHistory((items || []) as unknown as DownloadHistoryItem[]); - } - catch (err) { - console.error("Failed to fetch download history:", err); - } - }; - const fetchFetchHistory = async () => { - try { - const items = await GetFetchHistory(); - setFetchHistory(items || []); - } - catch (err) { - console.error("Failed to fetch fetch history:", err); - } - }; - useEffect(() => { - if (activeTab === "downloads") { - fetchDownloadHistory(); - const interval = setInterval(fetchDownloadHistory, 5000); - return () => clearInterval(interval); - } - else { - fetchFetchHistory(); - const interval = setInterval(fetchFetchHistory, 5000); - return () => clearInterval(interval); - } - }, [activeTab]); - useEffect(() => { - return () => { - playbackRef.current?.destroy(); - playbackRef.current = null; - }; - }, []); - useEffect(() => { - let result = [...downloadHistory]; - if (downloadSearchQuery) { - const query = downloadSearchQuery.toLowerCase(); - result = result.filter(item => item.title.toLowerCase().includes(query) || - item.artists.toLowerCase().includes(query) || - item.album.toLowerCase().includes(query)); - } - const parseDuration = (str: string) => { - const parts = str.split(':').map(Number); - if (parts.length === 2) - return parts[0] * 60 + parts[1]; - if (parts.length === 3) - return parts[0] * 3600 + parts[1] * 60 + parts[2]; - return 0; - }; - result.sort((a, b) => { - switch (downloadSortBy) { - case "default": - case "date_desc": return b.timestamp - a.timestamp; - case "date_asc": return a.timestamp - b.timestamp; - case "title_asc": return a.title.localeCompare(b.title); - case "title_desc": return b.title.localeCompare(a.title); - case "artist_asc": return a.artists.localeCompare(b.artists); - case "artist_desc": return b.artists.localeCompare(a.artists); - case "duration_asc": return parseDuration(a.duration_str) - parseDuration(b.duration_str); - case "duration_desc": return parseDuration(b.duration_str) - parseDuration(a.duration_str); - default: return 0; - } - }); - setFilteredDownloadHistory(result); - }, [downloadHistory, downloadSearchQuery, downloadSortBy]); - useEffect(() => { - setDownloadCurrentPage(1); - }, [downloadSearchQuery, downloadSortBy]); - useEffect(() => { - let result = [...fetchHistory]; - if (activeFetchTab !== "all") { - result = result.filter(item => item.type.toLowerCase() === activeFetchTab.toLowerCase()); - } - if (fetchSearchQuery) { - const query = fetchSearchQuery.toLowerCase(); - result = result.filter(item => item.name.toLowerCase().includes(query) || - item.info.toLowerCase().includes(query)); - } - result.sort((a, b) => b.timestamp - a.timestamp); - setFilteredFetchHistory(result); - }, [fetchHistory, fetchSearchQuery, activeFetchTab]); - useEffect(() => { - setFetchCurrentPage(1); - }, [fetchSearchQuery, activeFetchTab]); - const handlePreview = async (id: string, spotifyId: string) => { - if (playingPreviewId === id) { - playbackRef.current?.destroy(); - playbackRef.current = null; - setPlayingPreviewId(null); - return; - } - if (playbackRef.current) { - playbackRef.current.destroy(); - playbackRef.current = null; - } - try { - const url = await GetPreviewURL(spotifyId); - if (url) { - const playback = await createPreviewPlayback(url, getPreviewVolume()); - const audio = playback.audio; - playbackRef.current = playback; - audio.onended = () => { - setPlayingPreviewId(null); - if (playbackRef.current?.audio === audio) { - playbackRef.current.destroy(); - playbackRef.current = null; - } - }; - audio.onerror = () => { - setPlayingPreviewId(null); - if (playbackRef.current?.audio === audio) { - playbackRef.current.destroy(); - playbackRef.current = null; - } - }; - audio.play(); - setPlayingPreviewId(id); - } - } - catch (e) { - console.error("Failed to play preview:", e); - } - }; - const handleClearDownloadHistory = async () => { - await ClearDownloadHistory(); - fetchDownloadHistory(); - setShowClearDownloadConfirm(false); - }; - const handleDeleteDownloadItem = async (id: string) => { - await DeleteDownloadHistoryItem(id); - setDownloadHistory(prev => prev.filter(item => item.id !== id)); - }; - const handleClearFetchHistory = async () => { - await ClearFetchHistoryByType(activeFetchTab); - fetchFetchHistory(); - setShowClearFetchConfirm(false); - }; - const handleDeleteFetchItem = async (id: string, e: React.MouseEvent) => { - e.stopPropagation(); - await DeleteFetchHistoryItem(id); - setFetchHistory(prev => prev.filter(item => item.id !== id)); - }; - const getPaginationPages = (current: number, total: number): (number | 'ellipsis')[] => { - if (total <= 10) - return Array.from({ length: total }, (_, i) => i + 1); - const pages: (number | 'ellipsis')[] = []; - pages.push(1); - if (current <= 7) { - for (let i = 2; i <= 10; i++) - pages.push(i); - pages.push('ellipsis'); - pages.push(total); - } - else if (current >= total - 7) { - pages.push('ellipsis'); - for (let i = total - 9; i <= total; i++) - pages.push(i); - } - else { - pages.push('ellipsis'); - pages.push(current - 1); - pages.push(current); - pages.push(current + 1); - pages.push('ellipsis'); - pages.push(total); - } - return pages; - }; - const renderDownloadHistory = () => { - const totalPages = Math.ceil(filteredDownloadHistory.length / ITEMS_PER_PAGE); - const startIndex = (downloadCurrentPage - 1) * ITEMS_PER_PAGE; - const paginated = filteredDownloadHistory.slice(startIndex, startIndex + ITEMS_PER_PAGE); - return (
-
-
-
-

Downloads

- {filteredDownloadHistory.length > 0 && ( - {filteredDownloadHistory.length.toLocaleString('en-US')} - )} -
- -
- -
-
- - setDownloadSearchQuery(e.target.value)} className="pl-8 h-9"/> -
- -
-
- -
- {paginated.length === 0 ? (
-
- -
-
-

No download history

-

Your downloaded tracks will appear here.

-
-
) : ( - - - - - - - - - - - - - - {paginated.map((item, index) => ( - - - - - - - - - ))} - -
#TitleAlbumFormatDurDownloaded AtSourceActions
- {startIndex + index + 1} - -
- {item.album} { (e.target as HTMLImageElement).src = "https://placehold.co/300?text=No+Cover"; }}/> -
- {item.title} - {item.artists} -
-
-
-
{item.album}
-
-
- - {getHistoryFormatLabel(item)} - - {item.quality && {item.quality}} -
-
- {item.duration_str} - -
- {formatDate(item.timestamp).split(' ')[0]} - {formatDate(item.timestamp).split(' ')[1]} -
-
-
- - - -
- {getSourceIcon(item.source)} -
-
- -

{item.source || "Unknown"}

-
-
-
-
-
-
- {!(item.spotify_id?.startsWith('tidal_') || item.spotify_id?.startsWith('qobuz_') || item.spotify_id?.startsWith('amazon_') || item.spotify_id?.startsWith('deezer_')) && ( - - - - - -

{playingPreviewId === item.id ? "Pause Preview" : "Play Preview"}

-
-
-
)} - - - - - - - -

{getTrackLink(item.spotify_id).label}

-
-
-
- - - - - - - -

Delete

-
-
-
-
-
)} -
- - {totalPages > 1 && ( - - - { - e.preventDefault(); - if (downloadCurrentPage > 1) - setDownloadCurrentPage(downloadCurrentPage - 1); - }} className={downloadCurrentPage === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}/> - - - {getPaginationPages(downloadCurrentPage, totalPages).map((page, index) => (page === 'ellipsis' ? ( - - ) : ( - { - e.preventDefault(); - setDownloadCurrentPage(page as number); - }} isActive={downloadCurrentPage === page} className="cursor-pointer"> - {page} - - )))} - - - { - e.preventDefault(); - if (downloadCurrentPage < totalPages) - setDownloadCurrentPage(downloadCurrentPage + 1); - }} className={downloadCurrentPage === totalPages ? "pointer-events-none opacity-50" : "cursor-pointer"}/> - - - )} -
); - }; - const renderFetchHistory = () => { - const totalPages = Math.ceil(filteredFetchHistory.length / ITEMS_PER_PAGE); - const startIndex = (fetchCurrentPage - 1) * ITEMS_PER_PAGE; - const paginated = filteredFetchHistory.slice(startIndex, startIndex + ITEMS_PER_PAGE); - return (
-
-
-
-

Fetches

- {fetchHistory.length > 0 && ( - {fetchHistory.length.toLocaleString('en-US')} - )} -
- -
- - -
-
- - - - -
- -
-
- - setFetchSearchQuery(e.target.value)} className="pl-8 h-9"/> -
-
-
-
- -
- {paginated.length === 0 ? (
- -
-

No fetch history

-

Fetched metadata will appear here.

-
-
) : ( - - - - - - - - - - - {paginated.map((item, index) => ( - - - - - - ))} - -
# - {activeFetchTab === 'artist' ? 'Name' : 'Title'} - DetailsFetched AtActions
- {startIndex + index + 1} - -
-
- {item.image ? ({item.name}) : (
- {item.type.slice(0, 2).toUpperCase()} -
)} -
- {item.name} -
-
-
{item.info}
-
-
- {formatDate(item.timestamp).split(' ')[0]} - {formatDate(item.timestamp).split(' ')[1]} -
-
-
- - - - - - -

Load

-
-
-
- - - - - - - -

Delete

-
-
-
-
-
)} -
- - {totalPages > 1 && ( - - - { - e.preventDefault(); - if (fetchCurrentPage > 1) - setFetchCurrentPage(fetchCurrentPage - 1); - }} className={fetchCurrentPage === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}/> - - - {getPaginationPages(fetchCurrentPage, totalPages).map((page, index) => (page === 'ellipsis' ? ( - - ) : ( - { - e.preventDefault(); - setFetchCurrentPage(page as number); - }} isActive={fetchCurrentPage === page} className="cursor-pointer"> - {page} - - )))} - - - { - e.preventDefault(); - if (fetchCurrentPage < totalPages) - setFetchCurrentPage(fetchCurrentPage + 1); - }} className={fetchCurrentPage === totalPages ? "pointer-events-none opacity-50" : "cursor-pointer"}/> - - - )} -
); - }; - return (
-
-

History

-
- -
-
- - -
-
- - {activeTab === "downloads" && (
- {renderDownloadHistory()} -
)} - - {activeTab === "fetches" && (
- {renderFetchHistory()} -
)} - - - - - Clear Download History? - - This will remove all entries from your download history. This action cannot be undone. - Note: The actual downloaded files will NOT be deleted. - - - - - - - - - - - - - Clear {activeFetchTab.charAt(0).toUpperCase() + activeFetchTab.slice(1)} History? - - This will remove all {activeFetchTab} entries from your fetch history cache. - - - - - - - - -
); -} diff --git a/frontend/src/components/OtherProjects.tsx b/frontend/src/components/OtherProjects.tsx deleted file mode 100644 index ba75fb0..0000000 --- a/frontend/src/components/OtherProjects.tsx +++ /dev/null @@ -1,322 +0,0 @@ -import { useEffect, useState } from "react"; -import { openExternal } from "@/lib/utils"; -import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; -import { Star, GitFork, Clock, Download, Info } from "lucide-react"; -import AudioTTSProIcon from "@/assets/audiotts-pro.webp"; -import ChatGPTTTSIcon from "@/assets/chatgpt-tts.webp"; -import XIcon from "@/assets/x.webp"; -import SpotubeDLIcon from "@/assets/icons/spotubedl.svg"; -import XBatchDLIcon from "@/assets/icons/xbatchdl.svg"; -import SpotiFLACNextIcon from "@/assets/icons/next.svg"; -import { langColors } from "@/assets/github-lang-colors"; -const browserExtensionItems = [ - { icon: AudioTTSProIcon, label: "AudioTTS Pro", alt: "AudioTTS Pro" }, - { icon: ChatGPTTTSIcon, label: "ChatGPT TTS", alt: "ChatGPT TTS" }, - { icon: XIcon, label: "Twitter/X Media Batch Downloader", alt: "Twitter/X Media Batch Downloader" }, -]; -const projectCardClass = "cursor-pointer gap-3 py-5 transition-colors hover:bg-muted/50 dark:hover:bg-accent/50"; -const projectCardHeaderClass = "px-5 gap-1.5"; -const projectCardContentClass = "px-5"; -const projectBodyClass = "text-[13px] leading-snug"; -const releaseMetaClass = "text-xs text-muted-foreground whitespace-nowrap"; -const releaseVersionClass = "text-xs bg-primary text-primary-foreground px-1.5 py-0.5 rounded-sm font-mono font-semibold whitespace-nowrap"; -export function OtherProjects() { - const [repoStats, setRepoStats] = useState>({}); - useEffect(() => { - const fetchRepoStats = async () => { - const CACHE_KEY = "github_repo_stats_v4"; - const CACHE_DURATION = 1000 * 60 * 60; - const cached = localStorage.getItem(CACHE_KEY); - if (cached) { - try { - const { data, timestamp } = JSON.parse(cached); - if (Date.now() - timestamp < CACHE_DURATION) { - setRepoStats(data); - return; - } - } - catch (err) { - console.error("Failed to parse cache:", err); - } - } - const repos = [ - { name: "SpotiFLAC-Next", owner: "spotbye" }, - { name: "Twitter-X-Media-Batch-Downloader", owner: "afkarxyz" }, - ]; - const stats: Record = {}; - for (const repo of repos) { - try { - const [repoRes, releasesRes, langsRes] = await Promise.all([ - fetch(`https://api.github.com/repos/${repo.owner}/${repo.name}`), - fetch(`https://api.github.com/repos/${repo.owner}/${repo.name}/releases`), - fetch(`https://api.github.com/repos/${repo.owner}/${repo.name}/languages`), - ]); - if (repoRes.status === 403) { - if (cached) { - const { data } = JSON.parse(cached); - setRepoStats(data); - } - return; - } - if (repoRes.ok) { - const repoData = await repoRes.json(); - const releases = releasesRes.ok ? await releasesRes.json() : []; - const languages = langsRes.ok ? await langsRes.json() : {}; - let totalDownloads = 0; - let latestDownloads = 0; - let latestVersion = ""; - let latestReleaseAt = ""; - if (releases.length > 0) { - latestVersion = releases[0].tag_name || ""; - latestReleaseAt = releases[0].published_at || releases[0].created_at || ""; - latestDownloads = - releases[0].assets?.reduce((sum: number, asset: any) => sum + (asset.download_count || 0), 0) || 0; - totalDownloads = releases.reduce((sum: number, release: any) => { - return (sum + - (release.assets?.reduce((s: number, a: any) => s + (a.download_count || 0), 0) || 0)); - }, 0); - } - const topLangs = Object.entries(languages) - .sort(([, a]: any, [, b]: any) => b - a) - .slice(0, 4) - .map(([lang]) => lang); - stats[repo.name] = { - stars: repoData.stargazers_count, - forks: repoData.forks_count, - createdAt: repoData.created_at, - description: repoData.description, - totalDownloads, - latestDownloads, - latestVersion, - latestReleaseAt, - languages: topLangs, - }; - } - } - catch (err) { - console.error(`Failed to fetch stats for ${repo.name}:`, err); - if (cached) { - const { data } = JSON.parse(cached); - setRepoStats(data); - return; - } - } - } - setRepoStats(stats); - localStorage.setItem(CACHE_KEY, JSON.stringify({ data: stats, timestamp: Date.now() })); - }; - fetchRepoStats(); - }, []); - const formatTimeAgo = (dateString: string): string => { - const now = new Date(); - const updated = new Date(dateString); - const diffMs = now.getTime() - updated.getTime(); - const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); - const diffMonths = Math.floor(diffDays / 30); - if (diffDays === 0) - return "today"; - if (diffDays === 1) - return "1d"; - if (diffDays < 30) - return `${diffDays}d`; - if (diffMonths === 1) - return "1mo"; - if (diffMonths < 12) - return `${diffMonths}mo`; - const diffYears = Math.floor(diffMonths / 12); - return `${diffYears}y`; - }; - const formatReleaseTimeAgo = (dateString: string): string => { - if (!dateString) { - return ""; - } - const now = Date.now(); - const releasedAt = new Date(dateString).getTime(); - if (Number.isNaN(releasedAt)) { - return ""; - } - const diffMs = Math.max(0, now - releasedAt); - const totalMinutes = Math.floor(diffMs / (1000 * 60)); - const totalHours = Math.floor(totalMinutes / 60); - const totalDays = Math.floor(totalHours / 24); - const totalMonths = Math.floor(totalDays / 30); - const totalYears = Math.floor(totalMonths / 12); - if (totalYears > 0) { - const remainingMonths = totalMonths % 12; - return remainingMonths > 0 ? `${totalYears}y ${remainingMonths}m ago` : `${totalYears}y ago`; - } - if (totalMonths > 0) { - const remainingDays = totalDays % 30; - return remainingDays > 0 ? `${totalMonths}m ${remainingDays}d ago` : `${totalMonths}m ago`; - } - if (totalDays > 0) { - const remainingHours = totalHours % 24; - return remainingHours > 0 ? `${totalDays}d ${remainingHours}h ago` : `${totalDays}d ago`; - } - if (totalHours > 0) { - const remainingMinutes = totalMinutes % 60; - return `${totalHours}h ${remainingMinutes}m ago`; - } - return `${totalMinutes}m ago`; - }; - const formatNumber = (num: number): string => { - if (num >= 1000) { - return num.toLocaleString(); - } - return num.toString(); - }; - const getLangColor = (lang: string): string => { - return langColors[lang] || "#858585"; - }; - const getRepoDescription = (repoName: string): string => { - return repoStats[repoName]?.description || ""; - }; - return (
-
-

Other Projects

-
- -
-
- openExternal("https://github.com/spotbye/SpotiFLAC-Next")}> - -
- SpotiFLAC Next -
- {repoStats["SpotiFLAC-Next"]?.latestReleaseAt && ( - {formatReleaseTimeAgo(repoStats["SpotiFLAC-Next"].latestReleaseAt)} - )} - {repoStats["SpotiFLAC-Next"]?.latestVersion && ( - {repoStats["SpotiFLAC-Next"].latestVersion} - )} -
-
- - SpotiFLAC Next - - - {getRepoDescription("SpotiFLAC-Next")} - -
- {repoStats["SpotiFLAC-Next"] && ( - {repoStats["SpotiFLAC-Next"].languages?.length > 0 && (
- {repoStats["SpotiFLAC-Next"].languages.map((lang: string) => ( - {lang} - ))} -
)} -
- - {" "} - {formatNumber(repoStats["SpotiFLAC-Next"].stars)} - - - {" "} - {repoStats["SpotiFLAC-Next"].forks} - - - {" "} - {formatTimeAgo(repoStats["SpotiFLAC-Next"].createdAt)} - -
-
-
- - Note -
-

- This project released as a token of appreciation for those who have supported SpotiFLAC through Ko-fi, Patreon, or crypto. It’s not a paid product, but it’s shared privately through a supporter-only post. -

-
-
)} -
- openExternal("https://github.com/afkarxyz/Twitter-X-Media-Batch-Downloader")}> - -
- Twitter/X Media Batch Downloader -
- {repoStats["Twitter-X-Media-Batch-Downloader"]?.latestReleaseAt && ( - {formatReleaseTimeAgo(repoStats["Twitter-X-Media-Batch-Downloader"].latestReleaseAt)} - )} - {repoStats["Twitter-X-Media-Batch-Downloader"]?.latestVersion && ( - {repoStats["Twitter-X-Media-Batch-Downloader"].latestVersion} - )} -
-
- - Twitter/X Media Batch Downloader - - - {getRepoDescription("Twitter-X-Media-Batch-Downloader")} - -
- {repoStats["Twitter-X-Media-Batch-Downloader"] && ( -
- {repoStats["Twitter-X-Media-Batch-Downloader"].languages?.map((lang: string) => ( - {lang} - ))} -
-
- - {" "} - {formatNumber(repoStats["Twitter-X-Media-Batch-Downloader"].stars)} - - - {" "} - {repoStats["Twitter-X-Media-Batch-Downloader"].forks} - - - {" "} - {formatTimeAgo(repoStats["Twitter-X-Media-Batch-Downloader"] - .createdAt)} - -
-
- - TOTAL:{" "} - {formatNumber(repoStats["Twitter-X-Media-Batch-Downloader"] - .totalDownloads)} - - - LATEST:{" "} - {formatNumber(repoStats["Twitter-X-Media-Batch-Downloader"] - .latestDownloads)} - -
-
)} -
-
- openExternal("https://exyezed.fyi/")}> - - Browser Extensions & Scripts - - {browserExtensionItems.map((item) => (
- {item.alt}/ - - {item.label} - -
))} -
-
-
- openExternal("https://spotubedl.com/")}> - - - SpotubeDL{" "} - SpotubeDL.com - - - Download Spotify Tracks, Albums, Playlists & Discography as MP3/OGG/Opus. - - - -
-
-
-
); -} diff --git a/frontend/src/components/PlatformIcons.tsx b/frontend/src/components/PlatformIcons.tsx deleted file mode 100644 index 388e1c6..0000000 --- a/frontend/src/components/PlatformIcons.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import amazonMusicIcon from "../assets/icons/amzn.png"; -import appleMusicIcon from "../assets/icons/am.png"; -import deezerIcon from "../assets/icons/dzr.png"; -import lrclibIcon from "../assets/icons/lrclib.png"; -import musicBrainzDarkIcon from "../assets/icons/musicbrainz_d.png"; -import musicBrainzLightIcon from "../assets/icons/musicbrainz_l.png"; -import qobuzIcon from "../assets/icons/qbz.png"; -import songlinkDarkIcon from "../assets/icons/songlink_d.png"; -import songlinkLightIcon from "../assets/icons/songlink_l.png"; -import songstatsIcon from "../assets/icons/songstats.png"; -import tidalDarkIcon from "../assets/icons/tidal_d.png"; -import tidalLightIcon from "../assets/icons/tidal_l.png"; -type PlatformIconProps = { - className?: string; -}; -function sanitizeClassName(className: string): string { - return className - .split(/\s+/) - .filter(Boolean) - .filter((part) => part !== "fill-current" && part !== "fill-muted-foreground" && !part.startsWith("text-")) - .join(" "); -} -function hasRoundedClass(className: string): boolean { - return className - .split(/\s+/) - .some((part) => part.startsWith("rounded")); -} -function getStatusClasses(className: string): string { - if (className.includes("text-green-500")) { - return "ring-2 ring-green-500 rounded-sm"; - } - if (className.includes("text-red-500")) { - return "ring-2 ring-red-500 rounded-sm opacity-70"; - } - return ""; -} -function PlatformIcon({ src, alt, className = "w-4 h-4", defaultClassName = "" }: { - src: string; - alt: string; - className?: string; - defaultClassName?: string; -}) { - const cleanedClassName = sanitizeClassName(className); - const statusClasses = getStatusClasses(className); - const imageClassName = [ - cleanedClassName || "w-4 h-4", - "inline-block shrink-0 object-contain", - !hasRoundedClass(cleanedClassName) ? defaultClassName : "", - statusClasses, - ] - .filter(Boolean) - .join(" "); - return {alt}; -} -function ThemedPlatformIcon({ lightSrc, darkSrc, alt, className = "w-4 h-4", defaultClassName = "" }: { - lightSrc: string; - darkSrc: string; - alt: string; - className?: string; - defaultClassName?: string; -}) { - const cleanedClassName = sanitizeClassName(className); - const statusClasses = getStatusClasses(className); - const wrapperClassName = [ - cleanedClassName || "w-4 h-4", - "relative inline-flex shrink-0", - !hasRoundedClass(cleanedClassName) ? defaultClassName : "", - statusClasses, - ] - .filter(Boolean) - .join(" "); - return - - - ; -} -export function TidalIcon({ className = "w-4 h-4" }: PlatformIconProps) { - return ; -} -export function QobuzIcon({ className = "w-4 h-4" }: PlatformIconProps) { - return ; -} -export function AmazonIcon({ className = "w-4 h-4" }: PlatformIconProps) { - return ; -} -export function AppleMusicIcon({ className = "w-4 h-4" }: PlatformIconProps) { - return ; -} -export function DeezerIcon({ className = "w-4 h-4" }: PlatformIconProps) { - return ; -} -export function LrclibIcon({ className = "w-4 h-4" }: PlatformIconProps) { - return ; -} -export function MusicBrainzIcon({ className = "w-4 h-4" }: PlatformIconProps) { - return ; -} -export function SonglinkIcon({ className = "w-4 h-4" }: PlatformIconProps) { - return ; -} -export function SongstatsIcon({ className = "w-4 h-4" }: PlatformIconProps) { - return ; -} -export function TidalAvailabilityIcon({ className = "w-4 h-4" }: PlatformIconProps) { - return - - - ; -} -export function QobuzAvailabilityIcon({ className = "w-4 h-4" }: PlatformIconProps) { - return - - - ; -} -export function AmazonAvailabilityIcon({ className = "w-4 h-4" }: PlatformIconProps) { - return - - - ; -} diff --git a/frontend/src/components/PlaylistInfo.tsx b/frontend/src/components/PlaylistInfo.tsx deleted file mode 100644 index dc7cd29..0000000 --- a/frontend/src/components/PlaylistInfo.tsx +++ /dev/null @@ -1,249 +0,0 @@ -import { Button } from "@/components/ui/button"; -import { Card, CardContent } from "@/components/ui/card"; -import { Download, FolderOpen, ImageDown, FileText, XCircle } from "lucide-react"; -import { Spinner } from "@/components/ui/spinner"; -import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; -import { SearchAndSort } from "./SearchAndSort"; -import { TrackList } from "./TrackList"; -import { DownloadProgress } from "./DownloadProgress"; -import { getSettings } from "@/lib/settings"; -import { downloadCover } from "@/lib/api"; -import { useState } from "react"; -import { toastWithSound as toast } from "@/lib/toast-with-sound"; -import { joinPath, sanitizePath } from "@/lib/utils"; -import { parseTemplate, type TemplateData } from "@/lib/settings"; -import { buildPlaylistFolderName } from "@/lib/playlist"; -import type { TrackMetadata, TrackAvailability } from "@/types/api"; -interface PlaylistInfoProps { - playlistInfo: { - owner: { - name: string; - display_name: string; - images: string; - }; - tracks: { - total: number; - }; - followers: { - total: number; - }; - cover?: string; - description?: string; - }; - trackList: TrackMetadata[]; - searchQuery: string; - sortBy: string; - selectedTracks: string[]; - downloadedTracks: Set; - failedTracks: Set; - skippedTracks: Set; - downloadingTrack: string | null; - isDownloading: boolean; - bulkDownloadType: "all" | "selected" | null; - downloadProgress: number; - downloadRemainingCount: number; - currentDownloadInfo: { - name: string; - artists: string; - } | null; - currentPage: number; - itemsPerPage: number; - downloadedLyrics?: Set; - failedLyrics?: Set; - skippedLyrics?: Set; - downloadingLyricsTrack?: string | null; - checkingAvailabilityTrack?: string | null; - availabilityMap?: Map; - downloadedCovers?: Set; - failedCovers?: Set; - skippedCovers?: Set; - downloadingCoverTrack?: string | null; - isBulkDownloadingCovers?: boolean; - isBulkDownloadingLyrics?: boolean; - isMetadataLoading?: boolean; - onSearchChange: (value: string) => void; - onSortChange: (value: string) => void; - onToggleTrack: (id: string) => void; - onToggleSelectAll: (tracks: TrackMetadata[]) => void; - onDownloadTrack: (id: string, name: string, artists: string, albumName: string, spotifyId?: string, folderName?: string, durationMs?: number, position?: number, albumArtist?: string, releaseDate?: string, coverUrl?: string, spotifyTrackNumber?: number, spotifyDiscNumber?: number, spotifyTotalTracks?: number, spotifyTotalDiscs?: number, copyright?: string, publisher?: string) => void; - onDownloadLyrics?: (spotifyId: string, name: string, artists: string, albumName: string, folderName?: string, isArtistDiscography?: boolean, position?: number, albumArtist?: string, releaseDate?: string, discNumber?: number) => void; - onDownloadCover?: (coverUrl: string, trackName: string, artistName: string, albumName: string, folderName?: string, isArtistDiscography?: boolean, position?: number, trackId?: string, albumArtist?: string, releaseDate?: string, discNumber?: number) => void; - onCheckAvailability?: (spotifyId: string) => void; - onDownloadAllLyrics?: () => void; - onDownloadAllCovers?: () => void; - onDownloadAll: () => void; - onDownloadSelected: () => void; - onStopDownload: () => void; - onOpenFolder: () => void; - onPageChange: (page: number) => void; - onAlbumClick: (album: { - id: string; - name: string; - external_urls: string; - }) => void; - onArtistClick: (artist: { - id: string; - name: string; - external_urls: string; - }) => void; - onTrackClick: (track: TrackMetadata) => void; - onBack?: () => void; -} -export function PlaylistInfo({ playlistInfo, trackList, searchQuery, sortBy, selectedTracks, downloadedTracks, failedTracks, skippedTracks, downloadingTrack, isDownloading, bulkDownloadType, downloadProgress, downloadRemainingCount, currentDownloadInfo, currentPage, itemsPerPage, downloadedLyrics, failedLyrics, skippedLyrics, downloadingLyricsTrack, checkingAvailabilityTrack, availabilityMap, downloadedCovers, failedCovers, skippedCovers, downloadingCoverTrack, isBulkDownloadingCovers, isBulkDownloadingLyrics, isMetadataLoading = false, onSearchChange, onSortChange, onToggleTrack, onToggleSelectAll, onDownloadTrack, onDownloadLyrics, onDownloadCover, onCheckAvailability, onDownloadAllLyrics, onDownloadAllCovers, onDownloadAll, onDownloadSelected, onStopDownload, onOpenFolder, onPageChange, onAlbumClick, onArtistClick, onTrackClick, onBack, }: PlaylistInfoProps) { - const settings = getSettings(); - const playlistName = playlistInfo.owner.name; - const playlistFolderName = buildPlaylistFolderName(playlistName, playlistInfo.owner.display_name, settings.playlistOwnerFolderName); - const [downloadingPlaylistCover, setDownloadingPlaylistCover] = useState(false); - const fetchedTrackCount = trackList.length; - const totalTrackCount = playlistInfo.tracks.total; - const showStreamingProgress = isMetadataLoading && totalTrackCount > 0 && fetchedTrackCount < totalTrackCount; - const handleDownloadPlaylistCover = async () => { - if (!playlistInfo.cover) - return; - setDownloadingPlaylistCover(true); - try { - const os = settings.operatingSystem; - let outputDir = settings.downloadPath; - const placeholder = "__SLASH_PLACEHOLDER__"; - const templateData: TemplateData = { - artist: "", - album: "", - album_artist: "", - title: playlistName.replace(/\//g, placeholder), - playlist: playlistFolderName.replace(/\//g, placeholder), - }; - if (settings.createPlaylistFolder && playlistFolderName) { - outputDir = joinPath(os, outputDir, sanitizePath(playlistFolderName.replace(/\//g, " "), os)); - } - if (settings.folderTemplate) { - const folderPath = parseTemplate(settings.folderTemplate, templateData); - if (folderPath) { - const parts = folderPath.split("/").filter((p: string) => p.trim()); - for (const part of parts) { - outputDir = joinPath(os, outputDir, sanitizePath(part.replace(new RegExp(placeholder, "g"), " "), os)); - } - } - } - const response = await downloadCover({ - cover_url: playlistInfo.cover, - track_name: playlistName, - artist_name: "", - album_name: "", - album_artist: "", - release_date: "", - output_dir: outputDir, - filename_format: "title", - track_number: false, - position: 0, - disc_number: 0, - }); - if (response.success) { - if (response.already_exists) - toast.info("Cover already exists"); - else - toast.success("Separate playlist cover downloaded"); - } - else { - toast.error(response.error || "Failed to download cover"); - } - } - catch (err) { - toast.error(err instanceof Error ? err.message : "Failed to download cover"); - } - finally { - setDownloadingPlaylistCover(false); - } - }; - return (
- - {onBack && (
- -
)} - -
- {playlistInfo.cover && (
- {playlistName} -
- - - - -

Download Separate Playlist Cover

-
-
-
)} -
-
-

Playlist

-

{playlistName}

- {playlistInfo.description && (

{playlistInfo.description}

)} -
-
- {playlistInfo.owner.images && ({playlistInfo.owner.display_name})} - {playlistInfo.owner.display_name} -
- - - {showStreamingProgress - ? `${fetchedTrackCount.toLocaleString()} / ${totalTrackCount.toLocaleString()} tracks` - : `${Math.max(totalTrackCount, fetchedTrackCount).toLocaleString()} ${Math.max(totalTrackCount, fetchedTrackCount) === 1 ? "track" : "tracks"}`} - - - {playlistInfo.followers.total.toLocaleString()} {playlistInfo.followers.total === 1 ? "follower" : "followers"} -
-
-
- - {selectedTracks.length > 0 && ()} - {onDownloadAllLyrics && ( - - - - -

Download All Lyrics

-
-
)} - {onDownloadAllCovers && ( - - - - -

Download All Separate Covers

-
-
)} - {downloadedTracks.size > 0 && ( - - - - -

Open Folder

-
-
)} -
- {isDownloading && ()} -
-
-
-
-
- - -
-
); -} diff --git a/frontend/src/components/SearchAndSort.tsx b/frontend/src/components/SearchAndSort.tsx deleted file mode 100644 index 29a0559..0000000 --- a/frontend/src/components/SearchAndSort.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Input } from "@/components/ui/input"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; -import { Search, ArrowUpDown, XCircle } from "lucide-react"; -interface SearchAndSortProps { - searchQuery: string; - sortBy: string; - onSearchChange: (value: string) => void; - onSortChange: (value: string) => void; -} -export function SearchAndSort({ searchQuery, sortBy, onSearchChange, onSortChange, }: SearchAndSortProps) { - return (
-
- - onSearchChange(e.target.value)} className="pl-10 pr-8"/> - {searchQuery && ()} -
- -
); -} diff --git a/frontend/src/components/SearchBar.tsx b/frontend/src/components/SearchBar.tsx deleted file mode 100644 index 8ee2e50..0000000 --- a/frontend/src/components/SearchBar.tsx +++ /dev/null @@ -1,817 +0,0 @@ -import { useState, useEffect, useRef, useMemo } from "react"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { InputWithContext } from "@/components/ui/input-with-context"; -import { CloudDownload, XCircle, Link, Search, X, ChevronDown, ArrowUpDown, } from "lucide-react"; -import { Spinner } from "@/components/ui/spinner"; -import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; -import { FetchHistory } from "@/components/FetchHistory"; -import type { HistoryItem } from "@/components/FetchHistory"; -import { SearchSpotify, SearchSpotifyByType } from "../../wailsjs/go/main/App"; -import { backend } from "../../wailsjs/go/models"; -import { cn } from "@/lib/utils"; -import { useTypingEffect } from "@/hooks/useTypingEffect"; -import { getSettings, type Settings } from "@/lib/settings"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; -import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; -const FETCH_PLACEHOLDERS = [ - "https://open.spotify.com/track/...", - "https://open.spotify.com/album/...", - "https://open.spotify.com/playlist/...", - "https://open.spotify.com/artist/...", -]; -const SEARCH_PLACEHOLDERS = [ - "Golden", - "Taylor Swift", - "The Weeknd", - "Starboy", - "Joji", - "Die For You", -]; -const REGIONS = [ - "AD", - "AE", - "AG", - "AL", - "AM", - "AO", - "AR", - "AT", - "AU", - "AZ", - "BA", - "BB", - "BD", - "BE", - "BF", - "BG", - "BH", - "BI", - "BJ", - "BN", - "BO", - "BR", - "BS", - "BT", - "BW", - "BZ", - "CA", - "CD", - "CG", - "CH", - "CI", - "CL", - "CM", - "CO", - "CR", - "CV", - "CW", - "CY", - "CZ", - "DE", - "DJ", - "DK", - "DM", - "DO", - "DZ", - "EC", - "EE", - "EG", - "ES", - "ET", - "FI", - "FJ", - "FM", - "FR", - "GA", - "GB", - "GD", - "GE", - "GH", - "GM", - "GN", - "GQ", - "GR", - "GT", - "GW", - "GY", - "HK", - "HN", - "HR", - "HT", - "HU", - "ID", - "IE", - "IL", - "IN", - "IQ", - "IS", - "IT", - "JM", - "JO", - "JP", - "KE", - "KG", - "KH", - "KI", - "KM", - "KN", - "KR", - "KW", - "KZ", - "LA", - "LB", - "LC", - "LI", - "LK", - "LR", - "LS", - "LT", - "LU", - "LV", - "LY", - "MA", - "MC", - "MD", - "ME", - "MG", - "MH", - "MK", - "ML", - "MN", - "MO", - "MR", - "MT", - "MU", - "MV", - "MW", - "MX", - "MY", - "MZ", - "NA", - "NE", - "NG", - "NI", - "NL", - "NO", - "NP", - "NR", - "NZ", - "OM", - "PA", - "PE", - "PG", - "PH", - "PK", - "PL", - "PS", - "PT", - "PW", - "PY", - "QA", - "RO", - "RS", - "RW", - "SA", - "SB", - "SC", - "SE", - "SG", - "SI", - "SK", - "SL", - "SM", - "SN", - "SR", - "ST", - "SV", - "SZ", - "TD", - "TG", - "TH", - "TJ", - "TL", - "TN", - "TO", - "TR", - "TT", - "TV", - "TW", - "TZ", - "UA", - "UG", - "US", - "UY", - "UZ", - "VC", - "VE", - "VN", - "VU", - "WS", - "XK", - "ZA", - "ZM", - "ZW", -]; -const regionNames = new Intl.DisplayNames(["en"], { type: "region" }); -const getRegionName = (code: string) => { - try { - if (code === "XK") - return "Kosovo"; - return regionNames.of(code) || code; - } - catch (e) { - return code; - } -}; -type ResultTab = "tracks" | "albums" | "artists" | "playlists"; -const RECENT_SEARCHES_KEY = "spotiflac_recent_searches"; -const MAX_RECENT_SEARCHES = 8; -const SEARCH_LIMIT = 50; -interface SearchBarProps { - url: string; - loading: boolean; - onUrlChange: (url: string) => void; - onFetch: () => void; - onFetchUrl: (url: string) => Promise; - history: HistoryItem[]; - onHistorySelect: (item: HistoryItem) => void; - onHistoryRemove: (id: string) => void; - hasResult: boolean; - searchMode: boolean; - onSearchModeChange: (isSearch: boolean) => void; - region: string; - onRegionChange: (region: string) => void; -} -export function SearchBar({ url, loading, onUrlChange, onFetch, onFetchUrl, history, onHistorySelect, onHistoryRemove, hasResult, searchMode, onSearchModeChange, region, onRegionChange, }: SearchBarProps) { - const [searchQuery, setSearchQuery] = useState(""); - const [searchResults, setSearchResults] = useState(null); - const [showRegionSelector, setShowRegionSelector] = useState(() => getSettings().linkResolver === "songlink"); - const [resultFilter, setResultFilter] = useState(""); - const [sortOrders, setSortOrders] = useState>({ - tracks: "default", - albums: "default", - artists: "default", - playlists: "default", - }); - const [isSearching, setIsSearching] = useState(false); - const [isLoadingMore, setIsLoadingMore] = useState(false); - const [lastSearchedQuery, setLastSearchedQuery] = useState(""); - const [activeTab, setActiveTab] = useState("tracks"); - const [recentSearches, setRecentSearches] = useState([]); - const [hasMore, setHasMore] = useState>({ - tracks: false, - albums: false, - artists: false, - playlists: false, - }); - const [showInvalidUrlDialog, setShowInvalidUrlDialog] = useState(false); - const [invalidUrl, setInvalidUrl] = useState(""); - const searchTimeoutRef = useRef | null>(null); - const placeholders = searchMode ? SEARCH_PLACEHOLDERS : FETCH_PLACEHOLDERS; - const placeholderText = useTypingEffect(placeholders); - useEffect(() => { - try { - const saved = localStorage.getItem(RECENT_SEARCHES_KEY); - if (saved) { - setRecentSearches(JSON.parse(saved)); - } - } - catch (error) { - console.error("Failed to load recent searches:", error); - } - }, []); - useEffect(() => { - const syncRegionVisibility = (settings?: Partial) => { - const resolver = settings?.linkResolver ?? getSettings().linkResolver; - setShowRegionSelector(resolver === "songlink"); - }; - syncRegionVisibility(); - const handleSettingsUpdate = (event: Event) => { - syncRegionVisibility((event as CustomEvent>).detail); - }; - window.addEventListener("settingsUpdated", handleSettingsUpdate); - return () => window.removeEventListener("settingsUpdated", handleSettingsUpdate); - }, []); - const saveRecentSearch = (query: string) => { - const trimmed = query.trim(); - if (!trimmed) - return; - setRecentSearches((prev) => { - const filtered = prev.filter((s) => s.toLowerCase() !== trimmed.toLowerCase()); - const updated = [trimmed, ...filtered].slice(0, MAX_RECENT_SEARCHES); - try { - localStorage.setItem(RECENT_SEARCHES_KEY, JSON.stringify(updated)); - } - catch (error) { - console.error("Failed to save recent searches:", error); - } - return updated; - }); - }; - const removeRecentSearch = (query: string) => { - setRecentSearches((prev) => { - const updated = prev.filter((s) => s !== query); - try { - localStorage.setItem(RECENT_SEARCHES_KEY, JSON.stringify(updated)); - } - catch (error) { - console.error("Failed to save recent searches:", error); - } - return updated; - }); - }; - useEffect(() => { - if (!searchMode || !searchQuery.trim()) { - return; - } - if (searchQuery.trim() === lastSearchedQuery) { - return; - } - if (searchTimeoutRef.current) { - clearTimeout(searchTimeoutRef.current); - } - searchTimeoutRef.current = setTimeout(async () => { - setIsSearching(true); - try { - const results = await SearchSpotify({ - query: searchQuery, - limit: SEARCH_LIMIT, - }); - setSearchResults(results); - setResultFilter(""); - setLastSearchedQuery(searchQuery.trim()); - saveRecentSearch(searchQuery.trim()); - setHasMore({ - tracks: results.tracks.length === SEARCH_LIMIT, - albums: results.albums.length === SEARCH_LIMIT, - artists: results.artists.length === SEARCH_LIMIT, - playlists: results.playlists.length === SEARCH_LIMIT, - }); - if (results.tracks.length > 0) - setActiveTab("tracks"); - else if (results.albums.length > 0) - setActiveTab("albums"); - else if (results.artists.length > 0) - setActiveTab("artists"); - else if (results.playlists.length > 0) - setActiveTab("playlists"); - } - catch (error) { - console.error("Search failed:", error); - setSearchResults(null); - } - finally { - setIsSearching(false); - } - }, 400); - return () => { - if (searchTimeoutRef.current) { - clearTimeout(searchTimeoutRef.current); - } - }; - }, [searchQuery, searchMode, lastSearchedQuery]); - const handleLoadMore = async () => { - if (!searchResults || !lastSearchedQuery || isLoadingMore) - return; - const typeMap: Record = { - tracks: "track", - albums: "album", - artists: "artist", - playlists: "playlist", - }; - const currentCount = getTabCount(activeTab); - setIsLoadingMore(true); - try { - const moreResults = await SearchSpotifyByType({ - query: lastSearchedQuery, - search_type: typeMap[activeTab], - limit: SEARCH_LIMIT, - offset: currentCount, - }); - if (moreResults.length > 0) { - setSearchResults((prev) => { - if (!prev) - return prev; - const updated = new backend.SearchResponse({ - tracks: activeTab === "tracks" - ? [...prev.tracks, ...moreResults] - : prev.tracks, - albums: activeTab === "albums" - ? [...prev.albums, ...moreResults] - : prev.albums, - artists: activeTab === "artists" - ? [...prev.artists, ...moreResults] - : prev.artists, - playlists: activeTab === "playlists" - ? [...prev.playlists, ...moreResults] - : prev.playlists, - }); - return updated; - }); - } - setHasMore((prev) => ({ - ...prev, - [activeTab]: moreResults.length === SEARCH_LIMIT, - })); - } - catch (error) { - console.error("Load more failed:", error); - } - finally { - setIsLoadingMore(false); - } - }; - const isSpotifyUrl = (text: string) => { - const trimmed = text.trim(); - if (!trimmed) - return true; - const isUrl = /^(https?:\/\/|www\.)/i.test(trimmed) || /^spotify:/i.test(trimmed); - if (!isUrl) - return true; - return (trimmed.includes("spotify.com") || - trimmed.includes("spotify.link") || - trimmed.startsWith("spotify:")); - }; - const handlePaste = (e: React.ClipboardEvent) => { - if (searchMode) - return; - const pastedText = e.clipboardData.getData("text"); - if (pastedText && !isSpotifyUrl(pastedText)) { - e.preventDefault(); - setInvalidUrl(pastedText); - setShowInvalidUrlDialog(true); - } - }; - const handleFetchWithValidation = () => { - if (!isSpotifyUrl(url)) { - setInvalidUrl(url); - setShowInvalidUrlDialog(true); - return; - } - onFetch(); - }; - const handleResultClick = (externalUrl: string) => { - onSearchModeChange(false); - onFetchUrl(externalUrl); - }; - const formatDuration = (ms: number) => { - const minutes = Math.floor(ms / 60000); - const seconds = Math.floor((ms % 60000) / 1000); - return `${minutes}:${seconds.toString().padStart(2, "0")}`; - }; - const hasAnyResults = searchResults && - (searchResults.tracks.length > 0 || - searchResults.albums.length > 0 || - searchResults.artists.length > 0 || - searchResults.playlists.length > 0); - const getTabCount = (tab: ResultTab): number => { - if (!searchResults) - return 0; - switch (tab) { - case "tracks": - return searchResults.tracks.length; - case "albums": - return searchResults.albums.length; - case "artists": - return searchResults.artists.length; - case "playlists": - return searchResults.playlists.length; - } - }; - const sortedResults = useMemo(() => { - if (!searchResults) - return { tracks: [], albums: [], artists: [], playlists: [] }; - const filterStr = resultFilter.toLowerCase(); - let tracks = [...searchResults.tracks]; - if (filterStr) { - tracks = tracks.filter(t => (t.name || '').toLowerCase().includes(filterStr) || (t.artists || '').toLowerCase().includes(filterStr)); - } - const tSort = sortOrders.tracks; - if (tSort !== 'default') { - tracks.sort((a, b) => { - if (tSort === 'title-asc') - return (a.name || '').localeCompare(b.name || ''); - if (tSort === 'title-desc') - return (b.name || '').localeCompare(a.name || ''); - if (tSort === 'artist-asc') - return (a.artists || '').localeCompare(b.artists || ''); - if (tSort === 'artist-desc') - return (b.artists || '').localeCompare(a.artists || ''); - if (tSort === 'duration-desc') - return (b.duration_ms || 0) - (a.duration_ms || 0); - if (tSort === 'duration-asc') - return (a.duration_ms || 0) - (b.duration_ms || 0); - return 0; - }); - } - let albums = [...searchResults.albums]; - if (filterStr) { - albums = albums.filter(a => (a.name || '').toLowerCase().includes(filterStr) || (a.artists || '').toLowerCase().includes(filterStr)); - } - const alSort = sortOrders.albums; - if (alSort !== 'default') { - albums.sort((a, b) => { - if (alSort === 'title-asc') - return (a.name || '').localeCompare(b.name || ''); - if (alSort === 'title-desc') - return (b.name || '').localeCompare(a.name || ''); - if (alSort === 'artist-asc') - return (a.artists || '').localeCompare(b.artists || ''); - if (alSort === 'artist-desc') - return (b.artists || '').localeCompare(a.artists || ''); - if (alSort === 'year-desc') - return (b.release_date || '').localeCompare(a.release_date || ''); - if (alSort === 'year-asc') - return (a.release_date || '').localeCompare(b.release_date || ''); - return 0; - }); - } - let artists = [...searchResults.artists]; - if (filterStr) { - artists = artists.filter(a => (a.name || '').toLowerCase().includes(filterStr)); - } - const arSort = sortOrders.artists; - if (arSort !== 'default') { - artists.sort((a, b) => { - if (arSort === 'name-asc') - return (a.name || '').localeCompare(b.name || ''); - if (arSort === 'name-desc') - return (b.name || '').localeCompare(a.name || ''); - return 0; - }); - } - let playlists = [...searchResults.playlists]; - if (filterStr) { - playlists = playlists.filter(p => (p.name || '').toLowerCase().includes(filterStr) || (p.owner || '').toLowerCase().includes(filterStr)); - } - const pSort = sortOrders.playlists; - if (pSort !== 'default') { - playlists.sort((a, b) => { - if (pSort === 'title-asc') - return (a.name || '').localeCompare(b.name || ''); - if (pSort === 'title-desc') - return (b.name || '').localeCompare(a.name || ''); - if (pSort === 'owner-asc') - return (a.owner || '').localeCompare(b.owner || ''); - if (pSort === 'owner-desc') - return (b.owner || '').localeCompare(a.owner || ''); - return 0; - }); - } - return { tracks, albums, artists, playlists }; - }, [searchResults, sortOrders, resultFilter]); - const tabs: { - key: ResultTab; - label: string; - }[] = [ - { key: "tracks", label: "Tracks" }, - { key: "albums", label: "Albums" }, - { key: "artists", label: "Artists" }, - { key: "playlists", label: "Playlists" }, - ]; - return (
-
- - - - - -

{searchMode ? "Fetch Mode" : "Search Mode"}

-
-
- -
- {!searchMode ? (<> - onUrlChange(e.target.value)} onPaste={handlePaste} onKeyDown={(e) => e.key === "Enter" && handleFetchWithValidation()} className="pr-8"/> - {url && ()} - ) : (<> - setSearchQuery(e.target.value)} className="pr-8"/> - {searchQuery && ()} - )} -
- - {!searchMode && (<> - {showRegionSelector && ()} - - )} -
- - {!searchMode && !hasResult && ()} - - {searchMode && (
- {!searchQuery && !searchResults && recentSearches.length > 0 && (
-

Recent Searches

-
- {recentSearches.map((query) => (
setSearchQuery(query)}> - {query} - -
))} -
-
)} - - {isSearching && (
- - Searching... -
)} - - {!isSearching && searchQuery && !hasAnyResults && (
- No results found for "{searchQuery}" -
)} - - {!isSearching && hasAnyResults && (<> -
- {tabs.map((tab) => { - const count = getTabCount(tab.key); - if (count === 0) - return null; - return (); - })} -
- -
-
- - setResultFilter(e.target.value)} className="pl-10 pr-8"/> - {resultFilter && ()} -
- -
- -
- {activeTab === "tracks" && - sortedResults.tracks.map((track) => ())} - - {activeTab === "albums" && - sortedResults.albums.map((album) => ())} - - {activeTab === "artists" && - sortedResults.artists.map((artist) => ())} - - {activeTab === "playlists" && - sortedResults.playlists.map((playlist) => ())} -
- - {hasMore[activeTab] && (
- -
)} - )} -
)} - - - - - Invalid URL - - Only Spotify links are allowed in Fetch mode. - - - - {invalidUrl && (
- {invalidUrl} -
)} - - - - - -
-
-
); -} diff --git a/frontend/src/components/SettingsPage.tsx b/frontend/src/components/SettingsPage.tsx deleted file mode 100644 index d032be6..0000000 --- a/frontend/src/components/SettingsPage.tsx +++ /dev/null @@ -1,1003 +0,0 @@ -import { useState, useEffect, useCallback } from "react"; -import { flushSync } from "react-dom"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { InputWithContext } from "@/components/ui/input-with-context"; -import { Label } from "@/components/ui/label"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; -import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; -import { FolderOpen, Save, RotateCcw, Info, ArrowRight, MonitorCog, FolderCog, Router, FolderLock, Plus, Trash2, ExternalLink, PlugZap, Download, Tags } from "lucide-react"; -import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; -import { Switch } from "@/components/ui/switch"; -import { getSettings, getSettingsWithDefaults, saveSettings, resetToDefaultSettings, applyThemeMode, applyFont, getFontOptions, parseGoogleFontUrl, loadGoogleFontUrl, loadCustomFonts, saveCustomFonts, FOLDER_PRESETS, FILENAME_PRESETS, TEMPLATE_VARIABLES, hasConfiguredCustomTidalApi, sanitizeAutoOrder, type Settings as SettingsType, type FontFamily, type CustomFontFamily, type FolderPreset, type FilenamePreset, type ExistingFileCheckMode, } from "@/lib/settings"; -import { themes, applyTheme } from "@/lib/themes"; -import { SelectFolder, OpenConfigFolder, CheckCustomTidalAPI } from "../../wailsjs/go/main/App"; -import { toastWithSound as toast } from "@/lib/toast-with-sound"; -import { openExternal } from "@/lib/utils"; -import { ApiStatusTab } from "./ApiStatusTab"; -import { AmazonIcon, QobuzIcon, SonglinkIcon, SongstatsIcon, TidalIcon } from "./PlatformIcons"; -interface SettingsPageProps { - onUnsavedChangesChange?: (hasUnsavedChanges: boolean) => void; - onResetRequest?: (resetFn: () => void) => void; -} -type CustomTidalApiStatus = "idle" | "checking" | "online" | "offline"; -export function SettingsPage({ onUnsavedChangesChange, onResetRequest, }: SettingsPageProps) { - const [savedSettings, setSavedSettings] = useState(getSettings()); - const [tempSettings, setTempSettings] = useState(savedSettings); - const [isDark, setIsDark] = useState(document.documentElement.classList.contains("dark")); - const [showResetConfirm, setShowResetConfirm] = useState(false); - const [showAddFontDialog, setShowAddFontDialog] = useState(false); - const [showCustomTidalApiDialog, setShowCustomTidalApiDialog] = useState(false); - const [addFontUrl, setAddFontUrl] = useState(""); - const [customTidalApiStatus, setCustomTidalApiStatus] = useState("idle"); - const parsedAddFont = parseGoogleFontUrl(addFontUrl); - const fontOptions = getFontOptions(tempSettings.customFonts); - const hasUnsavedChanges = JSON.stringify(savedSettings) !== JSON.stringify(tempSettings); - const hasCustomTidalInstanceConfigured = hasConfiguredCustomTidalApi(tempSettings.customTidalApi); - const effectiveDownloader = !hasCustomTidalInstanceConfigured && tempSettings.downloader === "tidal" - ? "auto" - : tempSettings.downloader; - const effectiveAutoOrder = sanitizeAutoOrder(tempSettings.autoOrder, hasCustomTidalInstanceConfigured); - const resetToSaved = useCallback(() => { - const freshSavedSettings = getSettings(); - flushSync(() => { - setTempSettings(freshSavedSettings); - setIsDark(document.documentElement.classList.contains("dark")); - }); - }, []); - useEffect(() => { - if (onResetRequest) { - onResetRequest(resetToSaved); - } - }, [onResetRequest, resetToSaved]); - useEffect(() => { - onUnsavedChangesChange?.(hasUnsavedChanges); - }, [hasUnsavedChanges, onUnsavedChangesChange]); - useEffect(() => { - applyThemeMode(savedSettings.themeMode); - applyTheme(savedSettings.theme); - const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - const handleChange = () => { - if (savedSettings.themeMode === "auto") { - applyThemeMode("auto"); - applyTheme(savedSettings.theme); - } - }; - mediaQuery.addEventListener("change", handleChange); - return () => mediaQuery.removeEventListener("change", handleChange); - }, [savedSettings.themeMode, savedSettings.theme]); - useEffect(() => { - applyThemeMode(tempSettings.themeMode); - applyTheme(tempSettings.theme); - applyFont(tempSettings.fontFamily, tempSettings.customFonts); - setTimeout(() => { - setIsDark(document.documentElement.classList.contains("dark")); - }, 0); - }, [tempSettings.themeMode, tempSettings.theme, tempSettings.fontFamily, tempSettings.customFonts]); - useEffect(() => { - if (showAddFontDialog && parsedAddFont) { - loadGoogleFontUrl(parsedAddFont.url, "spotiflac-add-font-preview"); - } - }, [showAddFontDialog, parsedAddFont]); - useEffect(() => { - const loadDefaults = async () => { - const currentSettings = getSettings(); - if (!currentSettings.downloadPath) { - const settingsWithDefaults = await getSettingsWithDefaults(); - setSavedSettings(settingsWithDefaults); - setTempSettings(settingsWithDefaults); - await saveSettings(settingsWithDefaults); - } - }; - loadDefaults(); - }, []); - useEffect(() => { - const syncCustomFonts = async () => { - const customFonts = await loadCustomFonts(); - setSavedSettings((prev) => ({ ...prev, customFonts })); - setTempSettings((prev) => ({ ...prev, customFonts })); - }; - void syncCustomFonts(); - }, []); - const handleSave = async () => { - await saveSettings(tempSettings); - const persistedSettings = getSettings(); - setSavedSettings(persistedSettings); - setTempSettings(persistedSettings); - toast.success("Settings saved"); - onUnsavedChangesChange?.(false); - }; - const handleReset = async () => { - const defaultSettings = await resetToDefaultSettings(); - setTempSettings(defaultSettings); - setSavedSettings(defaultSettings); - applyThemeMode(defaultSettings.themeMode); - applyTheme(defaultSettings.theme); - applyFont(defaultSettings.fontFamily, defaultSettings.customFonts); - setShowResetConfirm(false); - toast.success("Settings reset to default"); - }; - const handleBrowseFolder = async () => { - try { - const selectedPath = await SelectFolder(tempSettings.downloadPath || ""); - if (selectedPath && selectedPath.trim() !== "") { - setTempSettings((prev) => ({ ...prev, downloadPath: selectedPath })); - } - } - catch (error) { - console.error("Error selecting folder:", error); - toast.error(`Error selecting folder: ${error}`); - } - }; - const closeAddFontDialog = () => { - setShowAddFontDialog(false); - setAddFontUrl(""); - }; - const handleAddFont = async () => { - if (!parsedAddFont) { - toast.error("Enter a valid Google Fonts URL"); - return; - } - const existingFonts = tempSettings.customFonts || []; - const existingIndex = existingFonts.findIndex((font) => font.value === parsedAddFont.value || font.url === parsedAddFont.url); - const customFonts = existingIndex >= 0 - ? existingFonts.map((font, index) => index === existingIndex ? parsedAddFont : font) - : [...existingFonts, parsedAddFont]; - const savedCustomFonts = await saveCustomFonts(customFonts); - setSavedSettings((prev) => ({ ...prev, customFonts: savedCustomFonts })); - setTempSettings((prev) => ({ - ...prev, - customFonts: savedCustomFonts, - fontFamily: parsedAddFont.value, - })); - closeAddFontDialog(); - toast.success(`${parsedAddFont.label} added`); - }; - const handleDeleteCustomFont = async (fontValue: CustomFontFamily) => { - const customFonts = (tempSettings.customFonts || []).filter((font) => font.value !== fontValue); - const savedCustomFonts = await saveCustomFonts(customFonts); - const shouldResetSavedFont = savedSettings.fontFamily === fontValue; - const shouldResetTempFont = tempSettings.fontFamily === fontValue; - const nextSavedSettings: SettingsType = { - ...savedSettings, - customFonts: savedCustomFonts, - fontFamily: shouldResetSavedFont ? "google-sans" : savedSettings.fontFamily, - }; - setSavedSettings(nextSavedSettings); - setTempSettings((prev) => ({ - ...prev, - customFonts: savedCustomFonts, - fontFamily: shouldResetTempFont ? "google-sans" : prev.fontFamily, - })); - if (shouldResetSavedFont) { - await saveSettings(nextSavedSettings); - } - toast.success("Font deleted"); - }; - const handleTidalQualityChange = async (value: "LOSSLESS" | "HI_RES_LOSSLESS") => { - setTempSettings((prev) => ({ ...prev, tidalQuality: value })); - }; - const handleQobuzQualityChange = (value: "6" | "7" | "27") => { - setTempSettings((prev) => ({ ...prev, qobuzQuality: value })); - }; - const handleAutoQualityChange = async (value: "16" | "24") => { - setTempSettings((prev) => ({ ...prev, autoQuality: value })); - }; - const persistCustomTidalApi = useCallback(async (nextValue: string) => { - const normalizedValue = nextValue.trim().replace(/\/+$/g, ""); - const persistedSettings = getSettings(); - const nextSavedSettings: SettingsType = { - ...persistedSettings, - customTidalApi: normalizedValue, - }; - await saveSettings(nextSavedSettings); - const nextSavedState = getSettings(); - setSavedSettings(nextSavedState); - setTempSettings((prev) => ({ - ...prev, - customTidalApi: nextSavedState.customTidalApi, - downloader: !hasConfiguredCustomTidalApi(nextSavedState.customTidalApi) && prev.downloader === "tidal" - ? nextSavedState.downloader - : prev.downloader, - autoOrder: sanitizeAutoOrder(prev.autoOrder, hasConfiguredCustomTidalApi(nextSavedState.customTidalApi)), - })); - }, []); - const handleCheckCustomTidalApi = async () => { - const normalizedCustomTidalApi = (tempSettings.customTidalApi || "").trim().replace(/\/+$/g, ""); - if (!normalizedCustomTidalApi.startsWith("https://")) { - toast.error("Enter a valid HTTPS HiFi API URL"); - return; - } - setCustomTidalApiStatus("checking"); - try { - const isOnline = await CheckCustomTidalAPI(normalizedCustomTidalApi); - setCustomTidalApiStatus(isOnline ? "online" : "offline"); - if (isOnline) { - toast.success("HiFi API instance is online"); - } - else { - toast.error("HiFi API instance is offline"); - } - } - catch (error) { - console.error("Failed to check custom Tidal API:", error); - setCustomTidalApiStatus("offline"); - toast.error(`Failed to check HiFi API instance: ${error}`); - } - }; - const [activeTab, setActiveTab] = useState<"general" | "download" | "files" | "metadata" | "status">("general"); - return (
-
-

Settings

-
- - - -
-
- -
- - - - - -
- -
- {activeTab === "general" && (
-
-
- - -
- -
- - -
-
- -
-
- -
- - -
-
- -
- setTempSettings((prev) => ({ - ...prev, - sfxEnabled: checked, - }))}/> - -
-
-
)} - - {activeTab === "download" && (
-
-
- -
- - {tempSettings.customTidalApi && ( - {tempSettings.customTidalApi} - )} -
-
- -
- -
- - - {effectiveDownloader === "auto" && (<> - - - - )} - - {effectiveDownloader === "tidal" && ()} - - {effectiveDownloader === "qobuz" && ()} - - {effectiveDownloader === "amazon" && (
- 16-bit - 24-bit/44.1kHz - 192kHz -
)} -
- - {((effectiveDownloader === "tidal" && - tempSettings.tidalQuality === "HI_RES_LOSSLESS") || - (effectiveDownloader === "qobuz" && - tempSettings.qobuzQuality === "27") || - (effectiveDownloader === "auto" && - tempSettings.autoQuality === "24")) && (
- setTempSettings((prev) => ({ - ...prev, - allowFallback: checked, - }))}/> - -
)} -
-
- -
-
- -
- -
-
- -
- setTempSettings((prev) => ({ - ...prev, - allowResolverFallback: checked, - }))}/> - -
-
-
)} - - {activeTab === "files" && (
-
-
- -
- setTempSettings((prev) => ({ - ...prev, - downloadPath: e.target.value, - }))} placeholder="C:\Users\YourUsername\Music"/> - -
-
- -
-
- - - - - - -

- Variables:{" "} - {TEMPLATE_VARIABLES.map((v) => v.key).join(", ")} -

-
-
-
-
- - {tempSettings.folderPreset === "custom" && ( setTempSettings((prev) => ({ - ...prev, - folderTemplate: e.target.value, - }))} placeholder="{artist}/{album}" className="h-9 text-sm flex-1"/>)} -
- {tempSettings.folderTemplate && (

- Preview:{" "} - - {tempSettings.folderTemplate - .replace(/\{artist\}/g, tempSettings.separator === "comma" ? "Kendrick Lamar, SZA" : "Kendrick Lamar; SZA") - .replace(/\{album\}/g, "Black Panther") - .replace(/\{album_artist\}/g, "Kendrick Lamar") - .replace(/\{title\}/g, "All The Stars") - .replace(/\{track\}/g, "01") - .replace(/\{disc\}/g, "1") - .replace(/\{year\}/g, "2018") - .replace(/\{date\}/g, "2018-02-09") - .replace(/\{isrc\}/g, "USUM71801234")} - / - -

)} -
- -
- setTempSettings((prev) => ({ - ...prev, - createPlaylistFolder: checked, - }))}/> - -
- -
- setTempSettings((prev) => ({ - ...prev, - playlistOwnerFolderName: checked, - }))}/> - -
- -
- setTempSettings((prev) => ({ - ...prev, - createM3u8File: checked, - }))}/> - -
-
- -
-
- - -
- -
-
- - - - - - -

- Variables:{" "} - {TEMPLATE_VARIABLES.map((v) => v.key).join(", ")} -

-
-
-
-
- - {tempSettings.filenamePreset === "custom" && ( setTempSettings((prev) => ({ - ...prev, - filenameTemplate: e.target.value, - }))} placeholder="{track}. {title}" className="h-9 text-sm flex-1"/>)} -
- {tempSettings.filenameTemplate && (

- Preview:{" "} - - {tempSettings.filenameTemplate - .replace(/\{artist\}/g, tempSettings.separator === "comma" ? "Kendrick Lamar, SZA" : "Kendrick Lamar; SZA") - .replace(/\{album_artist\}/g, "Kendrick Lamar") - .replace(/\{album\}/g, "Black Panther") - .replace(/\{title\}/g, "All The Stars") - .replace(/\{track\}/g, "01") - .replace(/\{disc\}/g, "1") - .replace(/\{year\}/g, "2018") - .replace(/\{date\}/g, "2018-02-09") - .replace(/\{isrc\}/g, "USUM71801234")} - .flac - -

)} -
- -
- - -
- -
- setTempSettings((prev) => ({ - ...prev, - redownloadWithSuffix: checked, - }))}/> - -
-
-
)} - - {activeTab === "metadata" && (
-
-
- setTempSettings((prev) => ({ - ...prev, - embedLyrics: checked, - }))}/> - -
- -
- setTempSettings((prev) => ({ - ...prev, - embedMaxQualityCover: checked, - }))}/> - -
- -
- setTempSettings((prev) => ({ - ...prev, - embedGenre: checked, - }))}/> - -
- - {tempSettings.embedGenre && (
- setTempSettings((prev) => ({ - ...prev, - useSingleGenre: checked, - }))}/> - -
)} -
- -
-
- setTempSettings((prev) => ({ - ...prev, - useFirstArtistOnly: checked, - }))}/> - -
-
-
)} - - {activeTab === "status" && ()} -
- - open ? setShowAddFontDialog(true) : closeAddFontDialog()}> - - -
- Add Font - -
- -
-
-
- - setAddFontUrl(event.target.value)} onKeyDown={(event) => { - if (event.key === "Enter" && parsedAddFont) { - void handleAddFont(); - } - }} placeholder="https://fonts.google.com/specimen/Ubuntu" autoFocus/> - {addFontUrl.trim() && !parsedAddFont && (

- Enter a valid Google Fonts URL. -

)} -
-
-

- Preview -

-

- Aa The quick brown fox -

-

- Kendrick Lamar - All The Stars -

-
-
- - - - -
-
- - - - -
- Tidal Source - -
- -
-
-
- -
- { - const nextValue = e.target.value.replace(/\/+$/g, ""); - setCustomTidalApiStatus("idle"); - void persistCustomTidalApi(nextValue); - }} placeholder="https://your-hifi-api.example"/> - - {tempSettings.customTidalApi && ()} -
-
- {customTidalApiStatus !== "idle" && (

- {customTidalApiStatus === "online" - ? "Custom HiFi API instance is online." - : customTidalApiStatus === "offline" - ? "Custom HiFi API instance is offline or returned preview-only data." - : "Checking custom HiFi API instance..."} -

)} -
- - - -
-
- - - - - Reset to Default? - - This will reset all settings to their default values. Your custom - font list will be kept. - - - - - - - - -
); -} diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx deleted file mode 100644 index 1554a08..0000000 --- a/frontend/src/components/Sidebar.tsx +++ /dev/null @@ -1,200 +0,0 @@ -import { useRef, useState, type RefObject } from "react"; -import { HomeIcon } from "@/components/ui/home"; -import { HistoryIcon } from "@/components/ui/history-icon"; -import { SettingsIcon } from "@/components/ui/settings"; -import { ActivityIcon, type ActivityIconHandle } from "@/components/ui/activity"; -import { TerminalIcon } from "@/components/ui/terminal"; -import { FileMusicIcon, type FileMusicIconHandle } from "@/components/ui/file-music"; -import { FilePenIcon, type FilePenIconHandle } from "@/components/ui/file-pen"; -import { BugReportIcon } from "@/components/ui/bug-report-icon"; -import { CoffeeIcon } from "@/components/ui/coffee"; -import { BlocksIcon } from "@/components/ui/blocks-icon"; -import { AudioLinesIcon, type AudioLinesIconHandle } from "@/components/ui/audio-lines"; -import { ToolCaseIcon } from "@/components/ui/tool-case"; -import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; -import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; -import { Checkbox } from "@/components/ui/checkbox"; -import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; -import { Button } from "@/components/ui/button"; -import { openExternal } from "@/lib/utils"; -export type PageType = "main" | "settings" | "debug" | "audio-analysis" | "audio-converter" | "audio-resampler" | "file-manager" | "projects" | "support" | "history"; -interface SidebarProps { - currentPage: PageType; - onPageChange: (page: PageType) => void; -} -interface AnimatedIconHandle { - startAnimation: () => void; - stopAnimation: () => void; -} -export function Sidebar({ currentPage, onPageChange }: SidebarProps) { - const [isIssuesDialogOpen, setIsIssuesDialogOpen] = useState(false); - const [hasIssueAgreement, setHasIssueAgreement] = useState(false); - const analyzerIconRef = useRef(null); - const resamplerIconRef = useRef(null); - const converterIconRef = useRef(null); - const fileManagerIconRef = useRef(null); - const handleIssuesDialogChange = (open: boolean) => { - setIsIssuesDialogOpen(open); - if (!open) { - setHasIssueAgreement(false); - } - }; - const handleOpenIssues = () => { - openExternal("https://github.com/spotbye/SpotiFLAC/issues"); - handleIssuesDialogChange(false); - }; - const getAnimatedItemHandlers = (iconRef: RefObject) => ({ - onMouseEnter: () => iconRef.current?.startAnimation(), - onMouseLeave: () => iconRef.current?.stopAnimation(), - onFocus: () => iconRef.current?.startAnimation(), - onBlur: () => iconRef.current?.stopAnimation(), - }); - return (
-
- - - - - -

Home

-
-
- - - - - - -

History

-
-
- - - - - - -

Settings

-
-
- - - - - - -

Debug Logs

-
-
- - - - - - - - - -

Tools

-
-
- - onPageChange("audio-analysis")} className="gap-3 cursor-pointer py-2 px-3" {...getAnimatedItemHandlers(analyzerIconRef)}> - - Audio Quality Analyzer - - onPageChange("audio-resampler")} className="gap-3 cursor-pointer py-2 px-3" {...getAnimatedItemHandlers(resamplerIconRef)}> - - Audio Resampler - - onPageChange("audio-converter")} className="gap-3 cursor-pointer py-2 px-3" {...getAnimatedItemHandlers(converterIconRef)}> - - Audio Converter - - onPageChange("file-manager")} className="gap-3 cursor-pointer py-2 px-3" {...getAnimatedItemHandlers(fileManagerIconRef)}> - - File Manager - - -
-
- -
- - - - - - -

Report Bugs or Request Features

-
-
- - - Before Opening GitHub Issues - - - -
-
-

Important

-

- Search existing issues first and use the issue template when opening a new report or request. -

-
- - -
- - - - - -
-
- - - - - - -

Other Projects

-
-
- - - - - - -

Support Me

-
-
-
-
); -} diff --git a/frontend/src/components/SpectrumVisualization.tsx b/frontend/src/components/SpectrumVisualization.tsx deleted file mode 100644 index 6b9d288..0000000 --- a/frontend/src/components/SpectrumVisualization.tsx +++ /dev/null @@ -1,602 +0,0 @@ -import { useEffect, useRef, useState, forwardRef, useImperativeHandle } from "react"; -import type { SpectrumData } from "@/types/api"; -import { Label } from "@/components/ui/label"; -import { Progress } from "@/components/ui/progress"; -import { loadAudioAnalysisPreferences, saveAudioAnalysisPreferences, type AnalyzerColorScheme, type AnalyzerFreqScale, type AnalyzerWindowFunction, } from "@/lib/audio-analysis-preferences"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; -export interface SpectrumVisualizationHandle { - getCanvasDataURL: () => string | null; -} -type ColorScheme = AnalyzerColorScheme; -type FreqScale = AnalyzerFreqScale; -type WindowFunction = AnalyzerWindowFunction; -export interface SpectrogramRenderOptions { - spectrumData: SpectrumData; - sampleRate: number; - duration: number; - freqScale: FreqScale; - colorScheme: ColorScheme; - fileName?: string; - shouldCancel?: () => boolean; -} -interface SpectrumVisualizationProps { - sampleRate: number; - duration: number; - spectrumData?: SpectrumData; - fileName?: string; - onReAnalyze?: (fftSize: number, windowFunction: string) => void; - isAnalyzingSpectrum?: boolean; - spectrumProgress?: { - percent: number; - message: string; - }; -} -const MARGIN = { top: 50, right: 120, bottom: 70, left: 90 }; -const CANVAS_W = 1100; -const CANVAS_H = 600; -const MAX_RENDER_HEIGHT = 1080; -function clamp01(value: number): number { - return Math.max(0, Math.min(1, value)); -} -function spekColorMap(t: number): [ - number, - number, - number -] { - const colors: Array<[ - number, - number, - number - ]> = [ - [0, 0, 0], - [0, 0, 25], - [0, 0, 50], - [0, 0, 80], - [20, 0, 120], - [50, 0, 150], - [80, 0, 180], - [120, 0, 120], - [150, 0, 80], - [180, 0, 40], - [210, 0, 0], - [240, 30, 0], - [255, 60, 0], - [255, 100, 0], - [255, 140, 0], - [255, 180, 0], - [255, 210, 0], - [255, 235, 0], - [255, 250, 50], - [255, 255, 100], - [255, 255, 150], - [255, 255, 200], - [255, 255, 255], - ]; - const scaled = t * (colors.length - 1); - const idx = Math.floor(scaled); - const fraction = scaled - idx; - if (idx >= colors.length - 1) { - return colors[colors.length - 1]; - } - const c1 = colors[idx]; - const c2 = colors[idx + 1]; - return [ - Math.round(c1[0] + (c2[0] - c1[0]) * fraction), - Math.round(c1[1] + (c2[1] - c1[1]) * fraction), - Math.round(c1[2] + (c2[2] - c1[2]) * fraction), - ]; -} -function viridisColorMap(t: number): [ - number, - number, - number -] { - const colors: Array<[ - number, - number, - number - ]> = [ - [68, 1, 84], - [70, 20, 100], - [72, 40, 120], - [67, 62, 133], - [62, 74, 137], - [55, 89, 140], - [49, 104, 142], - [43, 117, 142], - [38, 130, 142], - [35, 144, 140], - [31, 158, 137], - [42, 171, 129], - [53, 183, 121], - [81, 194, 105], - [109, 205, 89], - [144, 214, 67], - [180, 222, 44], - [216, 227, 41], - [253, 231, 37], - ]; - const scaled = t * (colors.length - 1); - const idx = Math.floor(scaled); - const fraction = scaled - idx; - if (idx >= colors.length - 1) { - return colors[colors.length - 1]; - } - const c1 = colors[idx]; - const c2 = colors[idx + 1]; - return [ - Math.floor(c1[0] + (c2[0] - c1[0]) * fraction), - Math.floor(c1[1] + (c2[1] - c1[1]) * fraction), - Math.floor(c1[2] + (c2[2] - c1[2]) * fraction), - ]; -} -function hotColorMap(t: number): [ - number, - number, - number -] { - if (t < 0.33) { - return [Math.floor(t * 3 * 255), 0, 0]; - } - if (t < 0.66) { - return [255, Math.floor((t - 0.33) * 3 * 255), 0]; - } - return [255, 255, Math.floor((t - 0.66) * 3 * 255)]; -} -function coolColorMap(t: number): [ - number, - number, - number -] { - return [Math.floor(t * 255), Math.floor((1 - t) * 255), 255]; -} -function getColorValues(norm: number, scheme: ColorScheme): [ - number, - number, - number -] { - const value = clamp01(norm); - switch (scheme) { - case "spek": - return spekColorMap(value); - case "viridis": - return viridisColorMap(value); - case "hot": - return hotColorMap(value); - case "cool": - return coolColorMap(value); - case "grayscale": - default: { - const gray = Math.floor(value * 255); - return [gray, gray, gray]; - } - } -} -function getColorString(norm: number, scheme: ColorScheme): string { - const [r, g, b] = getColorValues(norm, scheme); - return `rgb(${r},${g},${b})`; -} -function addAxisLabels(ctx: CanvasRenderingContext2D, plotWidth: number, plotHeight: number, sampleRate: number, duration: number, freqScale: FreqScale, fileName?: string) { - ctx.fillStyle = "#ffffff"; - ctx.font = "12px Segoe UI"; - ctx.textAlign = "center"; - const widthFactor = plotWidth / 1000; - let timeStep: number; - if (duration <= 10) { - timeStep = widthFactor >= 1.8 ? 0.25 : (widthFactor >= 1.3 ? 0.5 : 0.5); - } - else if (duration <= 30) { - timeStep = widthFactor >= 1.8 ? 0.5 : (widthFactor >= 1.3 ? 1 : 1); - } - else if (duration <= 120) { - timeStep = widthFactor >= 1.8 ? 3 : (widthFactor >= 1.3 ? 4 : 5); - } - else if (duration <= 600) { - timeStep = widthFactor >= 1.8 ? 10 : (widthFactor >= 1.3 ? 15 : 20); - } - else { - timeStep = widthFactor >= 1.8 ? 20 : (widthFactor >= 1.3 ? 30 : 40); - } - if (duration > 0) { - for (let time = 0; time <= duration + 1e-9; time += timeStep) { - const timeProgress = time / duration; - const x = MARGIN.left + timeProgress * (plotWidth - 1); - const y = CANVAS_H - MARGIN.bottom + 20; - ctx.strokeStyle = "#ffffff"; - ctx.lineWidth = 1; - ctx.beginPath(); - ctx.moveTo(x, MARGIN.top + plotHeight); - ctx.lineTo(x, MARGIN.top + plotHeight + 5); - ctx.stroke(); - let label: string; - if (timeStep >= 60) { - const minutes = Math.floor(time / 60); - const seconds = time % 60; - label = seconds === 0 ? `${minutes}m` : `${minutes}m${seconds}s`; - } - else { - label = `${time}s`; - } - ctx.fillText(label, x, y); - } - } - ctx.textAlign = "right"; - const maxFreq = sampleRate / 2; - if (freqScale === "log2") { - const heightFactor = plotHeight / 500; - const minFreq = 20; - const frequencies: number[] = []; - const octaveStep = heightFactor >= 1.5 ? 1 : (heightFactor >= 1.0 ? 1 : 2); - let octaveCount = 0; - for (let freq = minFreq; freq <= maxFreq; freq *= 2) { - if (octaveCount % octaveStep === 0) { - frequencies.push(freq); - } - octaveCount++; - } - for (const freq of frequencies) { - const freqNormalized = Math.log2(freq / minFreq) / Math.log2(maxFreq / minFreq); - const y = MARGIN.top + plotHeight * (1 - freqNormalized); - ctx.strokeStyle = "#ffffff"; - ctx.lineWidth = 1; - ctx.beginPath(); - ctx.moveTo(MARGIN.left - 5, y); - ctx.lineTo(MARGIN.left, y); - ctx.stroke(); - const label = freq >= 1000 ? `${(freq / 1000).toFixed(1)}k` : `${freq}`; - ctx.fillText(label, MARGIN.left - 10, y + 4); - } - } - else { - const heightFactor = plotHeight / 500; - let freqStep: number; - if (maxFreq <= 8000) { - freqStep = heightFactor >= 1.8 ? 250 : (heightFactor >= 1.3 ? 400 : 500); - } - else if (maxFreq <= 16000) { - freqStep = heightFactor >= 1.8 ? 500 : (heightFactor >= 1.3 ? 800 : 1000); - } - else if (maxFreq <= 24000) { - freqStep = heightFactor >= 1.8 ? 1000 : (heightFactor >= 1.3 ? 1500 : 2000); - } - else { - freqStep = heightFactor >= 1.8 ? 2000 : (heightFactor >= 1.3 ? 2500 : 4000); - } - for (let freq = 0; freq <= maxFreq; freq += freqStep) { - const y = MARGIN.top + plotHeight - (freq / maxFreq) * plotHeight + 4; - const x = MARGIN.left - 15; - ctx.strokeStyle = "#ffffff"; - ctx.lineWidth = 1; - ctx.beginPath(); - ctx.moveTo(MARGIN.left - 5, y - 4); - ctx.lineTo(MARGIN.left, y - 4); - ctx.stroke(); - let label: string; - if (freq === 0) { - label = "0"; - } - else if (freq >= 1000) { - label = freq % 1000 === 0 ? `${freq / 1000}k` : `${(freq / 1000).toFixed(1)}k`; - } - else { - label = `${freq}`; - } - ctx.fillText(label, x, y); - } - } - ctx.textAlign = "center"; - ctx.font = "14px Segoe UI"; - ctx.fillText("Time (seconds)", CANVAS_W / 2, CANVAS_H - 15); - ctx.save(); - ctx.translate(25, CANVAS_H / 2); - ctx.rotate(-Math.PI / 2); - ctx.fillText("Frequency (Hz)", 0, 0); - ctx.restore(); - ctx.font = "12px Segoe UI"; - if (fileName) { - ctx.textAlign = "left"; - ctx.fillText(fileName, MARGIN.left + 15, 25); - } - ctx.textAlign = "right"; - ctx.fillText(`Sample Rate: ${sampleRate} Hz`, CANVAS_W - 20, 25); -} -function drawColorBar(ctx: CanvasRenderingContext2D, plotHeight: number, colorScheme: ColorScheme) { - const colorBarWidth = 20; - const colorBarX = CANVAS_W - MARGIN.right + 30; - const colorBarY = MARGIN.top; - const gradient = ctx.createLinearGradient(0, colorBarY + plotHeight, 0, colorBarY); - for (let i = 0; i <= 100; i++) { - const value = i / 100; - gradient.addColorStop(value, getColorString(value, colorScheme)); - } - ctx.fillStyle = gradient; - ctx.fillRect(colorBarX, colorBarY, colorBarWidth, plotHeight); - ctx.strokeStyle = "#ffffff"; - ctx.lineWidth = 1; - ctx.strokeRect(colorBarX, colorBarY, colorBarWidth, plotHeight); - ctx.fillStyle = "#ffffff"; - ctx.font = "10px Segoe UI"; - ctx.textAlign = "left"; - ctx.fillText("High", colorBarX + colorBarWidth + 5, colorBarY + 12); - ctx.fillText("Low", colorBarX + colorBarWidth + 5, colorBarY + plotHeight - 5); -} -async function renderSpectrogram(ctx: CanvasRenderingContext2D, spectrum: SpectrumData, sampleRate: number, duration: number, freqScale: FreqScale, colorScheme: ColorScheme, fileName: string | undefined, shouldCancel: () => boolean) { - const plotWidth = CANVAS_W - MARGIN.left - MARGIN.right; - const plotHeight = CANVAS_H - MARGIN.top - MARGIN.bottom; - ctx.fillStyle = "#000000"; - ctx.fillRect(0, 0, CANVAS_W, CANVAS_H); - const spectrogramData = spectrum.time_slices; - const numTimeFrames = spectrogramData.length; - const numFreqBins = spectrogramData[0]?.magnitudes.length ?? 0; - if (numTimeFrames === 0 || numFreqBins === 0) { - return; - } - let minMag = Number.POSITIVE_INFINITY; - let maxMag = Number.NEGATIVE_INFINITY; - const sampleStep = numTimeFrames > 10000 ? Math.floor(numTimeFrames / 5000) : 1; - for (let i = 0; i < numTimeFrames; i += sampleStep) { - const frame = spectrogramData[i].magnitudes; - for (const mag of frame) { - if (Number.isFinite(mag)) { - if (mag < minMag) - minMag = mag; - if (mag > maxMag) - maxMag = mag; - } - } - } - if (!Number.isFinite(minMag) || !Number.isFinite(maxMag)) { - minMag = -120; - maxMag = 0; - } - const magRange = maxMag - minMag; - const safeMagRange = magRange > 0 ? magRange : 1; - const highResImageData = ctx.createImageData(plotWidth, MAX_RENDER_HEIGHT); - const highResData = highResImageData.data; - const CHUNK_SIZE = 50; - for (let xStart = 0; xStart < plotWidth; xStart += CHUNK_SIZE) { - if (shouldCancel()) { - return; - } - const xEnd = Math.min(xStart + CHUNK_SIZE, plotWidth); - for (let x = xStart; x < xEnd; x++) { - const timeProgress = x / (plotWidth - 1); - const exactTimePos = timeProgress * (numTimeFrames - 1); - const timeIdx = Math.floor(exactTimePos); - const timeIdx2 = Math.min(timeIdx + 1, numTimeFrames - 1); - const timeFrac = exactTimePos - timeIdx; - const frame1 = spectrogramData[timeIdx]?.magnitudes ?? spectrogramData[0].magnitudes; - const frame2 = spectrogramData[timeIdx2]?.magnitudes ?? frame1; - for (let y = 0; y < MAX_RENDER_HEIGHT; y++) { - let freqProgress = (MAX_RENDER_HEIGHT - 1 - y) / (MAX_RENDER_HEIGHT - 1); - if (freqScale === "log2") { - const minFreq = 20; - const maxFreq = sampleRate / 2; - const octaves = Math.log2(maxFreq / minFreq); - const octave = freqProgress * octaves; - const freq = minFreq * Math.pow(2, octave); - freqProgress = freq / maxFreq; - } - const exactFreqPos = freqProgress * (numFreqBins - 1); - const freqIdx = Math.floor(exactFreqPos); - const freqIdx2 = Math.min(freqIdx + 1, numFreqBins - 1); - const freqFrac = exactFreqPos - freqIdx; - let magnitude: number; - if (timeFrac === 0 && freqFrac === 0) { - magnitude = frame1[freqIdx] ?? 0; - } - else { - const mag11 = frame1[freqIdx] ?? 0; - const mag12 = frame1[freqIdx2] ?? 0; - const mag21 = frame2[freqIdx] ?? 0; - const mag22 = frame2[freqIdx2] ?? 0; - const magT1 = mag11 * (1 - freqFrac) + mag12 * freqFrac; - const magT2 = mag21 * (1 - freqFrac) + mag22 * freqFrac; - magnitude = magT1 * (1 - timeFrac) + magT2 * timeFrac; - } - const normalizedMag = clamp01((magnitude - minMag) / safeMagRange); - const [r, g, b] = getColorValues(normalizedMag, colorScheme); - const pixelIdx = (y * plotWidth + x) * 4; - highResData[pixelIdx] = r; - highResData[pixelIdx + 1] = g; - highResData[pixelIdx + 2] = b; - highResData[pixelIdx + 3] = 255; - } - } - if (xStart + CHUNK_SIZE < plotWidth) { - await new Promise((resolve) => setTimeout(resolve, 1)); - } - } - if (shouldCancel()) { - return; - } - const finalImageData = ctx.createImageData(plotWidth, plotHeight); - const finalData = finalImageData.data; - for (let y = 0; y < plotHeight; y++) { - for (let x = 0; x < plotWidth; x++) { - const highResY = Math.round((y / plotHeight) * MAX_RENDER_HEIGHT); - const highResIdx = (highResY * plotWidth + x) * 4; - const finalIdx = (y * plotWidth + x) * 4; - if (highResIdx < highResData.length) { - finalData[finalIdx] = highResData[highResIdx]; - finalData[finalIdx + 1] = highResData[highResIdx + 1]; - finalData[finalIdx + 2] = highResData[highResIdx + 2]; - finalData[finalIdx + 3] = highResData[highResIdx + 3]; - } - } - } - ctx.putImageData(finalImageData, MARGIN.left, MARGIN.top); - addAxisLabels(ctx, plotWidth, plotHeight, sampleRate, duration, freqScale, fileName); - drawColorBar(ctx, plotHeight, colorScheme); -} -export async function renderSpectrogramToCanvas(canvas: HTMLCanvasElement, options: SpectrogramRenderOptions): Promise { - canvas.width = CANVAS_W; - canvas.height = CANVAS_H; - const ctx = canvas.getContext("2d"); - if (!ctx) { - throw new Error("Cannot get 2D canvas context"); - } - await renderSpectrogram(ctx, options.spectrumData, options.sampleRate, options.duration, options.freqScale, options.colorScheme, options.fileName, options.shouldCancel ?? (() => false)); -} -export async function createSpectrogramDataURL(options: SpectrogramRenderOptions): Promise { - const canvas = document.createElement("canvas"); - await renderSpectrogramToCanvas(canvas, options); - return canvas.toDataURL("image/png"); -} -const COLOR_SCHEMES: { - value: ColorScheme; - label: string; - gradient: string; -}[] = [ - { value: "spek", label: "Spek", gradient: "linear-gradient(to right, #0f0040, #1e0080, #4000ff, #8000ff, #ff0080, #ff4000, #ff8000, #ffff00)" }, - { value: "viridis", label: "Viridis", gradient: "linear-gradient(to right, #440154, #31688e, #35b779, #fde725)" }, - { value: "hot", label: "Hot", gradient: "linear-gradient(to right, #000000, #ff0000, #ffff00, #ffffff)" }, - { value: "cool", label: "Cool", gradient: "linear-gradient(to right, #000080, #0000ff, #00ffff, #ffffff)" }, - { value: "grayscale", label: "Grayscale", gradient: "linear-gradient(to right, #000000, #ffffff)" }, -]; -export const SpectrumVisualization = forwardRef(({ sampleRate, duration, spectrumData, fileName, onReAnalyze, isAnalyzingSpectrum, spectrumProgress, }, ref) => { - const canvasRef = useRef(null); - const preferencesRef = useRef(loadAudioAnalysisPreferences()); - useImperativeHandle(ref, () => ({ - getCanvasDataURL: () => { - if (!canvasRef.current) - return null; - return canvasRef.current.toDataURL("image/png"); - }, - })); - const [freqScale, setFreqScale] = useState(preferencesRef.current.freqScale); - const [colorScheme, setColorScheme] = useState(preferencesRef.current.colorScheme); - const [fftSize, setFftSize] = useState(() => String(preferencesRef.current.fftSize)); - const [windowFunction, setWindowFunction] = useState(preferencesRef.current.windowFunction); - useEffect(() => { - if (spectrumData?.freq_bins) { - setFftSize(String((spectrumData.freq_bins - 1) * 2)); - } - }, [spectrumData]); - useEffect(() => { - saveAudioAnalysisPreferences({ - colorScheme, - freqScale, - fftSize: Number(fftSize), - windowFunction, - }); - }, [colorScheme, freqScale, fftSize, windowFunction]); - useEffect(() => { - const canvas = canvasRef.current; - if (!canvas) - return; - const ctx = canvas.getContext("2d"); - if (!ctx) - return; - let canceled = false; - const shouldCancel = () => canceled; - if (spectrumData) { - void renderSpectrogramToCanvas(canvas, { - spectrumData, - sampleRate, - duration, - freqScale, - colorScheme, - fileName, - shouldCancel, - }); - } - else { - ctx.fillStyle = "#000000"; - ctx.fillRect(0, 0, CANVAS_W, CANVAS_H); - ctx.fillStyle = "#444444"; - ctx.font = "16px Arial"; - ctx.textAlign = "center"; - ctx.fillText("No spectrum data", CANVAS_W / 2, CANVAS_H / 2); - } - return () => { - canceled = true; - }; - }, [spectrumData, sampleRate, duration, freqScale, colorScheme, fileName]); - const handleReAnalyze = (newFftSize: string, newWindowFunc: string) => { - setFftSize(newFftSize); - setWindowFunction(newWindowFunc as WindowFunction); - if (onReAnalyze) { - onReAnalyze(parseInt(newFftSize, 10), newWindowFunc); - } - }; - const spectrumPercent = Math.round(Math.max(0, Math.min(100, spectrumProgress?.percent ?? 0))); - return (
-
-
- - -
- -
- -
- - -
- -
- - -
- -
- - -
-
- -
- {isAnalyzingSpectrum && (
-
-
- Processing... - {spectrumPercent}% -
- -
-
)} - -
-
); -}); diff --git a/frontend/src/components/SupportPage.tsx b/frontend/src/components/SupportPage.tsx deleted file mode 100644 index 3811e9e..0000000 --- a/frontend/src/components/SupportPage.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { useState } from "react"; -import { CircleCheck, Copy } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { openExternal } from "@/lib/utils"; -import KofiLogo from "@/assets/ko-fi.gif"; -import KofiSvg from "@/assets/kofi_symbol.svg"; -import PatreonLogo from "@/assets/patreon.svg"; -import PatreonSymbol from "@/assets/patreon_symbol.svg"; -import UsdtBarcode from "@/assets/usdt.jpg"; - -export function SupportPage() { - const [copiedUsdt, setCopiedUsdt] = useState(false); - const [copiedEmail, setCopiedEmail] = useState(false); - return (
-
-

Support Me

-
- -
-
-
-
-
- Ko-fi -
-

Support via Ko-fi

-

- Buy me a coffee to help keep development going. -

-
- -
- -
-
-
- Patreon -
-

Support via Patreon

-

- Join on Patreon to help fund the project and follow updates. -

-
- -
- -
-
-
-
- USDT Barcode -
-
-

USDT (TRC20)

-

- Prefer crypto? Use the QR code or wallet address below. -

-
-
- - THnzAAwZgp2Sq5CAXLP2njQDhTvgZG9EWs - - -
-
-
- -
- If you have any questions or need help with donating, feel free to reach out via{" "} - {" "} - or{" "} - - . -
-
-
); -} diff --git a/frontend/src/components/TitleBar.tsx b/frontend/src/components/TitleBar.tsx deleted file mode 100644 index 992ebda..0000000 --- a/frontend/src/components/TitleBar.tsx +++ /dev/null @@ -1,197 +0,0 @@ -import { X, Minus, Maximize, SlidersHorizontal, Globe, Eye, EyeOff } from "lucide-react"; -import { WindowMinimise, WindowToggleMaximise, Quit } from "../../wailsjs/runtime/runtime"; -import { Menubar, MenubarContent, MenubarMenu, MenubarItem, MenubarTrigger, MenubarLabel, MenubarSeparator } from "@/components/ui/menubar"; -import { Slider } from "@/components/ui/slider"; -import { getSettings, updateSettings } from "@/lib/settings"; -import { PREVIEW_VOLUME_CHANGED_EVENT } from "@/lib/preview"; -import { fetchCurrentIPInfo } from "@/lib/api"; -import type { CurrentIPInfo } from "@/types/api"; -import { openExternal } from "@/lib/utils"; -import { useEffect, useRef, useState } from "react"; -const IP_INFO_REFRESH_INTERVAL_MS = 30000; -const SPOTIFY_BLOCKED_COUNTRY_CODES = new Set([ - "AF", - "IO", - "CF", - "CN", - "CU", - "ER", - "IR", - "MM", - "KP", - "RU", - "SO", - "SS", - "SD", - "SY", - "TM", - "YE", -]); -interface SettingsUpdatedDetail { - previewVolume?: number; -} -export function TitleBar() { - const initialSettings = getSettings(); - const [previewVolume, setPreviewVolume] = useState(initialSettings.previewVolume ?? 100); - const [currentIPInfo, setCurrentIPInfo] = useState(null); - const [isLoadingCurrentIPInfo, setIsLoadingCurrentIPInfo] = useState(false); - const [currentIPInfoError, setCurrentIPInfoError] = useState(""); - const [showIPAddress, setShowIPAddress] = useState(false); - const currentIPInfoRef = useRef(null); - useEffect(() => { - currentIPInfoRef.current = currentIPInfo; - }, [currentIPInfo]); - useEffect(() => { - const handleSettingsUpdate = (event: Event) => { - const updatedSettings = (event as CustomEvent).detail; - if (updatedSettings && typeof updatedSettings.previewVolume === "number") { - setPreviewVolume(updatedSettings.previewVolume); - } - }; - window.addEventListener("settingsUpdated", handleSettingsUpdate); - return () => window.removeEventListener("settingsUpdated", handleSettingsUpdate); - }, []); - const loadCurrentIPInfo = async (options?: { - silent?: boolean; - }) => { - const silent = options?.silent ?? false; - if (!silent) { - setIsLoadingCurrentIPInfo(true); - setCurrentIPInfoError(""); - } - try { - const info = await fetchCurrentIPInfo(); - setCurrentIPInfo(info); - setCurrentIPInfoError(""); - } - catch (error) { - if (!silent || !currentIPInfoRef.current) { - setCurrentIPInfo(null); - setCurrentIPInfoError(error instanceof Error ? error.message : "Unable to detect IP"); - } - } - finally { - if (!silent) { - setIsLoadingCurrentIPInfo(false); - } - } - }; - useEffect(() => { - void loadCurrentIPInfo(); - }, []); - useEffect(() => { - const intervalId = window.setInterval(() => { - void loadCurrentIPInfo({ silent: true }); - }, IP_INFO_REFRESH_INTERVAL_MS); - const handleFocus = () => { - if (document.visibilityState === "hidden") { - return; - } - void loadCurrentIPInfo({ silent: true }); - }; - window.addEventListener("focus", handleFocus); - document.addEventListener("visibilitychange", handleFocus); - return () => { - window.clearInterval(intervalId); - window.removeEventListener("focus", handleFocus); - document.removeEventListener("visibilitychange", handleFocus); - }; - }, []); - const handleMinimize = () => { - WindowMinimise(); - }; - const handleMaximize = () => { - WindowToggleMaximise(); - }; - const handleClose = () => { - Quit(); - }; - const handlePreviewVolumeChange = (value: number[]) => { - const nextValue = value[0]; - if (typeof nextValue !== "number" || Number.isNaN(nextValue)) { - return; - } - setPreviewVolume(nextValue); - window.dispatchEvent(new CustomEvent(PREVIEW_VOLUME_CHANGED_EVENT, { detail: nextValue })); - }; - const handlePreviewVolumeCommit = (value: number[]) => { - const nextValue = value[0]; - if (typeof nextValue !== "number" || Number.isNaN(nextValue)) { - return; - } - setPreviewVolume(nextValue); - void updateSettings({ previewVolume: nextValue }); - }; - const detectedCountryCode = currentIPInfo?.country_code?.toUpperCase() || ""; - const detectedFlagPath = detectedCountryCode ? `/assets/flags/${detectedCountryCode.toLowerCase()}.svg` : ""; - const isSpotifyBlockedCountry = detectedCountryCode !== "" && SPOTIFY_BLOCKED_COUNTRY_CODES.has(detectedCountryCode); - return (<> - -
- - -
- - - - - - -
-
- Preview Volume - - {previewVolume}% - -
- -
- -
- Network - {isSpotifyBlockedCountry && ( - (Blocked by Spotify) - )} -
-
-
-
- {detectedFlagPath ? ({detectedCountryCode}) : ()} - - {isLoadingCurrentIPInfo - ? "Detecting..." - : currentIPInfo - ? showIPAddress - ? `${currentIPInfo.ip} - ${currentIPInfo.country}${detectedCountryCode ? ` (${detectedCountryCode})` : ""}` - : `${currentIPInfo.country}${detectedCountryCode ? ` (${detectedCountryCode})` : ""}` - : "Unavailable"} - -
- {currentIPInfo && !isLoadingCurrentIPInfo && ()} -
- {!isLoadingCurrentIPInfo && !currentIPInfo && currentIPInfoError && (
- IP detection unavailable -
)} -
- - openExternal("https://afkarxyz.fyi")} className="gap-2"> - - Website - -
-
-
- - - -
- ); -} diff --git a/frontend/src/components/TrackInfo.tsx b/frontend/src/components/TrackInfo.tsx deleted file mode 100644 index 4ea8e7a..0000000 --- a/frontend/src/components/TrackInfo.tsx +++ /dev/null @@ -1,190 +0,0 @@ -import { Button } from "@/components/ui/button"; -import { Card, CardContent } from "@/components/ui/card"; -import { Download, FolderOpen, CheckCircle, XCircle, FileText, FileCheck, Globe, ImageDown, Play, Pause } from "lucide-react"; -import { Spinner } from "@/components/ui/spinner"; -import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; -import type { TrackMetadata, TrackAvailability } from "@/types/api"; -import { usePreview } from "@/hooks/usePreview"; -import { AvailabilityLinks, hasAvailabilityLinks } from "./AvailabilityLinks"; -import { buildClickableArtists } from "@/lib/artist-links"; -interface TrackInfoProps { - track: TrackMetadata & { - album_name: string; - release_date: string; - }; - isDownloading: boolean; - downloadingTrack: string | null; - isDownloaded: boolean; - isFailed: boolean; - isSkipped: boolean; - downloadingLyricsTrack?: string | null; - downloadedLyrics?: boolean; - failedLyrics?: boolean; - skippedLyrics?: boolean; - checkingAvailability?: boolean; - availability?: TrackAvailability; - downloadingCover?: boolean; - downloadedCover?: boolean; - failedCover?: boolean; - skippedCover?: boolean; - onDownload: (id: string, name: string, artists: string, albumName?: string, spotifyId?: string, playlistName?: string, durationMs?: number, position?: number, albumArtist?: string, releaseDate?: string, coverUrl?: string, spotifyTrackNumber?: number, spotifyDiscNumber?: number, spotifyTotalTracks?: number, spotifyTotalDiscs?: number, copyright?: string, publisher?: string) => void; - onDownloadLyrics?: (spotifyId: string, name: string, artists: string, albumName?: string, albumArtist?: string, releaseDate?: string, discNumber?: number) => void; - onCheckAvailability?: (spotifyId: string) => void; - onDownloadCover?: (coverUrl: string, trackName: string, artistName: string, albumName?: string, playlistName?: string, position?: number, trackId?: string, albumArtist?: string, releaseDate?: string, discNumber?: number) => void; - onOpenFolder: () => void; - onAlbumClick?: (album: { - id: string; - name: string; - external_urls: string; - }) => void; - onArtistClick?: (artist: { - id: string; - name: string; - external_urls: string; - }) => void; - onBack?: () => void; -} -export function TrackInfo({ track, isDownloading, downloadingTrack, isDownloaded, isFailed, isSkipped, downloadingLyricsTrack, downloadedLyrics, failedLyrics, skippedLyrics, checkingAvailability, availability, downloadingCover, downloadedCover, failedCover, skippedCover, onDownload, onDownloadLyrics, onCheckAvailability, onDownloadCover, onOpenFolder, onAlbumClick, onArtistClick, onBack, }: TrackInfoProps) { - const { playPreview, loadingPreview, playingTrack } = usePreview(); - const hasAlbumClick = !!(onAlbumClick && track.album_id && track.album_url); - const clickableArtists = buildClickableArtists(track.artists, track.artists_data, track.artist_id, track.artist_url); - const formatDuration = (ms: number) => { - const minutes = Math.floor(ms / 60000); - const seconds = Math.floor((ms % 60000) / 1000); - return `${minutes}:${seconds.toString().padStart(2, "0")}`; - }; - const formatPlays = (plays: string) => { - const num = parseInt(plays, 10); - if (isNaN(num)) - return plays; - return num.toLocaleString(); - }; - return ( - {onBack && (
- -
)} - -
-
- {track.images && (
- {track.name} -
- {formatDuration(track.duration_ms)} -
-
)} -
-
-
-
-

{track.name}

- {track.is_explicit && (E)} - {isSkipped ? () : isDownloaded ? () : isFailed ? () : null} -
-

- {clickableArtists.length > 0 ? clickableArtists.map((artist, index) => ( - {onArtistClick ? ( onArtistClick({ - id: artist.id, - name: artist.name, - external_urls: artist.external_urls, - })}> - {artist.name} - ) : (artist.name)} - {index < clickableArtists.length - 1 && ", "} - )) : track.artists} -

-
-
-
-
-

Album

-

{hasAlbumClick ? ( onAlbumClick?.({ - id: track.album_id!, - name: track.album_name, - external_urls: track.album_url!, - })}> - {track.album_name} - ) : (track.album_name)}

-
- {track.plays && (
-

Total Plays

-

{formatPlays(track.plays)}

-
)} -
-
-
-

Release Date

-

{track.release_date}

-
- {track.copyright && (
-

Copyright

-

- {track.copyright} -

-
)} -
-
- {track.spotify_id && (
- - {track.spotify_id && ( - - - - -

{playingTrack === track.spotify_id ? "Stop Preview" : "Play Preview"}

-
-
)} - {track.spotify_id && onDownloadLyrics && ( - - - - -

Download Separate Lyric

-
-
)} - {track.images && onDownloadCover && ( - - - - -

Download Separate Cover

-
-
)} - {track.spotify_id && onCheckAvailability && ( - - - - - - - )} - {isDownloaded && ( - - - - -

Open Folder

-
-
)} -
)} -
-
-
-
); -} diff --git a/frontend/src/components/TrackList.tsx b/frontend/src/components/TrackList.tsx deleted file mode 100644 index c161814..0000000 --- a/frontend/src/components/TrackList.tsx +++ /dev/null @@ -1,384 +0,0 @@ -import { Button } from "@/components/ui/button"; -import { Checkbox } from "@/components/ui/checkbox"; -import { Download, CheckCircle, XCircle, FileCheck, FileText, Globe, ImageDown, Play, Pause } from "lucide-react"; -import { Spinner } from "@/components/ui/spinner"; -import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; -import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, } from "@/components/ui/pagination"; -import type { TrackMetadata, TrackAvailability } from "@/types/api"; -import { usePreview } from "@/hooks/usePreview"; -import { AvailabilityLinks, hasAvailabilityLinks } from "./AvailabilityLinks"; -import { buildClickableArtists } from "@/lib/artist-links"; -interface TrackListProps { - tracks: TrackMetadata[]; - searchQuery: string; - sortBy: string; - selectedTracks: string[]; - downloadedTracks: Set; - failedTracks: Set; - skippedTracks: Set; - downloadingTrack: string | null; - isDownloading: boolean; - currentPage: number; - itemsPerPage: number; - showCheckboxes?: boolean; - hideAlbumColumn?: boolean; - folderName?: string; - isArtistDiscography?: boolean; - downloadedLyrics?: Set; - failedLyrics?: Set; - skippedLyrics?: Set; - downloadingLyricsTrack?: string | null; - checkingAvailabilityTrack?: string | null; - availabilityMap?: Map; - downloadedCovers?: Set; - failedCovers?: Set; - skippedCovers?: Set; - downloadingCoverTrack?: string | null; - onToggleTrack: (id: string) => void; - onToggleSelectAll: (tracks: TrackMetadata[]) => void; - onDownloadTrack: (id: string, name: string, artists: string, albumName: string, spotifyId?: string, folderName?: string, durationMs?: number, position?: number, albumArtist?: string, releaseDate?: string, coverUrl?: string, spotifyTrackNumber?: number, spotifyDiscNumber?: number, spotifyTotalTracks?: number, spotifyTotalDiscs?: number, copyright?: string, publisher?: string) => void; - onDownloadLyrics?: (spotifyId: string, name: string, artists: string, albumName: string, folderName?: string, isArtistDiscography?: boolean, position?: number, albumArtist?: string, releaseDate?: string, discNumber?: number) => void; - onCheckAvailability?: (spotifyId: string) => void; - onDownloadCover?: (coverUrl: string, trackName: string, artistName: string, albumName: string, folderName?: string, isArtistDiscography?: boolean, position?: number, trackId?: string, albumArtist?: string, releaseDate?: string, discNumber?: number) => void; - onPageChange: (page: number) => void; - onAlbumClick?: (album: { - id: string; - name: string; - external_urls: string; - }) => void; - onArtistClick?: (artist: { - id: string; - name: string; - external_urls: string; - }) => void; - onTrackClick?: (track: TrackMetadata) => void; -} -export function TrackList({ tracks, searchQuery, sortBy, selectedTracks, downloadedTracks, failedTracks, skippedTracks, downloadingTrack, isDownloading, currentPage, itemsPerPage, showCheckboxes = false, hideAlbumColumn = false, folderName, isArtistDiscography = false, downloadedLyrics, failedLyrics, skippedLyrics, downloadingLyricsTrack, checkingAvailabilityTrack, availabilityMap, downloadedCovers, failedCovers, skippedCovers, downloadingCoverTrack, onToggleTrack, onToggleSelectAll, onDownloadTrack, onDownloadLyrics, onCheckAvailability, onDownloadCover, onPageChange, onAlbumClick, onArtistClick, onTrackClick, }: TrackListProps) { - const { playPreview, loadingPreview, playingTrack } = usePreview(); - let filteredTracks = tracks.filter((track) => { - if (!searchQuery) - return true; - const query = searchQuery.toLowerCase(); - return (track.name.toLowerCase().includes(query) || - track.artists.toLowerCase().includes(query) || - track.album_name.toLowerCase().includes(query)); - }); - if (sortBy === "title-asc") { - filteredTracks = [...filteredTracks].sort((a, b) => a.name.localeCompare(b.name)); - } - else if (sortBy === "title-desc") { - filteredTracks = [...filteredTracks].sort((a, b) => b.name.localeCompare(a.name)); - } - else if (sortBy === "artist-asc") { - filteredTracks = [...filteredTracks].sort((a, b) => a.artists.localeCompare(b.artists)); - } - else if (sortBy === "artist-desc") { - filteredTracks = [...filteredTracks].sort((a, b) => b.artists.localeCompare(a.artists)); - } - else if (sortBy === "duration-asc") { - filteredTracks = [...filteredTracks].sort((a, b) => a.duration_ms - b.duration_ms); - } - else if (sortBy === "duration-desc") { - filteredTracks = [...filteredTracks].sort((a, b) => b.duration_ms - a.duration_ms); - } - else if (sortBy === "plays-asc") { - filteredTracks = [...filteredTracks].sort((a, b) => { - const aPlays = a.plays ? parseInt(a.plays, 10) : 0; - const bPlays = b.plays ? parseInt(b.plays, 10) : 0; - if (isNaN(aPlays)) - return 1; - if (isNaN(bPlays)) - return -1; - return aPlays - bPlays; - }); - } - else if (sortBy === "plays-desc") { - filteredTracks = [...filteredTracks].sort((a, b) => { - const aPlays = a.plays ? parseInt(a.plays, 10) : 0; - const bPlays = b.plays ? parseInt(b.plays, 10) : 0; - if (isNaN(aPlays)) - return 1; - if (isNaN(bPlays)) - return -1; - return bPlays - aPlays; - }); - } - else if (sortBy === "downloaded") { - filteredTracks = [...filteredTracks].sort((a, b) => { - const aDownloaded = a.spotify_id ? downloadedTracks.has(a.spotify_id) : false; - const bDownloaded = b.spotify_id ? downloadedTracks.has(b.spotify_id) : false; - return (bDownloaded ? 1 : 0) - (aDownloaded ? 1 : 0); - }); - } - else if (sortBy === "not-downloaded") { - filteredTracks = [...filteredTracks].sort((a, b) => { - const aDownloaded = a.spotify_id ? downloadedTracks.has(a.spotify_id) : false; - const bDownloaded = b.spotify_id ? downloadedTracks.has(b.spotify_id) : false; - return (aDownloaded ? 1 : 0) - (bDownloaded ? 1 : 0); - }); - } - else if (sortBy === "failed") { - filteredTracks = [...filteredTracks].sort((a, b) => { - const aFailed = a.spotify_id ? failedTracks.has(a.spotify_id) : false; - const bFailed = b.spotify_id ? failedTracks.has(b.spotify_id) : false; - return (bFailed ? 1 : 0) - (aFailed ? 1 : 0); - }); - } - const totalPages = Math.ceil(filteredTracks.length / itemsPerPage); - const startIndex = (currentPage - 1) * itemsPerPage; - const endIndex = startIndex + itemsPerPage; - const paginatedTracks = filteredTracks.slice(startIndex, endIndex); - const getPaginationPages = (current: number, total: number): (number | 'ellipsis')[] => { - if (total <= 10) { - return Array.from({ length: total }, (_, i) => i + 1); - } - const pages: (number | 'ellipsis')[] = []; - pages.push(1); - if (current <= 7) { - for (let i = 2; i <= 10; i++) { - pages.push(i); - } - pages.push('ellipsis'); - pages.push(total); - } - else if (current >= total - 7) { - pages.push('ellipsis'); - for (let i = total - 9; i <= total; i++) { - pages.push(i); - } - } - else { - pages.push('ellipsis'); - pages.push(current - 1); - pages.push(current); - pages.push(current + 1); - pages.push('ellipsis'); - pages.push(total); - } - return pages; - }; - const tracksWithId = filteredTracks.filter((track) => track.spotify_id); - const allSelected = tracksWithId.length > 0 && - tracksWithId.every((track) => selectedTracks.includes(track.spotify_id!)); - const formatDuration = (ms: number) => { - const minutes = Math.floor(ms / 60000); - const seconds = Math.floor((ms % 60000) / 1000); - return `${minutes}:${seconds.toString().padStart(2, "0")}`; - }; - const formatPlays = (plays: string | undefined) => { - if (!plays) - return ""; - const num = parseInt(plays, 10); - if (isNaN(num)) - return plays; - return num.toLocaleString(); - }; - const getAvailabilityButtonIcon = (spotifyId?: string) => { - if (!spotifyId) { - return ; - } - if (checkingAvailabilityTrack === spotifyId) { - return ; - } - const availability = availabilityMap?.get(spotifyId); - if (!availability) { - return ; - } - if (hasAvailabilityLinks(availability)) { - return ; - } - return ; - }; - return (
-
-
- - - - {showCheckboxes && ()} - - - {!hideAlbumColumn && ()} - - - - - - - {paginatedTracks.map((track, index) => ( - {showCheckboxes && ()} - - - {!hideAlbumColumn && ()} - - - - ))} - -
- onToggleSelectAll(filteredTracks)}/> - - # - - Title - - Album - - Duration - - Plays - - Actions -
- {track.spotify_id && ( onToggleTrack(track.spotify_id!)}/>)} - -
- {startIndex + index + 1} - {track.status && (track.status === "UP" || track.status === "DOWN" || track.status === "NEW") && ( - {track.status === "NEW" ? "●" : track.status === "UP" ? "▲" : "▼"} - )} -
-
-
- {track.images && ({track.name})} -
-
- {onTrackClick ? ( onTrackClick(track)}> - {track.name} - ) : ({track.name})} - {track.is_explicit && (E)} - - {track.spotify_id && skippedTracks.has(track.spotify_id) ? () : track.spotify_id && downloadedTracks.has(track.spotify_id) ? () : track.spotify_id && failedTracks.has(track.spotify_id) ? () : null} -
- - {(() => { - const clickableArtists = buildClickableArtists(track.artists, track.artists_data, track.artist_id, track.artist_url); - if (clickableArtists.length === 0) { - return track.artists; - } - return clickableArtists.map((artist, i) => ( - {onArtistClick ? ( onArtistClick({ - id: artist.id, - name: artist.name, - external_urls: artist.external_urls, - })}> - {artist.name} - ) : (artist.name)} - {i < clickableArtists.length - 1 && ", "} - )); - })()} - -
-
-
- {onAlbumClick && track.album_id && track.album_url ? ( onAlbumClick({ - id: track.album_id!, - name: track.album_name, - external_urls: track.album_url!, - })}> - {track.album_name} - ) : (track.album_name)} - - {formatDuration(track.duration_ms)} - - {track.plays ? formatPlays(track.plays) : ""} - -
- {track.spotify_id && ( - - - - - {downloadingTrack === track.spotify_id ? (

Downloading...

) : skippedTracks.has(track.spotify_id) ? (

Already exists

) : downloadedTracks.has(track.spotify_id) ? (

Downloaded

) : failedTracks.has(track.spotify_id) ? (

Failed

) : (

Download Track

)} -
-
)} - {track.spotify_id && ( - - - - -

{playingTrack === track.spotify_id ? "Stop Preview" : "Play Preview"}

-
-
)} - {track.spotify_id && onDownloadLyrics && ( - - - - -

Download Separate Lyric

-
-
)} - {track.images && onDownloadCover && ( - - - - -

Download Separate Cover

-
-
)} - {track.spotify_id && onCheckAvailability && ( - - - - - - - )} -
-
-
-
- - {totalPages > 1 && ( - - - { - e.preventDefault(); - if (currentPage > 1) - onPageChange(currentPage - 1); - }} className={currentPage === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}/> - - - {getPaginationPages(currentPage, totalPages).map((page, index) => (page === 'ellipsis' ? ( - - ) : ( - { - e.preventDefault(); - onPageChange(page); - }} isActive={currentPage === page} className="cursor-pointer"> - {page} - - )))} - - - { - e.preventDefault(); - if (currentPage < totalPages) - onPageChange(currentPage + 1); - }} className={currentPage === totalPages - ? "pointer-events-none opacity-50" - : "cursor-pointer"}/> - - - )} -
); -} diff --git a/frontend/src/components/ui/activity.tsx b/frontend/src/components/ui/activity.tsx deleted file mode 100644 index 1cde669..0000000 --- a/frontend/src/components/ui/activity.tsx +++ /dev/null @@ -1,63 +0,0 @@ -'use client'; -import type { Variants } from 'motion/react'; -import type { HTMLAttributes } from 'react'; -import { forwardRef, useCallback, useImperativeHandle, useRef } from 'react'; -import { motion, useAnimation } from 'motion/react'; -import { cn } from '@/lib/utils'; -export interface ActivityIconHandle { - startAnimation: () => void; - stopAnimation: () => void; -} -interface ActivityIconProps extends HTMLAttributes { - size?: number; -} -const PATH_VARIANTS: Variants = { - normal: { - pathLength: 1, - opacity: 1, - pathOffset: 0, - }, - animate: { - pathLength: [0, 1], - opacity: [0, 1], - pathOffset: [1, 0], - transition: { - duration: 0.8, - ease: 'easeInOut', - }, - }, -}; -const ActivityIcon = forwardRef(({ onMouseEnter, onMouseLeave, className, size = 28, ...props }, ref) => { - const controls = useAnimation(); - const isControlledRef = useRef(false); - useImperativeHandle(ref, () => { - isControlledRef.current = true; - return { - startAnimation: () => controls.start('animate'), - stopAnimation: () => controls.start('normal'), - }; - }); - const handleMouseEnter = useCallback((e: React.MouseEvent) => { - if (!isControlledRef.current) { - controls.start('animate'); - } - else { - onMouseEnter?.(e); - } - }, [controls, onMouseEnter]); - const handleMouseLeave = useCallback((e: React.MouseEvent) => { - if (!isControlledRef.current) { - controls.start('normal'); - } - else { - onMouseLeave?.(e); - } - }, [controls, onMouseLeave]); - return (
- - - -
); -}); -ActivityIcon.displayName = 'ActivityIcon'; -export { ActivityIcon }; diff --git a/frontend/src/components/ui/audio-lines.tsx b/frontend/src/components/ui/audio-lines.tsx deleted file mode 100644 index 0040347..0000000 --- a/frontend/src/components/ui/audio-lines.tsx +++ /dev/null @@ -1,87 +0,0 @@ -"use client"; -import { motion, useAnimation } from "motion/react"; -import type { HTMLAttributes } from "react"; -import { forwardRef, useCallback, useImperativeHandle, useRef } from "react"; -import { cn } from "@/lib/utils"; -export interface AudioLinesIconHandle { - startAnimation: () => void; - stopAnimation: () => void; -} -interface AudioLinesIconProps extends HTMLAttributes { - size?: number; -} -const AudioLinesIcon = forwardRef(({ onMouseEnter, onMouseLeave, className, size = 28, ...props }, ref) => { - const controls = useAnimation(); - const isControlledRef = useRef(false); - useImperativeHandle(ref, () => { - isControlledRef.current = true; - return { - startAnimation: () => controls.start("animate"), - stopAnimation: () => controls.start("normal"), - }; - }); - const handleMouseEnter = useCallback((e: React.MouseEvent) => { - if (isControlledRef.current) { - onMouseEnter?.(e); - } - else { - controls.start("animate"); - } - }, [controls, onMouseEnter]); - const handleMouseLeave = useCallback((e: React.MouseEvent) => { - if (isControlledRef.current) { - onMouseLeave?.(e); - } - else { - controls.start("normal"); - } - }, [controls, onMouseLeave]); - return (
- - - - - - - - -
); -}); -AudioLinesIcon.displayName = "AudioLinesIcon"; -export { AudioLinesIcon }; diff --git a/frontend/src/components/ui/badge.tsx b/frontend/src/components/ui/badge.tsx deleted file mode 100644 index 569cbdd..0000000 --- a/frontend/src/components/ui/badge.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from "react"; -import { Slot } from "@radix-ui/react-slot"; -import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils"; -const badgeVariants = cva("inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", { - variants: { - variant: { - default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", - secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", - destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", - outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", - }, - }, - defaultVariants: { - variant: "default", - }, -}); -function Badge({ className, variant, asChild = false, ...props }: React.ComponentProps<"span"> & VariantProps & { - asChild?: boolean; -}) { - const Comp = asChild ? Slot : "span"; - return (); -} -export { Badge, badgeVariants }; diff --git a/frontend/src/components/ui/blocks-icon.tsx b/frontend/src/components/ui/blocks-icon.tsx deleted file mode 100644 index b7d7029..0000000 --- a/frontend/src/components/ui/blocks-icon.tsx +++ /dev/null @@ -1,53 +0,0 @@ -"use client"; -import type { Variants } from "motion/react"; -import { motion, useAnimation } from "motion/react"; -import type { HTMLAttributes } from "react"; -import { forwardRef, useCallback, useImperativeHandle, useRef } from "react"; -import { cn } from "@/lib/utils"; -export interface BlocksIconHandle { - startAnimation: () => void; - stopAnimation: () => void; -} -interface BlocksIconProps extends HTMLAttributes { - size?: number; - loop?: boolean; -} -const VARIANTS: Variants = { - normal: { translateX: 0, translateY: 0 }, - animate: { translateX: -4, translateY: 4 }, -}; -const BlocksIcon = forwardRef(({ onMouseEnter, onMouseLeave, className, size = 28, loop = false, ...props }, ref) => { - const controls = useAnimation(); - const isControlledRef = useRef(false); - useImperativeHandle(ref, () => { - isControlledRef.current = true; - return { - startAnimation: () => controls.start("animate"), - stopAnimation: () => controls.start("normal"), - }; - }); - const handleMouseEnter = useCallback((e: React.MouseEvent) => { - if (isControlledRef.current) { - onMouseEnter?.(e); - } - else { - controls.start("animate"); - } - }, [controls, onMouseEnter]); - const handleMouseLeave = useCallback((e: React.MouseEvent) => { - if (isControlledRef.current) { - onMouseLeave?.(e); - } - else { - controls.start("normal"); - } - }, [controls, onMouseLeave]); - return (
- - - - -
); -}); -BlocksIcon.displayName = "BlocksIcon"; -export { BlocksIcon }; diff --git a/frontend/src/components/ui/bug-report-icon.tsx b/frontend/src/components/ui/bug-report-icon.tsx deleted file mode 100644 index 463f9ff..0000000 --- a/frontend/src/components/ui/bug-report-icon.tsx +++ /dev/null @@ -1,132 +0,0 @@ -"use client"; - -import type { Transition, Variants } from "motion/react"; -import { AnimatePresence, motion } from "motion/react"; -import { useEffect, useState, type HTMLAttributes } from "react"; -import { cn } from "@/lib/utils"; - -type ReportIconMode = "bug" | "bulb"; - -interface BugReportIconProps extends HTMLAttributes { - size?: number; - loop?: boolean; -} - -const LOOP_INTERVAL_MS = 2200; - -const GROUP_VARIANTS: Variants = { - hidden: { - opacity: 0, - }, - visible: { - opacity: 1, - transition: { - duration: 0.2, - ease: [0, 0, 0.2, 1], - }, - }, - exit: { - opacity: 0, - transition: { - duration: 0.18, - ease: [0.4, 0, 1, 1], - }, - }, -}; - -const DRAW_VARIANTS: Variants = { - hidden: { - pathLength: 0, - opacity: 0, - }, - visible: { - pathLength: 1, - opacity: 1, - }, - exit: { - pathLength: 1, - opacity: 0, - }, -}; - -function createDrawTransition(delay = 0, duration = 0.36): Transition { - return { - duration, - delay, - ease: [0.4, 0, 0.2, 1], - opacity: { delay }, - }; -} - -function BugPaths() { - return (<> - - - - - - - - - - - - ); -} - -function BulbPaths() { - return (<> - - - - ); -} - -function ReportIconGroup({ mode }: { mode: ReportIconMode }) { - return ( - {mode === "bug" ? : } - ); -} - -function StaticBugIcon() { - return ( - - - - - - - - - - - - ); -} - -function BugReportIcon({ className, size = 28, loop = false, ...props }: BugReportIconProps) { - const [mode, setMode] = useState("bug"); - - useEffect(() => { - if (!loop) { - setMode("bug"); - return; - } - - const intervalId = window.setInterval(() => { - setMode((currentMode) => currentMode === "bug" ? "bulb" : "bug"); - }, LOOP_INTERVAL_MS); - - return () => window.clearInterval(intervalId); - }, [loop]); - - return (
- - {loop ? ( - - ) : ()} - -
); -} - -export { BugReportIcon }; diff --git a/frontend/src/components/ui/button.tsx b/frontend/src/components/ui/button.tsx deleted file mode 100644 index a6bb15e..0000000 --- a/frontend/src/components/ui/button.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import * as React from "react"; -import { Slot } from "@radix-ui/react-slot"; -import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils"; -const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all cursor-pointer disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { - variants: { - variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", - destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", - outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", - secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - default: "h-9 px-4 py-2 has-[>svg]:px-3", - sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", - lg: "h-10 rounded-md px-6 has-[>svg]:px-4", - icon: "h-9 w-9 p-0", - "icon-sm": "h-8 w-8 p-0", - "icon-lg": "h-10 w-10 p-0", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, -}); -function Button({ className, variant, size, asChild = false, ...props }: React.ComponentProps<"button"> & VariantProps & { - asChild?: boolean; -}) { - const Comp = asChild ? Slot : "button"; - return (); -} -export { Button, buttonVariants }; diff --git a/frontend/src/components/ui/card.tsx b/frontend/src/components/ui/card.tsx deleted file mode 100644 index 9beb361..0000000 --- a/frontend/src/components/ui/card.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from "react"; -import { cn } from "@/lib/utils"; -function Card({ className, ...props }: React.ComponentProps<"div">) { - return (
); -} -function CardHeader({ className, ...props }: React.ComponentProps<"div">) { - return (
); -} -function CardTitle({ className, ...props }: React.ComponentProps<"div">) { - return (
); -} -function CardDescription({ className, ...props }: React.ComponentProps<"div">) { - return (
); -} -function CardAction({ className, ...props }: React.ComponentProps<"div">) { - return (
); -} -function CardContent({ className, ...props }: React.ComponentProps<"div">) { - return (
); -} -function CardFooter({ className, ...props }: React.ComponentProps<"div">) { - return (
); -} -export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, }; diff --git a/frontend/src/components/ui/checkbox.tsx b/frontend/src/components/ui/checkbox.tsx deleted file mode 100644 index 4da2c71..0000000 --- a/frontend/src/components/ui/checkbox.tsx +++ /dev/null @@ -1,13 +0,0 @@ -"use client"; -import * as React from "react"; -import * as CheckboxPrimitive from "@radix-ui/react-checkbox"; -import { CheckIcon } from "lucide-react"; -import { cn } from "@/lib/utils"; -function Checkbox({ className, ...props }: React.ComponentProps) { - return ( - - - - ); -} -export { Checkbox }; diff --git a/frontend/src/components/ui/coffee.tsx b/frontend/src/components/ui/coffee.tsx deleted file mode 100644 index 0dd8da8..0000000 --- a/frontend/src/components/ui/coffee.tsx +++ /dev/null @@ -1,67 +0,0 @@ -'use client'; -import type { Variants } from 'motion/react'; -import type { HTMLAttributes } from 'react'; -import { forwardRef, useCallback, useImperativeHandle, useRef } from 'react'; -import { motion, useAnimation } from 'motion/react'; -import { cn } from '@/lib/utils'; -export interface CoffeeIconHandle { - startAnimation: () => void; - stopAnimation: () => void; -} -interface CoffeeIconProps extends HTMLAttributes { - size?: number; - loop?: boolean; -} -const PATH_VARIANTS: Variants = { - normal: { - y: 0, - opacity: 1, - }, - animate: (custom: number) => ({ - y: -3, - opacity: [0, 1, 0], - transition: { - repeat: Infinity, - duration: 1.5, - ease: 'easeInOut', - delay: 0.2 * custom, - }, - }), -}; -const CoffeeIcon = forwardRef(({ onMouseEnter, onMouseLeave, className, size = 28, loop = false, ...props }, ref) => { - const controls = useAnimation(); - const isControlledRef = useRef(false); - useImperativeHandle(ref, () => { - isControlledRef.current = true; - return { - startAnimation: () => controls.start('animate'), - stopAnimation: () => controls.start('normal'), - }; - }); - const handleMouseEnter = useCallback((e: React.MouseEvent) => { - if (!isControlledRef.current) { - controls.start('animate'); - } - else { - onMouseEnter?.(e); - } - }, [controls, onMouseEnter]); - const handleMouseLeave = useCallback((e: React.MouseEvent) => { - if (!isControlledRef.current) { - controls.start('normal'); - } - else { - onMouseLeave?.(e); - } - }, [controls, onMouseLeave]); - return (
- - - - - - -
); -}); -CoffeeIcon.displayName = 'CoffeeIcon'; -export { CoffeeIcon }; diff --git a/frontend/src/components/ui/context-menu.tsx b/frontend/src/components/ui/context-menu.tsx deleted file mode 100644 index 5a334e3..0000000 --- a/frontend/src/components/ui/context-menu.tsx +++ /dev/null @@ -1,77 +0,0 @@ -"use client"; -import * as React from "react"; -import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"; -import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"; -import { cn } from "@/lib/utils"; -function ContextMenu({ ...props }: React.ComponentProps) { - return ; -} -function ContextMenuTrigger({ ...props }: React.ComponentProps) { - return (); -} -function ContextMenuGroup({ ...props }: React.ComponentProps) { - return (); -} -function ContextMenuPortal({ ...props }: React.ComponentProps) { - return (); -} -function ContextMenuSub({ ...props }: React.ComponentProps) { - return ; -} -function ContextMenuRadioGroup({ ...props }: React.ComponentProps) { - return (); -} -function ContextMenuSubTrigger({ className, inset, children, ...props }: React.ComponentProps & { - inset?: boolean; -}) { - return ( - {children} - - ); -} -function ContextMenuSubContent({ className, ...props }: React.ComponentProps) { - return (); -} -function ContextMenuContent({ className, ...props }: React.ComponentProps) { - return ( - - ); -} -function ContextMenuItem({ className, inset, variant = "default", ...props }: React.ComponentProps & { - inset?: boolean; - variant?: "default" | "destructive"; -}) { - return (); -} -function ContextMenuCheckboxItem({ className, children, checked, ...props }: React.ComponentProps) { - return ( - - - - - - {children} - ); -} -function ContextMenuRadioItem({ className, children, ...props }: React.ComponentProps) { - return ( - - - - - - {children} - ); -} -function ContextMenuLabel({ className, inset, ...props }: React.ComponentProps & { - inset?: boolean; -}) { - return (); -} -function ContextMenuSeparator({ className, ...props }: React.ComponentProps) { - return (); -} -function ContextMenuShortcut({ className, ...props }: React.ComponentProps<"span">) { - return (); -} -export { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuCheckboxItem, ContextMenuRadioItem, ContextMenuLabel, ContextMenuSeparator, ContextMenuShortcut, ContextMenuGroup, ContextMenuPortal, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuRadioGroup, }; diff --git a/frontend/src/components/ui/dialog.tsx b/frontend/src/components/ui/dialog.tsx deleted file mode 100644 index 8c5ef4f..0000000 --- a/frontend/src/components/ui/dialog.tsx +++ /dev/null @@ -1,47 +0,0 @@ -"use client"; -import * as React from "react"; -import * as DialogPrimitive from "@radix-ui/react-dialog"; -import { XIcon } from "lucide-react"; -import { cn } from "@/lib/utils"; -function Dialog({ ...props }: React.ComponentProps) { - return ; -} -function DialogTrigger({ ...props }: React.ComponentProps) { - return ; -} -function DialogPortal({ ...props }: React.ComponentProps) { - return ; -} -function DialogClose({ ...props }: React.ComponentProps) { - return ; -} -function DialogOverlay({ className, ...props }: React.ComponentProps) { - return (); -} -function DialogContent({ className, children, showCloseButton = true, ...props }: React.ComponentProps & { - showCloseButton?: boolean; -}) { - return ( - - - {children} - {showCloseButton && ( - - Close - )} - - ); -} -function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { - return (
); -} -function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { - return (
); -} -function DialogTitle({ className, ...props }: React.ComponentProps) { - return (); -} -function DialogDescription({ className, ...props }: React.ComponentProps) { - return (); -} -export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, }; diff --git a/frontend/src/components/ui/dropdown-menu.tsx b/frontend/src/components/ui/dropdown-menu.tsx deleted file mode 100644 index c769f7e..0000000 --- a/frontend/src/components/ui/dropdown-menu.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import * as React from "react"; -import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"; -import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui"; -import { cn } from "@/lib/utils"; -function DropdownMenu({ ...props }: React.ComponentProps) { - return ; -} -function DropdownMenuPortal({ ...props }: React.ComponentProps) { - return (); -} -function DropdownMenuTrigger({ ...props }: React.ComponentProps) { - return (); -} -function DropdownMenuContent({ className, sideOffset = 4, ...props }: React.ComponentProps) { - return ( - - ); -} -function DropdownMenuGroup({ ...props }: React.ComponentProps) { - return (); -} -function DropdownMenuItem({ className, inset, variant = "default", ...props }: React.ComponentProps & { - inset?: boolean; - variant?: "default" | "destructive"; -}) { - return (); -} -function DropdownMenuCheckboxItem({ className, children, checked, ...props }: React.ComponentProps) { - return ( - - - - - - {children} - ); -} -function DropdownMenuRadioGroup({ ...props }: React.ComponentProps) { - return (); -} -function DropdownMenuRadioItem({ className, children, ...props }: React.ComponentProps) { - return ( - - - - - - {children} - ); -} -function DropdownMenuLabel({ className, inset, ...props }: React.ComponentProps & { - inset?: boolean; -}) { - return (); -} -function DropdownMenuSeparator({ className, ...props }: React.ComponentProps) { - return (); -} -function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<"span">) { - return (); -} -function DropdownMenuSub({ ...props }: React.ComponentProps) { - return ; -} -function DropdownMenuSubTrigger({ className, inset, children, ...props }: React.ComponentProps & { - inset?: boolean; -}) { - return ( - {children} - - ); -} -function DropdownMenuSubContent({ className, ...props }: React.ComponentProps) { - return (); -} -export { DropdownMenu, DropdownMenuPortal, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, }; diff --git a/frontend/src/components/ui/file-music.tsx b/frontend/src/components/ui/file-music.tsx deleted file mode 100644 index aa0d576..0000000 --- a/frontend/src/components/ui/file-music.tsx +++ /dev/null @@ -1,64 +0,0 @@ -'use client'; -import type { Variants } from 'motion/react'; -import type { HTMLAttributes } from 'react'; -import { forwardRef, useCallback, useImperativeHandle, useRef } from 'react'; -import { motion, useAnimation } from 'motion/react'; -import { cn } from '@/lib/utils'; -export interface FileMusicIconHandle { - startAnimation: () => void; - stopAnimation: () => void; -} -interface FileMusicIconProps extends HTMLAttributes { - size?: number; -} -const PATH_VARIANTS: Variants = { - normal: { - pathLength: 1, - opacity: 1, - }, - animate: { - pathLength: [0, 1], - opacity: [0, 1], - transition: { - duration: 0.6, - ease: 'easeInOut', - }, - }, -}; -const FileMusicIcon = forwardRef(({ onMouseEnter, onMouseLeave, className, size = 28, ...props }, ref) => { - const controls = useAnimation(); - const isControlledRef = useRef(false); - useImperativeHandle(ref, () => { - isControlledRef.current = true; - return { - startAnimation: () => controls.start('animate'), - stopAnimation: () => controls.start('normal'), - }; - }); - const handleMouseEnter = useCallback((e: React.MouseEvent) => { - if (!isControlledRef.current) { - controls.start('animate'); - } - else { - onMouseEnter?.(e); - } - }, [controls, onMouseEnter]); - const handleMouseLeave = useCallback((e: React.MouseEvent) => { - if (!isControlledRef.current) { - controls.start('normal'); - } - else { - onMouseLeave?.(e); - } - }, [controls, onMouseLeave]); - return (
- - - - - - -
); -}); -FileMusicIcon.displayName = 'FileMusicIcon'; -export { FileMusicIcon }; diff --git a/frontend/src/components/ui/file-pen.tsx b/frontend/src/components/ui/file-pen.tsx deleted file mode 100644 index ccc727f..0000000 --- a/frontend/src/components/ui/file-pen.tsx +++ /dev/null @@ -1,63 +0,0 @@ -'use client'; -import type { Variants } from 'motion/react'; -import type { HTMLAttributes } from 'react'; -import { forwardRef, useCallback, useImperativeHandle, useRef } from 'react'; -import { motion, useAnimation } from 'motion/react'; -import { cn } from '@/lib/utils'; -export interface FilePenIconHandle { - startAnimation: () => void; - stopAnimation: () => void; -} -interface FilePenIconProps extends HTMLAttributes { - size?: number; -} -const PATH_VARIANTS: Variants = { - normal: { - pathLength: 1, - opacity: 1, - }, - animate: { - pathLength: [0, 1], - opacity: [0, 1], - transition: { - duration: 0.6, - ease: 'easeInOut', - }, - }, -}; -const FilePenIcon = forwardRef(({ onMouseEnter, onMouseLeave, className, size = 28, ...props }, ref) => { - const controls = useAnimation(); - const isControlledRef = useRef(false); - useImperativeHandle(ref, () => { - isControlledRef.current = true; - return { - startAnimation: () => controls.start('animate'), - stopAnimation: () => controls.start('normal'), - }; - }); - const handleMouseEnter = useCallback((e: React.MouseEvent) => { - if (!isControlledRef.current) { - controls.start('animate'); - } - else { - onMouseEnter?.(e); - } - }, [controls, onMouseEnter]); - const handleMouseLeave = useCallback((e: React.MouseEvent) => { - if (!isControlledRef.current) { - controls.start('normal'); - } - else { - onMouseLeave?.(e); - } - }, [controls, onMouseLeave]); - return (
- - - - - -
); -}); -FilePenIcon.displayName = 'FilePenIcon'; -export { FilePenIcon }; diff --git a/frontend/src/components/ui/history-icon.tsx b/frontend/src/components/ui/history-icon.tsx deleted file mode 100644 index a954d37..0000000 --- a/frontend/src/components/ui/history-icon.tsx +++ /dev/null @@ -1,97 +0,0 @@ -"use client"; -import type { Transition, Variants } from "motion/react"; -import { motion, useAnimation } from "motion/react"; -import type { HTMLAttributes } from "react"; -import { forwardRef, useCallback, useImperativeHandle, useRef } from "react"; -import { cn } from "@/lib/utils"; -export interface HistoryIconHandle { - startAnimation: () => void; - stopAnimation: () => void; -} -interface HistoryIconProps extends HTMLAttributes { - size?: number; -} -const ARROW_TRANSITION: Transition = { - type: "spring", - stiffness: 250, - damping: 25, -}; -const ARROW_VARIANTS: Variants = { - normal: { - rotate: "0deg", - }, - animate: { - rotate: "-50deg", - }, -}; -const HAND_TRANSITION: Transition = { - duration: 0.6, - ease: [0.4, 0, 0.2, 1], -}; -const HAND_VARIANTS: Variants = { - normal: { - rotate: 0, - originX: "0%", - originY: "100%", - }, - animate: { - rotate: -360, - originX: "0%", - originY: "100%", - }, -}; -const MINUTE_HAND_TRANSITION: Transition = { - duration: 0.5, - ease: "easeInOut", -}; -const MINUTE_HAND_VARIANTS: Variants = { - normal: { - rotate: 0, - originX: "0%", - originY: "0%", - }, - animate: { - rotate: -45, - originX: "0%", - originY: "0%", - }, -}; -const HistoryIcon = forwardRef(({ onMouseEnter, onMouseLeave, className, size = 28, ...props }, ref) => { - const controls = useAnimation(); - const isControlledRef = useRef(false); - useImperativeHandle(ref, () => { - isControlledRef.current = true; - return { - startAnimation: () => controls.start("animate"), - stopAnimation: () => controls.start("normal"), - }; - }); - const handleMouseEnter = useCallback((e: React.MouseEvent) => { - if (isControlledRef.current) { - onMouseEnter?.(e); - } - else { - controls.start("animate"); - } - }, [controls, onMouseEnter]); - const handleMouseLeave = useCallback((e: React.MouseEvent) => { - if (isControlledRef.current) { - onMouseLeave?.(e); - } - else { - controls.start("normal"); - } - }, [controls, onMouseLeave]); - return (
- - - - - - - - -
); -}); -HistoryIcon.displayName = "HistoryIcon"; -export { HistoryIcon }; diff --git a/frontend/src/components/ui/home.tsx b/frontend/src/components/ui/home.tsx deleted file mode 100644 index 8b6eb25..0000000 --- a/frontend/src/components/ui/home.tsx +++ /dev/null @@ -1,62 +0,0 @@ -'use client'; -import type { Transition, Variants } from 'motion/react'; -import type { HTMLAttributes } from 'react'; -import { forwardRef, useCallback, useImperativeHandle, useRef } from 'react'; -import { motion, useAnimation } from 'motion/react'; -import { cn } from '@/lib/utils'; -export interface HomeIconHandle { - startAnimation: () => void; - stopAnimation: () => void; -} -interface HomeIconProps extends HTMLAttributes { - size?: number; -} -const DEFAULT_TRANSITION: Transition = { - duration: 0.6, - opacity: { duration: 0.2 }, -}; -const PATH_VARIANTS: Variants = { - normal: { - pathLength: 1, - opacity: 1, - }, - animate: { - opacity: [0, 1], - pathLength: [0, 1], - }, -}; -const HomeIcon = forwardRef(({ onMouseEnter, onMouseLeave, className, size = 28, ...props }, ref) => { - const controls = useAnimation(); - const isControlledRef = useRef(false); - useImperativeHandle(ref, () => { - isControlledRef.current = true; - return { - startAnimation: () => controls.start('animate'), - stopAnimation: () => controls.start('normal'), - }; - }); - const handleMouseEnter = useCallback((e: React.MouseEvent) => { - if (!isControlledRef.current) { - controls.start('animate'); - } - else { - onMouseEnter?.(e); - } - }, [controls, onMouseEnter]); - const handleMouseLeave = useCallback((e: React.MouseEvent) => { - if (!isControlledRef.current) { - controls.start('normal'); - } - else { - onMouseLeave?.(e); - } - }, [controls, onMouseLeave]); - return (
- - - - -
); -}); -HomeIcon.displayName = 'HomeIcon'; -export { HomeIcon }; diff --git a/frontend/src/components/ui/input-with-context.tsx b/frontend/src/components/ui/input-with-context.tsx deleted file mode 100644 index 1c3ee0e..0000000 --- a/frontend/src/components/ui/input-with-context.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import * as React from "react"; -import { Input } from "@/components/ui/input"; -import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger, } from "@/components/ui/context-menu"; -import { Scissors, Copy, Clipboard, Type } from "lucide-react"; -export interface InputWithContextProps extends React.InputHTMLAttributes { - onValueChange?: (value: string) => void; -} -const InputWithContext = React.forwardRef(({ className, type, onValueChange, onChange, ...props }, ref) => { - const inputRef = React.useRef(null); - const [hasSelection, setHasSelection] = React.useState(false); - const [canPaste, setCanPaste] = React.useState(false); - React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement); - const updateSelectionState = () => { - const input = inputRef.current; - if (!input) - return; - const start = input.selectionStart ?? 0; - const end = input.selectionEnd ?? 0; - setHasSelection(start !== end); - }; - const checkClipboard = async () => { - try { - const text = await navigator.clipboard.readText(); - setCanPaste(text.length > 0); - } - catch { - setCanPaste(false); - } - }; - const handleCut = async () => { - const input = inputRef.current; - if (!input) - return; - const start = input.selectionStart ?? 0; - const end = input.selectionEnd ?? 0; - const selectedText = input.value.substring(start, end); - if (selectedText) { - try { - await navigator.clipboard.writeText(selectedText); - const newValue = input.value.substring(0, start) + input.value.substring(end); - input.value = newValue; - input.setSelectionRange(start, start); - if (onChange) { - const event = { - target: input, - currentTarget: input, - } as React.ChangeEvent; - onChange(event); - } - if (onValueChange) { - onValueChange(newValue); - } - input.focus(); - } - catch (err) { - console.error("Failed to cut:", err); - } - } - }; - const handleCopy = async () => { - const input = inputRef.current; - if (!input) - return; - const start = input.selectionStart ?? 0; - const end = input.selectionEnd ?? 0; - const selectedText = input.value.substring(start, end); - if (selectedText) { - try { - await navigator.clipboard.writeText(selectedText); - input.focus(); - } - catch (err) { - console.error("Failed to copy:", err); - } - } - }; - const handlePaste = async () => { - const input = inputRef.current; - if (!input) - return; - try { - const text = await navigator.clipboard.readText(); - const start = input.selectionStart ?? 0; - const end = input.selectionEnd ?? 0; - const newValue = input.value.substring(0, start) + text + input.value.substring(end); - input.value = newValue; - const newPosition = start + text.length; - input.setSelectionRange(newPosition, newPosition); - if (onChange) { - const event = { - target: input, - currentTarget: input, - } as React.ChangeEvent; - onChange(event); - } - if (onValueChange) { - onValueChange(newValue); - } - input.focus(); - await checkClipboard(); - } - catch (err) { - console.error("Failed to paste:", err); - } - }; - const handleSelectAll = () => { - const input = inputRef.current; - if (!input) - return; - input.select(); - input.focus(); - updateSelectionState(); - }; - const handleInputChange = (e: React.ChangeEvent) => { - if (onChange) { - onChange(e); - } - if (onValueChange) { - onValueChange(e.target.value); - } - }; - return ( { - if (open) { - checkClipboard(); - } - }}> - - - - - - - Cut - Ctrl+X - - - - Copy - Ctrl+C - - - - Paste - Ctrl+V - - - - - Select All - Ctrl+A - - - ); -}); -InputWithContext.displayName = "InputWithContext"; -export { InputWithContext }; diff --git a/frontend/src/components/ui/input.tsx b/frontend/src/components/ui/input.tsx deleted file mode 100644 index 3a6e9b1..0000000 --- a/frontend/src/components/ui/input.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import * as React from "react"; -import { cn } from "@/lib/utils"; -function Input({ className, type, ...props }: React.ComponentProps<"input">) { - return (); -} -export { Input }; diff --git a/frontend/src/components/ui/label.tsx b/frontend/src/components/ui/label.tsx deleted file mode 100644 index e4ef7b3..0000000 --- a/frontend/src/components/ui/label.tsx +++ /dev/null @@ -1,8 +0,0 @@ -"use client"; -import * as React from "react"; -import * as LabelPrimitive from "@radix-ui/react-label"; -import { cn } from "@/lib/utils"; -function Label({ className, ...props }: React.ComponentProps) { - return (); -} -export { Label }; diff --git a/frontend/src/components/ui/menubar.tsx b/frontend/src/components/ui/menubar.tsx deleted file mode 100644 index 2dfd7f2..0000000 --- a/frontend/src/components/ui/menubar.tsx +++ /dev/null @@ -1,60 +0,0 @@ -"use client"; -import * as React from "react"; -import * as MenubarPrimitive from "@radix-ui/react-menubar"; -import { Check, ChevronRight, Circle } from "lucide-react"; -import { cn } from "@/lib/utils"; -const Menubar = React.forwardRef, React.ComponentPropsWithoutRef>(({ className, ...props }, ref) => ()); -Menubar.displayName = MenubarPrimitive.Root.displayName; -const MenubarMenu = MenubarPrimitive.Menu; -const MenubarGroup = MenubarPrimitive.Group; -const MenubarPortal = MenubarPrimitive.Portal; -const MenubarSub = MenubarPrimitive.Sub; -const MenubarRadioGroup = MenubarPrimitive.RadioGroup; -const MenubarTrigger = React.forwardRef, React.ComponentPropsWithoutRef>(({ className, ...props }, ref) => ()); -MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName; -const MenubarSubTrigger = React.forwardRef, React.ComponentPropsWithoutRef & { - inset?: boolean; -}>(({ className, inset, children, ...props }, ref) => ( - {children} - - )); -MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName; -const MenubarSubContent = React.forwardRef, React.ComponentPropsWithoutRef>(({ className, ...props }, ref) => ()); -MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName; -const MenubarContent = React.forwardRef, React.ComponentPropsWithoutRef>(({ className, align = "start", alignOffset = -4, sideOffset = 8, ...props }, ref) => ( - - )); -MenubarContent.displayName = MenubarPrimitive.Content.displayName; -const MenubarItem = React.forwardRef, React.ComponentPropsWithoutRef & { - inset?: boolean; -}>(({ className, inset, ...props }, ref) => ()); -MenubarItem.displayName = MenubarPrimitive.Item.displayName; -const MenubarCheckboxItem = React.forwardRef, React.ComponentPropsWithoutRef>(({ className, children, checked, ...props }, ref) => ( - - - - - - {children} - )); -MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName; -const MenubarRadioItem = React.forwardRef, React.ComponentPropsWithoutRef>(({ className, children, ...props }, ref) => ( - - - - - - {children} - )); -MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName; -const MenubarLabel = React.forwardRef, React.ComponentPropsWithoutRef & { - inset?: boolean; -}>(({ className, inset, ...props }, ref) => ()); -MenubarLabel.displayName = MenubarPrimitive.Label.displayName; -const MenubarSeparator = React.forwardRef, React.ComponentPropsWithoutRef>(({ className, ...props }, ref) => ()); -MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName; -const MenubarShortcut = ({ className, ...props }: React.HTMLAttributes) => { - return (); -}; -MenubarShortcut.displayname = "MenubarShortcut"; -export { Menubar, MenubarMenu, MenubarTrigger, MenubarContent, MenubarItem, MenubarSeparator, MenubarLabel, MenubarCheckboxItem, MenubarRadioGroup, MenubarRadioItem, MenubarPortal, MenubarSubContent, MenubarSubTrigger, MenubarSub, MenubarGroup, MenubarShortcut, }; diff --git a/frontend/src/components/ui/pagination.tsx b/frontend/src/components/ui/pagination.tsx deleted file mode 100644 index 0ac29c8..0000000 --- a/frontend/src/components/ui/pagination.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import * as React from "react"; -import { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon, } from "lucide-react"; -import { cn } from "@/lib/utils"; -import { Button, buttonVariants } from "@/components/ui/button"; -function Pagination({ className, ...props }: React.ComponentProps<"nav">) { - return (

?l&?!?~`d*4PTcUyOuM*4}@a?R2f`B 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