@ozdao/martyrs 0.2.495 → 0.2.497
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/index.cjs +4 -4
- package/dist/_virtual/index.js +4 -4
- package/dist/_virtual/index2.cjs +4 -4
- package/dist/_virtual/index2.js +4 -4
- package/dist/builder.cjs +43 -42
- package/dist/builder.js +45 -44
- package/dist/globals.server.cjs +13 -2
- package/dist/globals.server.js +13 -2
- package/dist/martyrs/src/components/Block/Block.vue.cjs +1 -1
- package/dist/martyrs/src/components/Block/Block.vue.js +1 -1
- package/dist/martyrs/src/components/Button/{Button.vue.cjs → Button.vue2.cjs} +2 -2
- package/dist/martyrs/src/components/Button/Button.vue2.cjs.map +1 -0
- package/dist/martyrs/src/components/Button/{Button.vue.js → Button.vue2.js} +2 -2
- package/dist/martyrs/src/components/Button/{Button.vue.cjs.map → Button.vue2.js.map} +1 -1
- package/dist/martyrs/src/components/Chips/{Chips.vue.cjs → Chips.vue2.cjs} +2 -2
- package/dist/martyrs/src/components/Chips/Chips.vue2.cjs.map +1 -0
- package/dist/martyrs/src/components/Chips/{Chips.vue.js → Chips.vue2.js} +2 -2
- package/dist/martyrs/src/components/Chips/Chips.vue2.js.map +1 -0
- package/dist/martyrs/src/components/Dropdown/{Dropdown.vue.cjs → Dropdown.vue2.cjs} +2 -2
- package/dist/martyrs/src/components/Dropdown/Dropdown.vue2.cjs.map +1 -0
- package/dist/martyrs/src/components/Dropdown/{Dropdown.vue.js → Dropdown.vue2.js} +2 -2
- package/dist/martyrs/src/components/Dropdown/{Dropdown.vue.cjs.map → Dropdown.vue2.js.map} +1 -1
- package/dist/martyrs/src/components/Feed/Feed.vue.cjs +2 -2
- package/dist/martyrs/src/components/Feed/Feed.vue.js +2 -2
- package/dist/martyrs/src/components/FieldTags/FieldTags.vue.cjs +1 -1
- package/dist/martyrs/src/components/FieldTags/FieldTags.vue.js +1 -1
- package/dist/martyrs/src/components/Select/{Select.vue2.cjs → Select.vue.cjs} +2 -2
- package/dist/martyrs/src/components/Select/{Select.vue2.js.map → Select.vue.cjs.map} +1 -1
- package/dist/martyrs/src/components/Select/{Select.vue2.js → Select.vue.js} +2 -2
- package/dist/martyrs/src/components/Select/Select.vue.js.map +1 -0
- package/dist/martyrs/src/components/Tooltip/{Tooltip.vue2.cjs → Tooltip.vue.cjs} +2 -2
- package/dist/martyrs/src/components/Tooltip/{Tooltip.vue2.js.map → Tooltip.vue.cjs.map} +1 -1
- package/dist/martyrs/src/components/Tooltip/{Tooltip.vue2.js → Tooltip.vue.js} +2 -2
- package/dist/martyrs/src/components/Tooltip/Tooltip.vue.js.map +1 -0
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.cjs +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditAccount.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditAccount.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditProfile.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditProfile.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.js +1 -1
- package/dist/martyrs/src/modules/community/components/blocks/CardBlogpost.vue.cjs +1 -1
- package/dist/martyrs/src/modules/community/components/blocks/CardBlogpost.vue.js +1 -1
- package/dist/martyrs/src/modules/community/components/layouts/Community.vue.cjs +1 -1
- package/dist/martyrs/src/modules/community/components/layouts/Community.vue.js +1 -1
- package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.cjs +2 -2
- package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.js +2 -2
- package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.cjs +2 -2
- package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.js +2 -2
- package/dist/martyrs/src/modules/events/components/blocks/CardEvent.vue.cjs +1 -1
- package/dist/martyrs/src/modules/events/components/blocks/CardEvent.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/elements/ButtonCheck.vue.cjs +1 -1
- package/dist/martyrs/src/modules/events/components/elements/ButtonCheck.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/elements/ButtonJoin.vue.cjs +1 -1
- package/dist/martyrs/src/modules/events/components/elements/ButtonJoin.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.cjs +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EditEventTickets.vue.cjs +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EditEventTickets.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/Event.vue.cjs +3 -3
- package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +3 -3
- package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.cjs +3 -3
- package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +3 -3
- package/dist/martyrs/src/modules/globals/views/classes/globals.i18n.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/classes/globals.i18n.js +1 -1
- package/dist/martyrs/src/modules/globals/views/components/blocks/CardHeader.vue.cjs +3 -3
- package/dist/martyrs/src/modules/globals/views/components/blocks/CardHeader.vue.js +3 -3
- package/dist/martyrs/src/modules/globals/views/components/blocks/PopupAuth.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/blocks/PopupAuth.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/components/blocks/PopupDateSelector.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/blocks/PopupDateSelector.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/Header.vue.cjs +2 -2
- package/dist/martyrs/src/modules/globals/views/components/partials/Header.vue.js +2 -2
- package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/NavigationBar.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/NavigationBar.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/forms/AdjustmentForm.vue.cjs +1 -1
- package/dist/martyrs/src/modules/inventory/components/forms/AdjustmentForm.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/forms/StockAlertsForm.vue.cjs +1 -1
- package/dist/martyrs/src/modules/inventory/components/forms/StockAlertsForm.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/pages/Inventory.vue.cjs +1 -1
- package/dist/martyrs/src/modules/inventory/components/pages/Inventory.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.cjs +3 -3
- package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js +3 -3
- package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.cjs +1 -1
- package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/cards/ArtistCardSmall.vue.cjs +95 -0
- package/dist/martyrs/src/modules/music/components/cards/ArtistCardSmall.vue.cjs.map +1 -0
- package/dist/martyrs/src/modules/music/components/cards/ArtistCardSmall.vue.js +95 -0
- package/dist/martyrs/src/modules/music/components/cards/ArtistCardSmall.vue.js.map +1 -0
- package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.cjs +1 -1
- package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.cjs +1 -1
- package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.cjs +2 -2
- package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.js +2 -2
- package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.cjs +2 -2
- package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.js +2 -2
- package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.cjs +1 -1
- package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.cjs +1 -1
- package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.cjs +2 -2
- package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.js +2 -2
- package/dist/martyrs/src/modules/music/components/pages/Album.vue.cjs +87 -140
- package/dist/martyrs/src/modules/music/components/pages/Album.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Album.vue.js +97 -150
- package/dist/martyrs/src/modules/music/components/pages/Album.vue.js.map +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Artist.vue.cjs +2 -2
- package/dist/martyrs/src/modules/music/components/pages/Artist.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js +2 -2
- package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js.map +1 -1
- package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.cjs +1 -1
- package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.cjs +86 -136
- package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js +102 -152
- package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js.map +1 -1
- package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.cjs +1 -1
- package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Track.vue.cjs +147 -159
- package/dist/martyrs/src/modules/music/components/pages/Track.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Track.vue.js +172 -184
- package/dist/martyrs/src/modules/music/components/pages/Track.vue.js.map +1 -1
- package/dist/martyrs/src/modules/music/components/pages/TrackCreate.vue.cjs +1 -1
- package/dist/martyrs/src/modules/music/components/pages/TrackCreate.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.cjs +14 -19
- package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.js +15 -20
- package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.js.map +1 -1
- package/dist/martyrs/src/modules/music/components/player/TrackProgress.vue.cjs +2 -2
- package/dist/martyrs/src/modules/music/components/player/TrackProgress.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/music/components/player/TrackProgress.vue.js +2 -2
- package/dist/martyrs/src/modules/music/components/player/TrackProgress.vue.js.map +1 -1
- package/dist/martyrs/src/modules/music/components/player/VolumeControl.vue.cjs +2 -2
- package/dist/martyrs/src/modules/music/components/player/VolumeControl.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/music/components/player/VolumeControl.vue.js +2 -2
- package/dist/martyrs/src/modules/music/components/player/VolumeControl.vue.js.map +1 -1
- package/dist/martyrs/src/modules/music/router/music.cjs +4 -4
- package/dist/martyrs/src/modules/music/router/music.js +4 -4
- package/dist/martyrs/src/modules/orders/components/blocks/CardOrderUser.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/blocks/CardOrderUser.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.cjs +3 -3
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js +3 -3
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormAddCustomer.vue.cjs +2 -2
- package/dist/martyrs/src/modules/orders/components/sections/FormAddCustomer.vue.js +2 -2
- package/dist/martyrs/src/modules/orders/components/sections/FormCustomerDetails.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormCustomerDetails.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.cjs +2 -2
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +2 -2
- package/dist/martyrs/src/modules/orders/components/sections/FormPayment.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormPayment.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/elements/ButtonToggleMembership.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/elements/ButtonToggleMembership.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/sections/DetailsTabSection.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/sections/DetailsTabSection.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +1 -1
- package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.cjs +1 -1
- package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.js +1 -1
- package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.cjs +2 -2
- package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/pages/views/components/partials/SidebarPages.vue.cjs +1 -1
- package/dist/martyrs/src/modules/pages/views/components/partials/SidebarPages.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/blocks/ProductDiscounts.vue.cjs +2 -2
- package/dist/martyrs/src/modules/products/components/blocks/ProductDiscounts.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.cjs +3 -3
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +3 -3
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs +2 -2
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/sections/EditAttributes.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/sections/EditAttributes.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/EditDiscounts.vue.cjs +2 -2
- package/dist/martyrs/src/modules/products/components/sections/EditDiscounts.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.cjs +2 -2
- package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/sections/ProductConfigurator.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/sections/ProductConfigurator.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/ProductsRecommended.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/sections/ProductsRecommended.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.cjs +2 -2
- package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.js +2 -2
- package/dist/martyrs/src/modules/reports/components/sections/FormReport.vue.cjs +2 -2
- package/dist/martyrs/src/modules/reports/components/sections/FormReport.vue.js +2 -2
- package/dist/martyrs/src/modules/spots/components/blocks/CardSpot.vue.cjs +1 -1
- package/dist/martyrs/src/modules/spots/components/blocks/CardSpot.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/blocks/SpotMemberModify.vue.cjs +1 -1
- package/dist/martyrs/src/modules/spots/components/blocks/SpotMemberModify.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.cjs +1 -1
- package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/Map.vue.cjs +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/Map.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.cjs +2 -2
- package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/spots/components/sections/WorktimeEdit.vue.cjs +2 -2
- package/dist/martyrs/src/modules/spots/components/sections/WorktimeEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDeposit.vue.cjs +1 -1
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDeposit.vue.js +1 -1
- package/dist/martyrs/src/modules/wallet/views/components/pages/Wallet.vue.cjs +5 -5
- package/dist/martyrs/src/modules/wallet/views/components/pages/Wallet.vue.js +5 -5
- package/dist/martyrs.css +1 -1
- package/dist/style.css +98 -81
- package/package.json +1 -1
- package/src/builder/rspack/rspack.config.ssr.client.js +41 -41
- package/src/modules/globals/controllers/classes/globals.websocket.js +11 -2
- package/src/modules/music/README.md +2 -0
- package/src/modules/music/components/cards/ArtistCardSmall.vue +92 -0
- package/src/modules/music/components/pages/Album.vue +20 -56
- package/src/modules/music/components/pages/Artist.vue +1 -1
- package/src/modules/music/components/pages/Playlist.vue +26 -44
- package/src/modules/music/components/pages/Track.vue +51 -74
- package/src/modules/music/components/player/MusicPlayer.vue +24 -21
- package/src/modules/music/components/player/TrackProgress.vue +9 -8
- package/src/modules/music/components/player/VolumeControl.vue +3 -2
- package/src/styles/base/all.scss +1 -0
- package/dist/martyrs/src/components/Button/Button.vue.js.map +0 -1
- package/dist/martyrs/src/components/Chips/Chips.vue.cjs.map +0 -1
- package/dist/martyrs/src/components/Chips/Chips.vue.js.map +0 -1
- package/dist/martyrs/src/components/Dropdown/Dropdown.vue.js.map +0 -1
- package/dist/martyrs/src/components/Select/Select.vue2.cjs.map +0 -1
- package/dist/martyrs/src/components/Tooltip/Tooltip.vue2.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Track.vue.js","sources":["../../../../../../../src/modules/music/components/pages/Track.vue"],"sourcesContent":["<!-- components/pages/Track.vue -->\n<template>\n <div class=\"track-page pd-small\">\n <!-- Loading -->\n <div v-if=\"isLoading\" class=\"w-100 h-25r flex-center flex\">\n <Loader />\n </div>\n\n <!-- Not Found -->\n <div v-if=\"hasLoaded && !track\" class=\"t-center pd-big\">\n <h2 class=\"\">Track not found</h2>\n <p class=\"t-transp t-medium\">The track you're looking for doesn't exist or has been removed.</p>\n </div>\n\n <!-- Track Content -->\n <div v-if=\"track\" class=\"track-content cols-2-fit-content mobile:cols-1 gap-big\">\n <!-- Left Column - Cover & Stats -->\n <div class=\"pos-sticky pos-t-0 mobile:pos-relative track-cover-section\">\n <!-- Cover with Play Overlay -->\n <div class=\"cover-container relative mn-b-medium radius-big overflow-hidden shadow-big\">\n <Media \n :url=\"track.coverUrl || (track.album && track.album.coverUrl) || '/logo/logo-placeholder.jpg'\" \n :alt=\"track.title\"\n class=\"aspect-1x1 w-100 radius-medium o-hidden\"\n />\n <!-- <div class=\"cover-overlay absolute inset-0 bg-black-transp-40 flex-center opacity-0 hover-opacity-100 transition\">\n <Button\n @click=\"playTrack\"\n color=\"white\"\n size=\"big\"\n class=\"w-5r h-5r radius-full shadow-big hover-scale-110\"\n >\n <IconPlay class=\"w-2r h-2r\" />\n </Button>\n </div> -->\n </div>\n\n \n\n <!-- Quick Stats -->\n <div class=\"stats-grid grid cols-2 gap-small\">\n <div class=\"stat-card bg-light pd-medium radius-medium t-center\">\n <div class=\" mn-b-thin\">{{ formatNumber(track.playCount) }}</div>\n <div class=\"t-small t-transp t-uppercase\">Plays</div>\n </div>\n <div class=\"stat-card bg-light pd-medium radius-medium t-center\">\n <div class=\" mn-b-thin\">{{ formatNumber(track.views) }}</div>\n <div class=\"t-small t-transp t-uppercase\">Views</div>\n </div>\n </div>\n </div>\n\n <!-- Right Column - Track Details -->\n <div class=\"track-details-section\">\n <!-- Track Type Badge -->\n <div class=\"flex items-center gap-small mn-b-small\">\n <span class=\"badge bg-primary-transp-20 t-primary pd-thin-big radius-small t-small t-uppercase\">Single</span>\n <span v-if=\"track.isExplicit\" class=\"badge bg-danger-transp-20 t-danger pd-thin-big radius-small t-small\">Explicit</span>\n </div>\n\n <!-- Track Title -->\n <h1 class=\"h1 mn-b-medium\">{{ track.title }}</h1>\n <!-- Action Buttons -->\n <div class=\"flex gap-small mn-b-medium\">\n <Button\n @click=\"playTrack\"\n color=\"primary\"\n size=\"medium\"\n class=\"flex-1 t-white bg-black radius-thin flex-center gap-thin\"\n >\n <IconPlay fill=\"rgb(var(--white))\" class=\"i-medium\" />\n Play\n </Button>\n\n <Button\n @click=\"addToQueue\"\n color=\"primary\"\n size=\"medium\"\n class=\"flex-1 bg-light radius-thin flex-center gap-thin\"\n >\n <IconAdd class=\"i-medium\" />\n Add to Queue\n </Button>\n\n <Button\n @click=\"toggleFavorite\"\n color=\"primary\"\n size=\"medium\"\n class=\"flex-1 bg-light radius-thin flex-center gap-thin\"\n >\n <IconLike class=\"i-medium\" :fill=\"isFavorite\" />\n {{isFavorite ? 'Liked' : 'Like'}}\n </Button>\n\n <Dropdown :label=\"{component: IconEllipsis, class: 'bg-light radius-thin pd-thin i-big' }\" v-model=\"showDropdown\" class=\"relative\">\n <template #trigger>\n <Button color=\"transp\" size=\"medium\" class=\"w-3r h-3r radius-full\">\n <IconEllipsis class=\"w-1-25r h-1-25r\" />\n </Button>\n </template>\n <template #default>\n <div class=\"dropdown-menu bg-dark pd-small radius-medium shadow-big mn-t-thin\">\n <Button @click=\"showAddToPlaylistModal = true\" color=\"transp\" size=\"small\" class=\"w-100 justify-start\">\n Add to Playlist\n </Button>\n <Button @click=\"copyLink\" color=\"transp\" size=\"small\" class=\"w-100 justify-start\">\n Copy Link\n </Button>\n <template v-if=\"isOwner\">\n <hr class=\"mn-v-thin border-dark-transp-10\" />\n <Button @click=\"editTrack\" color=\"transp\" size=\"small\" class=\"w-100 justify-start\">\n Edit Track\n </Button>\n <Button @click=\"deleteTrack\" color=\"danger\" size=\"small\" class=\"w-100 justify-start\">\n Delete Track\n </Button>\n </template>\n </div>\n </template>\n </Dropdown>\n </div>\n\n <!-- Artist Card -->\n <div class=\"artist-card bg-light pd-medium radius-medium flex items-center gap-medium mn-b-big\">\n <router-link \n :to=\"{ name: 'artist', params: { url: track.artist.url } }\"\n class=\"flex items-center gap-medium flex-1 hover-opacity\"\n >\n <div class=\"artist-avatar\">\n <Media \n v-if=\"track.artist.photoUrl\"\n :src=\"track.artist.photoUrl\"\n :alt=\"track.artist.name\"\n class=\"w-4r h-4r radius-full object-cover\"\n />\n <div v-else class=\"w-4r h-4r radius-full bg-primary flex-center \">\n {{ track.artist.name.charAt(0) }}\n </div>\n </div>\n <div>\n <div class=\"flex items-center gap-thin\">\n <span class=\"t-large \">{{ track.artist.name }}</span>\n <IconVerified v-if=\"track.artist.isVerified\" class=\"w-1r h-1r t-primary\" />\n </div>\n <span class=\"t-small t-transp\">Artist</span>\n </div>\n </router-link>\n <Button \n v-if=\"!isOwner\"\n @click=\"toggleFollowArtist\"\n :color=\"isFollowingArtist ? 'primary' : 'transp'\"\n size=\"small\"\n >\n {{ isFollowingArtist ? 'Following' : 'Follow' }}\n </Button>\n </div>\n\n\n\n <!-- Metadata Cards -->\n <div class=\"metadata-grid grid cols-2 gap-small mn-b-big\">\n <!-- Duration -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <div class=\"icon-wrapper bg-primary-transp-20 w-3r h-3r radius-small flex-center\">\n <IconClock class=\"i-regular t-primary\" />\n </div>\n <div>\n <div class=\"t-small t-transp t-uppercase\">Duration</div>\n <div class=\"t-medium \">{{ formatDuration(track.duration) }}</div>\n </div>\n </div>\n\n <!-- Release Date -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <div class=\"icon-wrapper bg-primary-transp-20 w-3r h-3r radius-small flex-center\">\n <IconCalendar class=\"i-regular t-primary\" />\n </div>\n <div>\n <div class=\"t-small t-transp t-uppercase\">Released</div>\n <div class=\"t-medium \">{{ formatDate(track.releaseDate) }}</div>\n </div>\n </div>\n\n <!-- Status -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <div class=\"icon-wrapper bg-success-transp-20 w-3r h-3r radius-small flex-center\">\n <IconCheck class=\"i-regular t-success\" />\n </div>\n <div>\n <div class=\"t-small t-transp t-uppercase\">Status</div>\n <div class=\"t-medium t-success\">{{ track.status }}</div>\n </div>\n </div>\n\n <!-- Visibility -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <div class=\"icon-wrapper bg-primary-transp-20 w-3r h-3r radius-small flex-center\">\n <IconEye class=\"i-regular t-primary\" />\n </div>\n <div>\n <div class=\"t-small t-transp t-uppercase\">Visibility</div>\n <div class=\"t-medium \">{{ track.isPublic ? 'Public' : 'Private' }}</div>\n </div>\n </div>\n </div>\n\n <!-- Album Info -->\n <div v-if=\"track.album\" class=\"album-card bg-light pd-medium radius-medium mn-b-medium\">\n <div class=\"t-small t-transp t-uppercase mn-b-thin\">From Album</div>\n <router-link \n :to=\"`/album/${track.album.url}`\"\n class=\"flex items-center gap-medium hover-opacity\"\n >\n <Media \n v-if=\"track.album.coverUrl\"\n :src=\"track.album.coverUrl\"\n :alt=\"track.album.title\"\n class=\"w-3r h-3r radius-small object-cover\"\n />\n <span class=\"t-medium \">{{ track.album.title }}</span>\n </router-link>\n </div>\n\n <!-- Genres & Tags -->\n <div v-if=\"(track.genre && track.genre.length) || (track.tags && track.tags.length)\" class=\"tags-section mn-b-medium\">\n <h3 class=\"t-medium mn-b-small\">Genres & Tags</h3>\n <div class=\"flex gap-thin flex-wrap\">\n <span \n v-for=\"genre in track.genre\" \n :key=\"genre\"\n class=\"tag bg-primary-transp-20 t-primary pd-thin-big radius-small t-small hover-bg-primary-transp-30 cursor-pointer\"\n >\n {{ genre }}\n </span>\n <span \n v-for=\"tag in track.tags\" \n :key=\"tag\"\n class=\"tag bg-light t-transp pd-thin-big radius-small t-small hover-bg-light cursor-pointer\"\n >\n #{{ tag }}\n </span>\n </div>\n </div>\n\n <!-- Description -->\n <div v-if=\"track.description\" class=\"description-section bg-light pd-medium radius-medium mn-b-medium\">\n <h3 class=\"t-medium mn-b-small\">About</h3>\n <p class=\"t-transp\">{{ track.description }}</p>\n </div>\n\n <!-- Lyrics -->\n <div v-if=\"track.lyrics\" class=\"lyrics-section bg-light pd-medium radius-medium\">\n <h3 class=\"t-medium mn-b-small\">Lyrics</h3>\n <pre class=\"t-transp t-small\">{{ track.lyrics }}</pre>\n </div>\n </div>\n </div>\n\n <!-- Related Tracks -->\n <section v-if=\"track && relatedTracks && relatedTracks.length\" class=\"related-section mn-t-big\">\n <h2 class=\"h2 mn-b-medium\">Related Tracks</h2>\n <Feed\n :store=\"{\n read: () => new Promise(resolve => resolve(relatedTracks || [])),\n state: { isLoading: false }\n }\"\n :external=\"true\"\n :items=\"relatedTracks\"\n :states=\"{\n empty: {\n title: 'No related tracks',\n description: 'Check back later for recommendations',\n class: 'pd-medium bg-light radius-medium'\n }\n }\"\n class=\"grid cols-2 cols-m-3 cols-l-4 gap-medium\"\n >\n <template #default=\"{ items }\">\n <div class=\"bg-light radius-medium o-hidden\">\n <TrackListCard\n v-for=\"(relatedTrack, index) in items\"\n :key=\"relatedTrack._id\"\n :track=\"relatedTrack\"\n :index=\"index\"\n :showAlbum=\"true\"\n :showCover=\"true\"\n />\n </div>\n </template>\n </Feed>\n </section>\n\n <!-- Add to Playlist Modal -->\n <Popup \n v-if=\"showAddToPlaylistModal\" \n @close-popup=\"showAddToPlaylistModal = false\" \n class=\"bg-white pd-medium w-m-25r radius-medium\"\n >\n <h3 class=\"h3 mn-b-medium\">Add to Playlist</h3>\n <!-- <PlaylistSelector \n :trackId=\"track._id\" \n @added=\"showAddToPlaylistModal = false\"\n /> -->\n <p class=\"t-transp\">Playlist selector coming soon...</p>\n </Popup>\n </div>\n</template>\n\n<script setup>\nimport { ref, computed, onMounted, watch } from 'vue';\nimport { useRoute, useRouter } from 'vue-router';\nimport Button from '@martyrs/src/components/Button/Button.vue';\nimport Loader from '@martyrs/src/components/Loader/Loader.vue';\nimport Media from '@martyrs/src/components/Media/Media.vue';\nimport Dropdown from '@martyrs/src/components/Dropdown/Dropdown.vue';\nimport Popup from '@martyrs/src/components/Popup/Popup.vue';\nimport Feed from '@martyrs/src/components/Feed/Feed.vue';\n\n// Icons\nimport IconPlay from '@martyrs/src/modules/icons/navigation/IconPlay.vue';\nimport IconLike from '@martyrs/src/modules/icons/navigation/IconLike.vue';\nimport IconEllipsis from '@martyrs/src/modules/icons/navigation/IconEllipsis.vue';\nimport IconAdd from '@martyrs/src/modules/icons/navigation/IconAdd.vue';\nimport IconClock from '@martyrs/src/modules/icons/entities/IconTime.vue';\nimport IconCalendar from '@martyrs/src/modules/icons/entities/IconCalendar.vue';\nimport IconCheck from '@martyrs/src/modules/icons/navigation/IconCheckmark.vue';\nimport IconEye from '@martyrs/src/modules/icons/actions/IconShow.vue';\nimport IconVerified from '@martyrs/src/modules/icons/navigation/IconCheckmark.vue';\n\n// Components\nimport TrackListCard from '../cards/TrackListCard.vue';\n// import PlaylistSelector from '../forms/PlaylistSelector.vue';\n\n// Store\nimport { state as tracksState, actions as tracksActions } from '../../store/tracks.js';\nimport { actions as playerActions } from '../../store/player.js';\nimport { state as authState } from '@martyrs/src/modules/auth/views/store/auth.js';\n\nconst route = useRoute();\nconst router = useRouter();\n\n// Emits\nconst emits = defineEmits(['page-loading', 'page-loaded']);\n\n// State\nconst hasLoaded = ref(false);\nconst showDropdown = ref(false);\nconst showAddToPlaylistModal = ref(false);\nconst isFavorite = ref(false);\nconst isFollowingArtist = ref(false);\n\n// Clear state\ntracksState.currentTrack = null;\ntracksState.relatedTracks = [];\n\n// Computed\nconst track = computed(() => tracksState.currentTrack);\nconst relatedTracks = computed(() => tracksState.relatedTracks || []);\n\nconst isOwner = computed(() => {\n return track.value?.owner?.target === authState.user?._id;\n});\n\n// Format helpers\nconst formatDuration = (seconds) => {\n if (!seconds) return '0:00';\n const h = Math.floor(seconds / 3600);\n const m = Math.floor((seconds % 3600) / 60);\n const s = Math.floor(seconds % 60);\n \n if (h > 0) {\n return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;\n }\n return `${m}:${s.toString().padStart(2, '0')}`;\n};\n\nconst formatDate = (dateString) => {\n if (!dateString) return 'Unknown';\n return new Date(dateString).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric'\n });\n};\n\nconst formatNumber = (num) => {\n if (!num) return '0';\n if (num >= 1000000) {\n return (num / 1000000).toFixed(1) + 'M';\n } else if (num >= 1000) {\n return (num / 1000).toFixed(1) + 'K';\n }\n return num.toString();\n};\n\n// Actions\nconst playTrack = () => {\n if (track.value) {\n playerActions.setQueue([track.value]);\n }\n};\n\nconst toggleFavorite = () => {\n isFavorite.value = !isFavorite.value;\n // TODO: Implement actual saving\n};\n\nconst toggleFollowArtist = () => {\n isFollowingArtist.value = !isFollowingArtist.value;\n // TODO: Implement actual following\n};\n\nconst addToQueue = () => {\n if (track.value) {\n playerActions.addToQueue(track.value);\n }\n};\n\nconst editTrack = () => {\n router.push({ name: 'track-edit', params: { url: track.value.url } });\n};\n\nconst deleteTrack = async () => {\n if (confirm('Are you sure you want to delete this track?')) {\n try {\n await tracksActions.deleteTrack(track.value._id);\n router.push({ name: 'music-library' });\n } catch (error) {\n console.error('Failed to delete track:', error);\n }\n }\n};\n\nconst copyLink = () => {\n navigator.clipboard.writeText(window.location.href);\n showDropdown.value = false;\n};\n\n// Data fetching\nconst fetchTrackData = async () => {\n try {\n await tracksActions.fetchTrackByUrl(route.params.url);\n await tracksActions.fetchRelatedTracks(route.params.url);\n } catch (error) {\n console.error('Error loading track:', error);\n }\n};\n\n// Lifecycle\nonMounted(async () => {\n emits('page-loading');\n \n await fetchTrackData();\n \n hasLoaded.value = true;\n emits('page-loaded');\n});\n</script>\n\n<style scoped>\n</style>"],"names":["tracksState","authState","playerActions","tracksActions"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Track.vue.js","sources":["../../../../../../../src/modules/music/components/pages/Track.vue"],"sourcesContent":["<!-- components/pages/Track.vue -->\n<template>\n <div class=\"track-page pd-small\">\n <!-- Loading -->\n <div v-if=\"isLoading\" class=\"w-100 h-25r flex-center flex\">\n <Loader />\n </div>\n\n <!-- Not Found -->\n <div v-if=\"hasLoaded && !track\" class=\"t-center pd-big\">\n <h2 class=\"\">Track not found</h2>\n <p class=\"t-transp t-medium\">The track you're looking for doesn't exist or has been removed.</p>\n </div>\n\n <!-- Track Content -->\n <div v-if=\"track\" class=\"track-content cols-2-fit-content mobile:cols-1 gap-big\">\n <!-- Left Column - Cover & Stats -->\n <div class=\"pos-sticky pos-t-0 mobile:pos-relative track-cover-section\">\n <!-- Cover with Play Overlay -->\n <div class=\"cover-container pos-relative mn-b-medium radius-big o-hidden\">\n <Media \n :url=\"track.coverUrl || (track.album && track.album.coverUrl) || '/logo/logo-placeholder.jpg'\" \n :alt=\"track.title\"\n class=\"aspect-1x1 w-100 radius-medium o-hidden\"\n />\n <div class=\"cover-overlay w-100 h-100 pos-absolute pos-t-0 pos-r-0 bg-black-transp-40 flex flex-center\">\n <Button\n @click=\"playTrack\"\n color=\"white\"\n size=\"big\"\n class=\"w-5r h-5r radius-big bg-main shadow-big hover-scale-110\"\n >\n <IconPlay v-if=\"!isPlaying\" fill=\"rgb(var(--white))\" class=\"i-medium\" />\n <IconPause v-else fill=\"rgb(var(--white))\" class=\"i-medium\" />\n </Button>\n </div>\n </div>\n\n \n\n <!-- Quick Stats -->\n <div class=\"stats-grid grid cols-2 gap-small\">\n <div class=\"stat-card bg-light pd-medium radius-medium t-center\">\n <div class=\" mn-b-thin\">{{ formatNumber(track.playCount) }}</div>\n <div class=\"t-small t-transp t-uppercase\">Plays</div>\n </div>\n <div class=\"stat-card bg-light pd-medium radius-medium t-center\">\n <div class=\" mn-b-thin\">{{ formatNumber(track.views) }}</div>\n <div class=\"t-small t-transp t-uppercase\">Views</div>\n </div>\n </div>\n </div>\n\n <!-- Right Column - Track Details -->\n <div class=\"track-details-section\">\n <!-- Track Type Badge -->\n <div class=\"flex items-center gap-small mn-b-small\">\n <span class=\"bg-light t-medium pd-thin radius-thin uppercase t-small t-uppercase\">Single</span>\n <span class=\"bg-light t-medium pd-thin radius-thin uppercase t-small t-uppercase\">Explicit</span>\n </div>\n\n <!-- Track Title -->\n <h1 class=\"h1 mn-b-medium\">{{ track.title }}</h1>\n <!-- Action Buttons -->\n <div class=\"flex gap-small mn-b-medium\">\n <Button\n @click=\"playTrack\"\n color=\"primary\"\n size=\"medium\"\n class=\"flex-1 t-white bg-black radius-thin flex-center gap-thin\"\n >\n <IconPlay v-if=\"!isPlaying\" fill=\"rgb(var(--white))\" class=\"i-medium\" />\n <IconPause v-else fill=\"rgb(var(--white))\" class=\"i-medium\" />\n {{ !isPlaying ? 'Play' : 'Pause'}}\n </Button>\n\n <Button\n @click=\"addToQueue\"\n color=\"primary\"\n size=\"medium\"\n class=\"flex-1 bg-light radius-thin flex-center gap-thin\"\n >\n <IconAdd class=\"i-medium\" />\n Add to Queue\n </Button>\n\n <Button\n @click=\"toggleFavorite\"\n color=\"primary\"\n size=\"medium\"\n class=\"flex-1 bg-light radius-thin flex-center gap-thin\"\n >\n <IconLike class=\"i-medium\" :fill=\"isFavorite ? 'rgb(var(--main)':'rgb(var(--black)'\" />\n {{isFavorite ? 'Liked' : 'Like'}}\n </Button>\n\n <Dropdown :label=\"{component: IconEllipsis, class: 'bg-light radius-thin pd-thin i-big' }\" v-model=\"showDropdown\" class=\"relative\">\n <template #trigger>\n <Button color=\"transp\" size=\"medium\" class=\"w-3r h-3r radius-full\">\n <IconEllipsis class=\"w-1-25r h-1-25r\" />\n </Button>\n </template>\n <template #default>\n <div class=\"dropdown-menu bg-dark pd-small radius-medium shadow-big mn-t-thin\">\n <Button @click=\"showAddToPlaylistModal = true\" color=\"transp\" size=\"small\" class=\"w-100 justify-start\">\n Add to Playlist\n </Button>\n <Button @click=\"copyLink\" color=\"transp\" size=\"small\" class=\"w-100 justify-start\">\n Copy Link\n </Button>\n <template v-if=\"isOwner\">\n <hr class=\"mn-v-thin border-dark-transp-10\" />\n <Button @click=\"editTrack\" color=\"transp\" size=\"small\" class=\"w-100 justify-start\">\n Edit Track\n </Button>\n <Button @click=\"deleteTrack\" color=\"danger\" size=\"small\" class=\"w-100 justify-start\">\n Delete Track\n </Button>\n </template>\n </div>\n </template>\n </Dropdown>\n </div>\n\n <!-- Artist Card -->\n <div class=\"artists-section mn-b-medium\">\n <h3 class=\"t-medium mn-b-small\" v-if=\"track.artist\">Artist</h3>\n <div class=\"flex flex-col gap-small\">\n <ArtistCardSmall \n :key=\"track.artist._id\"\n :artist=\"track.artist\"\n :is-following=\"isFollowingArtist\"\n :show-follow-button=\"!isOwner\"\n @toggle-follow=\"toggleFollowArtist\"\n />\n </div>\n </div>\n\n <!-- Metadata Cards -->\n <h3 class=\"t-medium mn-b-small\">Metadata</h3>\n <div class=\"metadata-grid grid cols-2 gap-small mn-b-medium\">\n <!-- Release Date -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <IconCalendar class=\"i-regular t-primary\" />\n <div>\n <div class=\"t-small t-transp t-uppercase\">Released</div>\n <div class=\"t-medium \">{{ formatDate(track.releaseDate) }}</div>\n </div>\n </div>\n\n <!-- Total Duration -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <IconClock class=\"i-regular t-primary\" />\n <div>\n <div class=\"t-small t-transp t-uppercase\">Duration</div>\n <div class=\"t-medium \">{{ formatDuration(track.duration) }}</div>\n </div>\n </div>\n\n <!-- Label -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <IconCheck class=\"i-regular t-primary\" />\n <div>\n <div class=\"t-small t-transp t-uppercase\">Status</div>\n <div class=\"t-medium \">{{ track.status }}</div>\n </div>\n </div>\n\n <!-- Visibility -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <IconEye class=\"i-regular t-primary\" />\n <div>\n <div class=\"t-small t-transp t-uppercase\">Visibility</div>\n <div class=\"t-medium \">{{ track.isPublic ? 'Public' : 'Private' }}</div>\n </div>\n </div>\n </div>\n\n\n <!-- Album Info -->\n <h3 v-if=\"track.album\" class=\"t-medium mn-b-small\">From Album</h3>\n <div v-if=\"track.album\" class=\"album-card bg-light pd-medium radius-medium mn-b-medium\">\n \n <router-link \n :to=\"`/album/${track.album.url}`\"\n class=\"flex flex-v-center gap-thin hover-opacity\"\n >\n <Media \n :url=\"track.album.coverArt || '/logo/logo-placeholder.jpg'\"\n :alt=\"track.album.title\"\n class=\"w-3r h-3r radius-thin o-hidden object-cover\"\n />\n <span class=\"t-medium \">{{ track.album.title }}</span>\n </router-link>\n </div>\n\n <!-- Genres & Tags -->\n <div v-if=\"(track.genre && track.genre.length) || (track.tags && track.tags.length)\" class=\"tags-section mn-b-medium\">\n <h3 class=\"t-medium mn-b-small\">Genres & Tags</h3>\n <div class=\"flex gap-thin flex-wrap\">\n <span \n v-for=\"genre in track.genre\" \n :key=\"genre\"\n class=\"tag bg-main t-medium pd-thin radius-thin t-small cursor-pointer\"\n >\n {{ genre.name || genre }}\n </span>\n <span \n v-for=\"tag in track.tags\" \n :key=\"tag\"\n class=\"tag bg-light t-transp pd-thin-big radius-small t-small hover-bg-light cursor-pointer\"\n >\n #{{ tag.name || tag }}\n </span>\n </div>\n </div>\n\n <!-- Description -->\n <div v-if=\"track.description\" class=\"description-section bg-light pd-medium radius-medium mn-b-medium\">\n <h3 class=\"t-medium mn-b-small\">About</h3>\n <p class=\"t-transp\">{{ track.description }}</p>\n </div>\n\n <!-- Lyrics -->\n <div v-if=\"track.lyrics\" class=\"lyrics-section bg-light pd-medium radius-medium\">\n <h3 class=\"t-medium mn-b-small\">Lyrics</h3>\n <pre class=\"t-transp t-small\">{{ track.lyrics }}</pre>\n </div>\n </div>\n </div>\n\n <!-- Related Tracks -->\n <section v-if=\"track && relatedTracks && relatedTracks.length\" class=\"related-section mn-t-big\">\n <h2 class=\"h2 mn-b-medium\">Related Tracks</h2>\n <Feed\n :store=\"{\n read: () => new Promise(resolve => resolve(relatedTracks || [])),\n state: { isLoading: false }\n }\"\n :external=\"true\"\n :items=\"relatedTracks\"\n :states=\"{\n empty: {\n title: 'No related tracks',\n description: 'Check back later for recommendations',\n class: 'pd-medium bg-light radius-medium'\n }\n }\"\n class=\"grid cols-2 cols-m-3 cols-l-4 gap-medium\"\n >\n <template #default=\"{ items }\">\n <div class=\"bg-light radius-medium o-hidden\">\n <TrackListCard\n v-for=\"(relatedTrack, index) in items\"\n :key=\"relatedTrack._id\"\n :track=\"relatedTrack\"\n :index=\"index\"\n :showAlbum=\"true\"\n :showCover=\"true\"\n />\n </div>\n </template>\n </Feed>\n </section>\n\n <!-- Add to Playlist Modal -->\n <Popup \n v-if=\"showAddToPlaylistModal\" \n @close-popup=\"showAddToPlaylistModal = false\" \n class=\"bg-white pd-medium w-m-25r radius-medium\"\n >\n <h3 class=\"h3 mn-b-medium\">Add to Playlist</h3>\n <!-- <PlaylistSelector \n :trackId=\"track._id\" \n @added=\"showAddToPlaylistModal = false\"\n /> -->\n <p class=\"t-transp\">Playlist selector coming soon...</p>\n </Popup>\n </div>\n</template>\n\n<script setup>\nimport { ref, computed, onMounted, watch } from 'vue';\nimport { useRoute, useRouter } from 'vue-router';\nimport Button from '@martyrs/src/components/Button/Button.vue';\nimport Loader from '@martyrs/src/components/Loader/Loader.vue';\nimport Media from '@martyrs/src/components/Media/Media.vue';\nimport Dropdown from '@martyrs/src/components/Dropdown/Dropdown.vue';\nimport Popup from '@martyrs/src/components/Popup/Popup.vue';\nimport Feed from '@martyrs/src/components/Feed/Feed.vue';\n\n// Icons\nimport IconPlay from '@martyrs/src/modules/icons/navigation/IconPlay.vue';\nimport IconPause from '@martyrs/src/modules/icons/navigation/IconPause.vue';\nimport IconLike from '@martyrs/src/modules/icons/navigation/IconLike.vue';\nimport IconEllipsis from '@martyrs/src/modules/icons/navigation/IconEllipsis.vue';\nimport IconAdd from '@martyrs/src/modules/icons/navigation/IconAdd.vue';\nimport IconClock from '@martyrs/src/modules/icons/entities/IconTime.vue';\nimport IconCalendar from '@martyrs/src/modules/icons/entities/IconCalendar.vue';\nimport IconCheck from '@martyrs/src/modules/icons/navigation/IconCheckmark.vue';\nimport IconEye from '@martyrs/src/modules/icons/actions/IconShow.vue';\nimport IconVerified from '@martyrs/src/modules/icons/navigation/IconCheckmark.vue';\n\n// Components\nimport TrackListCard from '../cards/TrackListCard.vue';\nimport ArtistCardSmall from '../cards/ArtistCardSmall.vue';\n// import PlaylistSelector from '../forms/PlaylistSelector.vue';\n\n// Store\nimport { state as tracksState, actions as tracksActions } from '../../store/tracks.js';\nimport { state as playerState, actions as playerActions } from '../../store/player.js';\nimport { state as authState } from '@martyrs/src/modules/auth/views/store/auth.js';\n\nconst isPlaying = computed(() => playerState.isPlaying);\n\nconst route = useRoute();\nconst router = useRouter();\n\n// Emits\nconst emits = defineEmits(['page-loading', 'page-loaded']);\n\n// State\nconst hasLoaded = ref(false);\nconst showDropdown = ref(false);\nconst showAddToPlaylistModal = ref(false);\nconst isFavorite = ref(false);\nconst isFollowingArtist = ref(false);\n\n// Clear state\ntracksState.currentTrack = null;\ntracksState.relatedTracks = [];\n\n// Computed\nconst track = computed(() => tracksState.currentTrack);\nconst relatedTracks = computed(() => tracksState.relatedTracks || []);\n\nconst isOwner = computed(() => {\n return track.value?.owner?.target === authState.user?._id;\n});\n\n// Format helpers\nconst formatDuration = (seconds) => {\n if (!seconds) return '0:00';\n const h = Math.floor(seconds / 3600);\n const m = Math.floor((seconds % 3600) / 60);\n const s = Math.floor(seconds % 60);\n \n if (h > 0) {\n return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;\n }\n return `${m}:${s.toString().padStart(2, '0')}`;\n};\n\nconst formatDate = (dateString) => {\n if (!dateString) return 'Unknown';\n return new Date(dateString).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric'\n });\n};\n\nconst formatNumber = (num) => {\n if (!num) return '0';\n if (num >= 1000000) {\n return (num / 1000000).toFixed(1) + 'M';\n } else if (num >= 1000) {\n return (num / 1000).toFixed(1) + 'K';\n }\n return num.toString();\n};\n\n// Actions\nconst playTrack = () => {\n if (track.value) {\n playerActions.setQueue([track.value]);\n }\n};\n\nconst toggleFavorite = () => {\n isFavorite.value = !isFavorite.value;\n // TODO: Implement actual saving\n};\n\nconst toggleFollowArtist = () => {\n isFollowingArtist.value = !isFollowingArtist.value;\n // TODO: Implement actual following\n};\n\nconst addToQueue = () => {\n if (track.value) {\n playerActions.addToQueue(track.value);\n }\n};\n\nconst editTrack = () => {\n router.push({ name: 'track-edit', params: { url: track.value.url } });\n};\n\nconst deleteTrack = async () => {\n if (confirm('Are you sure you want to delete this track?')) {\n try {\n await tracksActions.deleteTrack(track.value._id);\n router.push({ name: 'music-library' });\n } catch (error) {\n console.error('Failed to delete track:', error);\n }\n }\n};\n\nconst copyLink = () => {\n navigator.clipboard.writeText(window.location.href);\n showDropdown.value = false;\n};\n\n// Data fetching\nconst fetchTrackData = async () => {\n try {\n await tracksActions.fetchTrackByUrl(route.params.url);\n await tracksActions.fetchRelatedTracks(route.params.url);\n } catch (error) {\n console.error('Error loading track:', error);\n }\n};\n\n// Lifecycle\nonMounted(async () => {\n emits('page-loading');\n \n await fetchTrackData();\n \n hasLoaded.value = true;\n emits('page-loaded');\n});\n</script>\n\n<style scoped>\n</style>"],"names":["playerState","tracksState","authState","playerActions","tracksActions"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyTA,UAAM,YAAY,SAAS,MAAMA,MAAY,SAAS;AAEtD,UAAM,QAAQ,SAAQ;AACtB,UAAM,SAAS,UAAS;AAGxB,UAAM,QAAQ;AAGd,UAAM,YAAY,IAAI,KAAK;AAC3B,UAAM,eAAe,IAAI,KAAK;AAC9B,UAAM,yBAAyB,IAAI,KAAK;AACxC,UAAM,aAAa,IAAI,KAAK;AAC5B,UAAM,oBAAoB,IAAI,KAAK;AAGnCC,YAAY,eAAe;AAC3BA,YAAY,gBAAgB,CAAA;AAG5B,UAAM,QAAQ,SAAS,MAAMA,QAAY,YAAY;AACrD,UAAM,gBAAgB,SAAS,MAAMA,QAAY,iBAAiB,CAAA,CAAE;AAEpE,UAAM,UAAU,SAAS,MAAM;AAC7B,aAAO,MAAM,OAAO,OAAO,WAAWC,QAAU,MAAM;AAAA,IACxD,CAAC;AAGD,UAAM,iBAAiB,CAAC,YAAY;AAClC,UAAI,CAAC,QAAS,QAAO;AACrB,YAAM,IAAI,KAAK,MAAM,UAAU,IAAI;AACnC,YAAM,IAAI,KAAK,MAAO,UAAU,OAAQ,EAAE;AAC1C,YAAM,IAAI,KAAK,MAAM,UAAU,EAAE;AAEjC,UAAI,IAAI,GAAG;AACT,eAAO,GAAG,CAAC,IAAI,EAAE,SAAQ,EAAG,SAAS,GAAG,GAAG,CAAC,IAAI,EAAE,SAAQ,EAAG,SAAS,GAAG,GAAG,CAAC;AAAA,MAC/E;AACA,aAAO,GAAG,CAAC,IAAI,EAAE,SAAQ,EAAG,SAAS,GAAG,GAAG,CAAC;AAAA,IAC9C;AAEA,UAAM,aAAa,CAAC,eAAe;AACjC,UAAI,CAAC,WAAY,QAAO;AACxB,aAAO,IAAI,KAAK,UAAU,EAAE,mBAAmB,SAAS;AAAA,QACtD,MAAM;AAAA,QACN,OAAO;AAAA,QACP,KAAK;AAAA,MACT,CAAG;AAAA,IACH;AAEA,UAAM,eAAe,CAAC,QAAQ;AAC5B,UAAI,CAAC,IAAK,QAAO;AACjB,UAAI,OAAO,KAAS;AAClB,gBAAQ,MAAM,KAAS,QAAQ,CAAC,IAAI;AAAA,MACtC,WAAW,OAAO,KAAM;AACtB,gBAAQ,MAAM,KAAM,QAAQ,CAAC,IAAI;AAAA,MACnC;AACA,aAAO,IAAI,SAAQ;AAAA,IACrB;AAGA,UAAM,YAAY,MAAM;AACtB,UAAI,MAAM,OAAO;AACfC,kBAAc,SAAS,CAAC,MAAM,KAAK,CAAC;AAAA,MACtC;AAAA,IACF;AAEA,UAAM,iBAAiB,MAAM;AAC3B,iBAAW,QAAQ,CAAC,WAAW;AAAA,IAEjC;AAEA,UAAM,qBAAqB,MAAM;AAC/B,wBAAkB,QAAQ,CAAC,kBAAkB;AAAA,IAE/C;AAEA,UAAM,aAAa,MAAM;AACvB,UAAI,MAAM,OAAO;AACfA,kBAAc,WAAW,MAAM,KAAK;AAAA,MACtC;AAAA,IACF;AAEA,UAAM,YAAY,MAAM;AACtB,aAAO,KAAK,EAAE,MAAM,cAAc,QAAQ,EAAE,KAAK,MAAM,MAAM,IAAG,EAAE,CAAE;AAAA,IACtE;AAEA,UAAM,cAAc,YAAY;AAC9B,UAAI,QAAQ,6CAA6C,GAAG;AAC1D,YAAI;AACF,gBAAMC,QAAc,YAAY,MAAM,MAAM,GAAG;AAC/C,iBAAO,KAAK,EAAE,MAAM,gBAAe,CAAE;AAAA,QACvC,SAAS,OAAO;AACd,kBAAQ,MAAM,2BAA2B,KAAK;AAAA,QAChD;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,MAAM;AACrB,gBAAU,UAAU,UAAU,OAAO,SAAS,IAAI;AAClD,mBAAa,QAAQ;AAAA,IACvB;AAGA,UAAM,iBAAiB,YAAY;AACjC,UAAI;AACF,cAAMA,QAAc,gBAAgB,MAAM,OAAO,GAAG;AACpD,cAAMA,QAAc,mBAAmB,MAAM,OAAO,GAAG;AAAA,MACzD,SAAS,OAAO;AACd,gBAAQ,MAAM,wBAAwB,KAAK;AAAA,MAC7C;AAAA,IACF;AAGA,cAAU,YAAY;AACpB,YAAM,cAAc;AAEpB,YAAM,eAAc;AAEpB,gBAAU,QAAQ;AAClB,YAAM,aAAa;AAAA,IACrB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
|
|
|
3
3
|
const vue = require("vue");
|
|
4
4
|
const vueRouter = require("vue-router");
|
|
5
5
|
;/* empty css */
|
|
6
|
-
;/* empty css
|
|
6
|
+
;/* empty css */
|
|
7
7
|
const TrackForm = require("../forms/TrackForm.vue.cjs");
|
|
8
8
|
require("../../../auth/views/store/auth.cjs");
|
|
9
9
|
const _hoisted_1 = { class: "track-create-page" };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createElementBlock, openBlock, createVNode } from "vue";
|
|
2
2
|
import { useRouter } from "vue-router";
|
|
3
3
|
/* empty css */
|
|
4
|
-
/* empty css
|
|
4
|
+
/* empty css */
|
|
5
5
|
import _sfc_main$1 from "../forms/TrackForm.vue.js";
|
|
6
6
|
import "../../../auth/views/store/auth.js";
|
|
7
7
|
const _hoisted_1 = { class: "track-create-page" };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
3
|
const vue = require("vue");
|
|
4
4
|
const Media = require("../../../../components/Media/Media.vue.cjs");
|
|
5
|
-
const Button = require("../../../../components/Button/Button.
|
|
5
|
+
const Button = require("../../../../components/Button/Button.vue2.cjs");
|
|
6
6
|
const TrackProgress = require("./TrackProgress.vue.cjs");
|
|
7
7
|
const VolumeControl = require("./VolumeControl.vue.cjs");
|
|
8
8
|
const IconPlay = require("../../../icons/navigation/IconPlay.vue.cjs");
|
|
@@ -12,7 +12,7 @@ const IconChevronLeft = require("../../../icons/navigation/IconChevronLeft.vue.c
|
|
|
12
12
|
const IconShuffle = require("../../../icons/navigation/IconShuffle.vue.cjs");
|
|
13
13
|
const IconRefresh = require("../../../icons/navigation/IconRefresh.vue.cjs");
|
|
14
14
|
const IconLike = require("../../../icons/navigation/IconLike.vue.cjs");
|
|
15
|
-
const
|
|
15
|
+
const IconUnMute = require("../../../icons/navigation/IconUnMute.vue.cjs");
|
|
16
16
|
const IconMute = require("../../../icons/navigation/IconMute.vue.cjs");
|
|
17
17
|
const player = require("../../store/player.cjs");
|
|
18
18
|
;/* empty css */
|
|
@@ -91,10 +91,7 @@ const _sfc_main = {
|
|
|
91
91
|
showSucces: false
|
|
92
92
|
}, {
|
|
93
93
|
default: vue.withCtx(() => [
|
|
94
|
-
vue.createVNode(IconLike.default, {
|
|
95
|
-
fill: "rgb(var(--white))",
|
|
96
|
-
class: "like-icon"
|
|
97
|
-
})
|
|
94
|
+
vue.createVNode(IconLike.default, { class: "like-icon" })
|
|
98
95
|
]),
|
|
99
96
|
_: 1
|
|
100
97
|
}, 8, ["class"])
|
|
@@ -109,7 +106,7 @@ const _sfc_main = {
|
|
|
109
106
|
}, {
|
|
110
107
|
default: vue.withCtx(() => [
|
|
111
108
|
vue.createVNode(IconShuffle.default, {
|
|
112
|
-
fill: "rgb(var(--
|
|
109
|
+
fill: "rgb(var(--black))",
|
|
113
110
|
class: "control-icon"
|
|
114
111
|
})
|
|
115
112
|
]),
|
|
@@ -123,7 +120,7 @@ const _sfc_main = {
|
|
|
123
120
|
}, {
|
|
124
121
|
default: vue.withCtx(() => [
|
|
125
122
|
vue.createVNode(IconChevronLeft.default, {
|
|
126
|
-
fill: "rgb(var(--
|
|
123
|
+
fill: "rgb(var(--black))",
|
|
127
124
|
class: "control-icon"
|
|
128
125
|
})
|
|
129
126
|
]),
|
|
@@ -138,9 +135,11 @@ const _sfc_main = {
|
|
|
138
135
|
default: vue.withCtx(() => [
|
|
139
136
|
isPlaying.value ? (vue.openBlock(), vue.createBlock(IconPause.default, {
|
|
140
137
|
key: 0,
|
|
138
|
+
fill: "white",
|
|
141
139
|
class: "play-icon"
|
|
142
140
|
})) : (vue.openBlock(), vue.createBlock(IconPlay.default, {
|
|
143
141
|
key: 1,
|
|
142
|
+
fill: "white",
|
|
144
143
|
class: "play-icon"
|
|
145
144
|
}))
|
|
146
145
|
]),
|
|
@@ -154,7 +153,7 @@ const _sfc_main = {
|
|
|
154
153
|
}, {
|
|
155
154
|
default: vue.withCtx(() => [
|
|
156
155
|
vue.createVNode(IconChevronRight.default, {
|
|
157
|
-
fill: "rgb(var(--
|
|
156
|
+
fill: "rgb(var(--black))",
|
|
158
157
|
class: "control-icon"
|
|
159
158
|
})
|
|
160
159
|
]),
|
|
@@ -168,7 +167,7 @@ const _sfc_main = {
|
|
|
168
167
|
}, {
|
|
169
168
|
default: vue.withCtx(() => [
|
|
170
169
|
vue.createVNode(IconRefresh.default, {
|
|
171
|
-
fill: "rgb(var(--
|
|
170
|
+
fill: "rgb(var(--black))",
|
|
172
171
|
class: "control-icon"
|
|
173
172
|
})
|
|
174
173
|
]),
|
|
@@ -187,17 +186,13 @@ const _sfc_main = {
|
|
|
187
186
|
showSucces: false
|
|
188
187
|
}, {
|
|
189
188
|
default: vue.withCtx(() => [
|
|
190
|
-
|
|
189
|
+
muted.value || volume.value < 5e-3 ? (vue.openBlock(), vue.createBlock(IconMute.default, {
|
|
191
190
|
key: 0,
|
|
192
|
-
fill: "rgb(var(--
|
|
191
|
+
fill: "rgb(var(--black))",
|
|
193
192
|
class: "volume-icon"
|
|
194
|
-
})) :
|
|
193
|
+
})) : (vue.openBlock(), vue.createBlock(IconUnMute.default, {
|
|
195
194
|
key: 1,
|
|
196
|
-
fill: "rgb(var(--
|
|
197
|
-
class: "volume-icon"
|
|
198
|
-
})) : (vue.openBlock(), vue.createBlock(IconMute.default, {
|
|
199
|
-
key: 2,
|
|
200
|
-
fill: "rgb(var(--white))",
|
|
195
|
+
fill: "rgb(var(--black))",
|
|
201
196
|
class: "volume-icon"
|
|
202
197
|
}))
|
|
203
198
|
]),
|
|
@@ -212,6 +207,6 @@ const _sfc_main = {
|
|
|
212
207
|
};
|
|
213
208
|
}
|
|
214
209
|
};
|
|
215
|
-
const MusicPlayer = /* @__PURE__ */ _pluginVue_exportHelper.default(_sfc_main, [["__scopeId", "data-v-
|
|
210
|
+
const MusicPlayer = /* @__PURE__ */ _pluginVue_exportHelper.default(_sfc_main, [["__scopeId", "data-v-f4886dd7"]]);
|
|
216
211
|
exports.default = MusicPlayer;
|
|
217
212
|
//# sourceMappingURL=MusicPlayer.vue.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MusicPlayer.vue.cjs","sources":["../../../../../../../src/modules/music/components/player/MusicPlayer.vue"],"sourcesContent":["<!-- components/player/MusicPlayer.vue -->\n<template>\n <div class=\"player-container\">\n <div class=\"player\">\n <!-- Track Info Section -->\n <div class=\"track-info\">\n <div class=\"track-image\">\n <Media \n :url=\"currentTrack?.coverUrl || (currentTrack?.album && currentTrack.album.coverUrl) || '/assets/placeholder-track.jpg'\" \n class=\"track-image-media\"\n />\n </div>\n <div class=\"track-details\">\n <h3 class=\"track-title\">{{ currentTrack?.title || 'No track playing' }}</h3>\n <p class=\"track-artist\">{{ getArtistName(currentTrack) }}</p>\n </div>\n <Button \n @click=\"toggleFavorite\" \n class=\"like-btn\"\n :class=\"{ liked: isFavorite }\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconLike fill=\"rgb(var(--white))\" class=\"like-icon\"/>\n </Button>\n </div>\n\n <!-- Control Section -->\n <div class=\"controls\">\n <div class=\"control-buttons\">\n <Button \n @click=\"toggleShuffle\" \n class=\"control-btn secondary\"\n :class=\"{ active: shuffle }\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconShuffle fill=\"rgb(var(--white))\" class=\"control-icon\"/>\n </Button>\n \n <Button \n @click=\"playPrevious\" \n class=\"control-btn secondary\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconPrevious fill=\"rgb(var(--white))\" class=\"control-icon\"/>\n </Button>\n \n <Button \n @click=\"togglePlay\" \n class=\"control-btn primary\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconPause v-if=\"isPlaying\" class=\"play-icon\"/>\n <IconPlay v-else class=\"play-icon\"/>\n </Button>\n \n <Button \n @click=\"playNext\" \n class=\"control-btn secondary\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconNext fill=\"rgb(var(--white))\" class=\"control-icon\"/>\n </Button>\n \n <Button \n @click=\"toggleRepeat\" \n class=\"control-btn secondary\"\n :class=\"{ active: repeat !== 'off' }\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconRepeat fill=\"rgb(var(--white))\" class=\"control-icon\"/>\n </Button>\n </div>\n \n <!-- Progress Bar -->\n <div class=\"progress-section\">\n <TrackProgress />\n </div>\n </div>\n\n <!-- Volume Section -->\n <div class=\"volume-section\">\n <Button \n @click=\"toggleMute\" \n class=\"volume-btn\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconVolume fill=\"rgb(var(--white))\" v-if=\"!muted && volume > 0.5\" class=\"volume-icon\"/>\n <IconVolumeHalf fill=\"rgb(var(--white))\" v-else-if=\"!muted && volume > 0\" class=\"volume-icon\"/>\n <IconVolumeMute fill=\"rgb(var(--white))\" v-else class=\"volume-icon\"/>\n </Button>\n \n <div class=\"volume-slider\">\n <VolumeControl />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { computed, ref } from 'vue';\nimport Media from '@martyrs/src/components/Media/Media.vue';\nimport Button from '@martyrs/src/components/Button/Button.vue';\nimport TrackProgress from './TrackProgress.vue';\nimport VolumeControl from './VolumeControl.vue';\n\n// Import icons\nimport IconPlay from '@martyrs/src/modules/icons/navigation/IconPlay.vue';\nimport IconPause from '@martyrs/src/modules/icons/navigation/IconPause.vue';\nimport IconNext from '@martyrs/src/modules/icons/navigation/IconChevronRight.vue';\nimport IconPrevious from '@martyrs/src/modules/icons/navigation/IconChevronLeft.vue';\nimport IconShuffle from '@martyrs/src/modules/icons/navigation/IconShuffle.vue';\nimport IconRepeat from '@martyrs/src/modules/icons/navigation/IconRefresh.vue';\nimport IconLike from '@martyrs/src/modules/icons/navigation/IconLike.vue';\nimport IconVolume from '@martyrs/src/modules/icons/navigation/IconVolume.vue';\nimport IconVolumeHalf from '@martyrs/src/modules/icons/navigation/IconVolume.vue';\nimport IconVolumeMute from '@martyrs/src/modules/icons/navigation/IconMute.vue';\n\n// Import player store\nimport { state as playerState, actions as playerActions } from '../../store/player.js';\n\n// State\nconst isFavorite = ref(false);\n\n// Computed properties\nconst currentTrack = computed(() => playerState.currentTrack);\nconst isPlaying = computed(() => playerState.isPlaying);\nconst volume = computed(() => playerState.volume);\nconst muted = computed(() => playerState.muted);\nconst shuffle = computed(() => playerState.shuffle);\nconst repeat = computed(() => playerState.repeat);\n\n// Methods\nconst togglePlay = () => {\n playerActions.togglePlay();\n};\n\nconst playNext = () => {\n playerActions.playNext();\n};\n\nconst playPrevious = () => {\n playerActions.playPrevious();\n};\n\nconst toggleShuffle = () => {\n playerActions.toggleShuffle();\n};\n\nconst toggleRepeat = () => {\n playerActions.toggleRepeat();\n};\n\nconst toggleMute = () => {\n playerActions.toggleMute();\n};\n\nconst toggleFavorite = () => {\n isFavorite.value = !isFavorite.value;\n // Implement favorite track logic here\n};\n\nconst getArtistName = (track) => {\n if (!track) return 'Unknown Artist';\n \n if (track.artist) {\n if (typeof track.artist === 'object') {\n return track.artist.name || 'Unknown Artist';\n }\n return track.artist;\n }\n return 'Unknown Artist';\n};\n</script>\n\n<style scoped>\n.player-container {\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 1000;\n background: linear-gradient(135deg, rgb(24, 24, 24) 0%, rgb(18, 18, 18) 100%);\n border-top: 1px solid rgb(40, 40, 40);\n backdrop-filter: blur(10px);\n}\n\n.player {\n display: grid;\n grid-template-columns: 1fr 2fr 1fr;\n align-items: center;\n padding: 12px 16px;\n gap: 16px;\n height: 90px;\n max-width: 100%;\n}\n\n/* Track Info Section */\n.track-info {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.track-image {\n width: 56px;\n height: 56px;\n border-radius: 4px;\n overflow: hidden;\n flex-shrink: 0;\n}\n\n.track-image-media {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transition: transform 0.3s ease;\n}\n\n.track-image:hover .track-image-media {\n transform: scale(1.05);\n}\n\n.track-details {\n min-width: 0;\n flex: 1;\n}\n\n.track-title {\n font-size: 14px;\n font-weight: 600;\n color: rgb(var(--white));\n margin: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n line-height: 1.2;\n}\n\n.track-artist {\n font-size: 12px;\n color: rgb(var(--grey));\n margin: 2px 0 0 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.like-btn {\n background: none;\n border: none;\n color: rgb(var(--grey));\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.like-icon {\n width: 16px;\n height: 16px;\n}\n\n.like-btn:hover {\n color: rgb(var(--white));\n background: rgba(255, 255, 255, 0.1);\n}\n\n.like-btn.liked {\n color: rgb(var(--main));\n}\n\n.like-btn.liked .like-icon {\n fill: rgb(var(--main));\n}\n\n.like-btn.liked:hover {\n color: rgb(var(--main));\n opacity: 0.8;\n}\n\n/* Controls Section */\n.controls {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n width: 100%;\n}\n\n.control-buttons {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.control-btn {\n background: none;\n border: none;\n color: rgb(var(--grey));\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.control-icon {\n width: 16px;\n height: 16px;\n}\n\n.control-btn.primary {\n background: rgb(var(--white));\n color: rgb(var(--black));\n width: 32px;\n height: 32px;\n}\n\n.play-icon {\n width: 14px;\n height: 14px;\n fill: rgb(var(--black));\n}\n\n.control-btn.primary:hover {\n background: rgb(240, 240, 240);\n transform: scale(1.06);\n}\n\n.control-btn.secondary:hover {\n color: rgb(var(--white));\n background: rgba(255, 255, 255, 0.1);\n}\n\n.control-btn.secondary:hover .control-icon {\n fill: rgb(var(--white));\n}\n\n.control-btn.active {\n color: rgb(var(--main));\n}\n\n.control-btn.active .control-icon {\n fill: rgb(var(--main));\n}\n\n.control-btn.active:hover {\n color: rgb(var(--main));\n opacity: 0.8;\n}\n\n/* Progress Section */\n.progress-section {\n width: 100%;\n max-width: 600px;\n}\n\n/* Volume Section */\n.volume-section {\n display: flex;\n align-items: center;\n gap: 12px;\n justify-content: flex-end;\n}\n\n.volume-btn {\n background: none;\n border: none;\n color: rgb(var(--grey));\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.volume-icon {\n width: 16px;\n height: 16px;\n}\n\n.volume-btn:hover {\n color: rgb(var(--white));\n background: rgba(255, 255, 255, 0.1);\n}\n\n.volume-btn:hover .volume-icon {\n fill: rgb(var(--white));\n}\n\n.volume-slider {\n width: 100px;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .player {\n grid-template-columns: 1fr;\n grid-template-rows: auto auto auto;\n height: auto;\n padding: 8px 12px 12px;\n gap: 12px;\n }\n\n .track-info {\n order: 1;\n }\n\n .controls {\n order: 2;\n }\n\n .volume-section {\n order: 3;\n justify-content: center;\n }\n\n .volume-slider {\n width: 120px;\n }\n\n .progress-section {\n max-width: 100%;\n }\n}\n\n/* Animations */\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.player-container {\n animation: fadeIn 0.3s ease-out;\n}\n\n@keyframes pulse {\n 0% {\n transform: scale(1);\n }\n 50% {\n transform: scale(1.05);\n }\n 100% {\n transform: scale(1);\n }\n}\n\n.control-btn.primary:active {\n animation: pulse 0.3s ease;\n}\n</style>"],"names":["ref","computed","playerState","playerActions"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiIA,UAAM,aAAaA,IAAAA,IAAI,KAAK;AAG5B,UAAM,eAAeC,IAAAA,SAAS,MAAMC,OAAAA,MAAY,YAAY;AAC5D,UAAM,YAAYD,IAAAA,SAAS,MAAMC,OAAAA,MAAY,SAAS;AACtD,UAAM,SAASD,IAAAA,SAAS,MAAMC,OAAAA,MAAY,MAAM;AAChD,UAAM,QAAQD,IAAAA,SAAS,MAAMC,OAAAA,MAAY,KAAK;AAC9C,UAAM,UAAUD,IAAAA,SAAS,MAAMC,OAAAA,MAAY,OAAO;AAClD,UAAM,SAASD,IAAAA,SAAS,MAAMC,OAAAA,MAAY,MAAM;AAGhD,UAAM,aAAa,MAAM;AACvBC,aAAAA,QAAc,WAAU;AAAA,IAC1B;AAEA,UAAM,WAAW,MAAM;AACrBA,aAAAA,QAAc,SAAQ;AAAA,IACxB;AAEA,UAAM,eAAe,MAAM;AACzBA,aAAAA,QAAc,aAAY;AAAA,IAC5B;AAEA,UAAM,gBAAgB,MAAM;AAC1BA,aAAAA,QAAc,cAAa;AAAA,IAC7B;AAEA,UAAM,eAAe,MAAM;AACzBA,aAAAA,QAAc,aAAY;AAAA,IAC5B;AAEA,UAAM,aAAa,MAAM;AACvBA,aAAAA,QAAc,WAAU;AAAA,IAC1B;AAEA,UAAM,iBAAiB,MAAM;AAC3B,iBAAW,QAAQ,CAAC,WAAW;AAAA,IAEjC;AAEA,UAAM,gBAAgB,CAAC,UAAU;AAC/B,UAAI,CAAC,MAAO,QAAO;AAEnB,UAAI,MAAM,QAAQ;AAChB,YAAI,OAAO,MAAM,WAAW,UAAU;AACpC,iBAAO,MAAM,OAAO,QAAQ;AAAA,QAC9B;AACA,eAAO,MAAM;AAAA,MACf;AACA,aAAO;AAAA,IACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"MusicPlayer.vue.cjs","sources":["../../../../../../../src/modules/music/components/player/MusicPlayer.vue"],"sourcesContent":["<!-- components/player/MusicPlayer.vue -->\n<template>\n <div class=\"player-container\">\n <div class=\"player\">\n <!-- Track Info Section -->\n <div class=\"track-info\">\n <div class=\"track-image\">\n <Media \n :url=\"currentTrack?.coverUrl || (currentTrack?.album && currentTrack.album.coverUrl) || '/assets/placeholder-track.jpg'\" \n class=\"track-image-media\"\n />\n </div>\n <div class=\"track-details\">\n <h3 class=\"track-title\">{{ currentTrack?.title || 'No track playing' }}</h3>\n <p class=\"track-artist\">{{ getArtistName(currentTrack) }}</p>\n </div>\n <Button \n @click=\"toggleFavorite\" \n class=\"like-btn\"\n :class=\"{ liked: isFavorite }\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconLike class=\"like-icon\"/>\n </Button>\n </div>\n\n <!-- Control Section -->\n <div class=\"controls\">\n <div class=\"control-buttons\">\n <Button \n @click=\"toggleShuffle\" \n class=\"control-btn secondary\"\n :class=\"{ active: shuffle }\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconShuffle fill=\"rgb(var(--black))\" class=\"control-icon\"/>\n </Button>\n \n <Button \n @click=\"playPrevious\" \n class=\"control-btn secondary\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconPrevious fill=\"rgb(var(--black))\" class=\"control-icon\"/>\n </Button>\n \n <Button \n @click=\"togglePlay\" \n class=\"control-btn primary\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconPause v-if=\"isPlaying\" fill=\"white\" class=\"play-icon\"/>\n <IconPlay fill=\"white\" v-else class=\"play-icon\"/>\n </Button>\n \n <Button \n @click=\"playNext\" \n class=\"control-btn secondary\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconNext fill=\"rgb(var(--black))\" class=\"control-icon\"/>\n </Button>\n \n <Button \n @click=\"toggleRepeat\" \n class=\"control-btn secondary\"\n :class=\"{ active: repeat !== 'off' }\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconRepeat fill=\"rgb(var(--black))\" class=\"control-icon\"/>\n </Button>\n </div>\n \n <!-- Progress Bar -->\n <div class=\"progress-section\">\n <TrackProgress />\n </div>\n </div>\n\n <!-- Volume Section -->\n <div class=\"volume-section\">\n <Button \n @click=\"toggleMute\" \n class=\"volume-btn\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconVolumeMute fill=\"rgb(var(--black))\" v-if=\"muted || volume < 0.005\" class=\"volume-icon\"/>\n <!-- <IconVolumeHalf fill=\"rgb(var(--black))\" v-else-if=\"!muted && volume > 0\" class=\"volume-icon\"/> -->\n <IconUnMute fill=\"rgb(var(--black))\" v-else class=\"volume-icon\"/>\n </Button>\n \n <div class=\"volume-slider\">\n <VolumeControl />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { computed, ref } from 'vue';\nimport Media from '@martyrs/src/components/Media/Media.vue';\nimport Button from '@martyrs/src/components/Button/Button.vue';\nimport TrackProgress from './TrackProgress.vue';\nimport VolumeControl from './VolumeControl.vue';\n\n// Import icons\nimport IconPlay from '@martyrs/src/modules/icons/navigation/IconPlay.vue';\nimport IconPause from '@martyrs/src/modules/icons/navigation/IconPause.vue';\nimport IconNext from '@martyrs/src/modules/icons/navigation/IconChevronRight.vue';\nimport IconPrevious from '@martyrs/src/modules/icons/navigation/IconChevronLeft.vue';\nimport IconShuffle from '@martyrs/src/modules/icons/navigation/IconShuffle.vue';\nimport IconRepeat from '@martyrs/src/modules/icons/navigation/IconRefresh.vue';\nimport IconLike from '@martyrs/src/modules/icons/navigation/IconLike.vue';\nimport IconVolume from '@martyrs/src/modules/icons/navigation/IconVolume.vue';\nimport IconUnMute from '@martyrs/src/modules/icons/navigation/IconUnMute.vue';\nimport IconVolumeHalf from '@martyrs/src/modules/icons/navigation/IconVolume.vue';\nimport IconVolumeMute from '@martyrs/src/modules/icons/navigation/IconMute.vue';\n\n// Import player store\nimport { state as playerState, actions as playerActions } from '../../store/player.js';\n\n// State\nconst isFavorite = ref(false);\n\n// Computed properties\nconst currentTrack = computed(() => playerState.currentTrack);\nconst isPlaying = computed(() => playerState.isPlaying);\nconst volume = computed(() => playerState.volume);\nconst muted = computed(() => playerState.muted);\nconst shuffle = computed(() => playerState.shuffle);\nconst repeat = computed(() => playerState.repeat);\n\n// Methods\nconst togglePlay = () => {\n playerActions.togglePlay();\n};\n\nconst playNext = () => {\n playerActions.playNext();\n};\n\nconst playPrevious = () => {\n playerActions.playPrevious();\n};\n\nconst toggleShuffle = () => {\n playerActions.toggleShuffle();\n};\n\nconst toggleRepeat = () => {\n playerActions.toggleRepeat();\n};\n\nconst toggleMute = () => {\n playerActions.toggleMute();\n};\n\nconst toggleFavorite = () => {\n isFavorite.value = !isFavorite.value;\n // Implement favorite track logic here\n};\n\nconst getArtistName = (track) => {\n if (!track) return 'Unknown Artist';\n \n if (track.artist) {\n if (typeof track.artist === 'object') {\n return track.artist.name || 'Unknown Artist';\n }\n return track.artist;\n }\n return 'Unknown Artist';\n};\n</script>\n\n<style scoped>\n.player-container {\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 1000;\n background: linear-gradient(135deg, rgb(var(--white)) 0%, rgb(var(--light)));\n border-top: 1px solid rgb(var(--light));\n backdrop-filter: blur(10px);\n}\n\n.player {\n display: grid;\n grid-template-columns: 1fr 2fr 1fr;\n align-items: center;\n padding: 12px 16px;\n gap: 16px;\n height: 90px;\n max-width: 100%;\n}\n\n/* Track Info Section */\n.track-info {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.track-image {\n width: 56px;\n height: 56px;\n border-radius: 4px;\n overflow: hidden;\n flex-shrink: 0;\n}\n\n.track-image-media {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transition: transform 0.3s ease;\n}\n\n.track-image:hover .track-image-media {\n transform: scale(1.05);\n}\n\n.track-details {\n min-width: 0;\n flex: 1;\n}\n\n.track-title {\n font-size: 14px;\n font-weight: 600;\n color: rgb(var(--black));\n margin: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n line-height: 1.2;\n}\n\n.track-artist {\n font-size: 12px;\n color: rgb(var(--grey));\n margin: 2px 0 0 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.like-btn {\n background: none;\n border: none;\n color: rgb(var(--grey));\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.like-icon {\n width: 16px;\n height: 16px;\n}\n\n.like-btn:hover {\n color: rgb(var(--black));\n background: rgba(var(--black),0.1);\n}\n\n.like-btn.liked {\n color: rgb(var(--main));\n}\n\n.like-btn.liked .like-icon {\n fill: rgb(var(--main));\n}\n\n.like-btn.liked:hover {\n color: rgb(var(--main));\n opacity: 0.8;\n}\n\n/* Controls Section */\n.controls {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n width: 100%;\n}\n\n.control-buttons {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.control-btn {\n background: none;\n border: none;\n color: rgb(var(--grey));\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.control-icon {\n width: 16px;\n height: 16px;\n}\n\n.control-btn.primary {\n background: rgb(var(--second));\n color: rgb(var(--white));\n width: 32px;\n height: 32px;\n}\n\n.play-icon {\n width: 14px;\n height: 14px;\n fill: rgb(var(--white));\n}\n\n.control-btn.primary:hover {\n background: rgb(var(--second));\n transform: scale(1.06);\n}\n\n.control-btn.secondary:hover {\n color: rgb(var(--white));\n background: rgba(var(--black),0.1);\n}\n\n.control-btn.secondary:hover .control-icon {\n fill: rgb(var(--white));\n}\n\n.control-btn.active {\n color: rgb(var(--main));\n background: rgba(var(--second),0.1);\n}\n\n.control-btn.active .control-icon {\n fill: rgb(var(--main));\n}\n\n.control-btn.active:hover {\n color: rgb(var(--main));\n opacity: 0.8;\n background: rgba(var(--second),0.2);\n}\n\n/* Progress Section */\n.progress-section {\n width: 100%;\n max-width: 600px;\n}\n\n/* Volume Section */\n.volume-section {\n display: flex;\n align-items: center;\n gap: 12px;\n justify-content: flex-end;\n}\n\n.volume-btn {\n background: none;\n border: none;\n color: rgb(var(--grey));\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.volume-icon {\n width: 16px;\n height: 16px;\n}\n\n.volume-btn:hover {\n color: rgb(var(--white));\n background: rgba(var(--white),0.1);\n}\n\n.volume-btn:hover .volume-icon {\n fill: rgb(var(--white));\n}\n\n.volume-slider {\n width: 100px;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .player {\n grid-template-columns: 1fr;\n grid-template-rows: auto auto auto;\n height: auto;\n padding: 8px 12px 12px;\n gap: 12px;\n }\n\n .track-info {\n order: 1;\n }\n\n .controls {\n order: 2;\n }\n\n .volume-section {\n order: 3;\n justify-content: center;\n }\n\n .volume-slider {\n width: 120px;\n }\n\n .progress-section {\n max-width: 100%;\n }\n}\n\n/* Animations */\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.player-container {\n animation: fadeIn 0.3s ease-out;\n}\n\n@keyframes pulse {\n 0% {\n transform: scale(1);\n }\n 50% {\n transform: scale(1.05);\n }\n 100% {\n transform: scale(1);\n }\n}\n\n.control-btn.primary:active {\n animation: pulse 0.3s ease;\n}\n</style>"],"names":["ref","computed","playerState","playerActions"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkIA,UAAM,aAAaA,IAAAA,IAAI,KAAK;AAG5B,UAAM,eAAeC,IAAAA,SAAS,MAAMC,OAAAA,MAAY,YAAY;AAC5D,UAAM,YAAYD,IAAAA,SAAS,MAAMC,OAAAA,MAAY,SAAS;AACtD,UAAM,SAASD,IAAAA,SAAS,MAAMC,OAAAA,MAAY,MAAM;AAChD,UAAM,QAAQD,IAAAA,SAAS,MAAMC,OAAAA,MAAY,KAAK;AAC9C,UAAM,UAAUD,IAAAA,SAAS,MAAMC,OAAAA,MAAY,OAAO;AAClD,UAAM,SAASD,IAAAA,SAAS,MAAMC,OAAAA,MAAY,MAAM;AAGhD,UAAM,aAAa,MAAM;AACvBC,aAAAA,QAAc,WAAU;AAAA,IAC1B;AAEA,UAAM,WAAW,MAAM;AACrBA,aAAAA,QAAc,SAAQ;AAAA,IACxB;AAEA,UAAM,eAAe,MAAM;AACzBA,aAAAA,QAAc,aAAY;AAAA,IAC5B;AAEA,UAAM,gBAAgB,MAAM;AAC1BA,aAAAA,QAAc,cAAa;AAAA,IAC7B;AAEA,UAAM,eAAe,MAAM;AACzBA,aAAAA,QAAc,aAAY;AAAA,IAC5B;AAEA,UAAM,aAAa,MAAM;AACvBA,aAAAA,QAAc,WAAU;AAAA,IAC1B;AAEA,UAAM,iBAAiB,MAAM;AAC3B,iBAAW,QAAQ,CAAC,WAAW;AAAA,IAEjC;AAEA,UAAM,gBAAgB,CAAC,UAAU;AAC/B,UAAI,CAAC,MAAO,QAAO;AAEnB,UAAI,MAAM,QAAQ;AAChB,YAAI,OAAO,MAAM,WAAW,UAAU;AACpC,iBAAO,MAAM,OAAO,QAAQ;AAAA,QAC9B;AACA,eAAO,MAAM;AAAA,MACf;AACA,aAAO;AAAA,IACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ref, computed, createElementBlock, openBlock, createElementVNode, createVNode, toDisplayString, normalizeClass, withCtx, createBlock } from "vue";
|
|
2
2
|
import Media from "../../../../components/Media/Media.vue.js";
|
|
3
|
-
import _sfc_main$1 from "../../../../components/Button/Button.
|
|
3
|
+
import _sfc_main$1 from "../../../../components/Button/Button.vue2.js";
|
|
4
4
|
import TrackProgress from "./TrackProgress.vue.js";
|
|
5
5
|
import VolumeControl from "./VolumeControl.vue.js";
|
|
6
6
|
import _sfc_main$5 from "../../../icons/navigation/IconPlay.vue.js";
|
|
@@ -10,8 +10,8 @@ import IconPrevious from "../../../icons/navigation/IconChevronLeft.vue.js";
|
|
|
10
10
|
import _sfc_main$3 from "../../../icons/navigation/IconShuffle.vue.js";
|
|
11
11
|
import _sfc_main$6 from "../../../icons/navigation/IconRefresh.vue.js";
|
|
12
12
|
import _sfc_main$2 from "../../../icons/navigation/IconLike.vue.js";
|
|
13
|
-
import _sfc_main$
|
|
14
|
-
import _sfc_main$
|
|
13
|
+
import _sfc_main$8 from "../../../icons/navigation/IconUnMute.vue.js";
|
|
14
|
+
import _sfc_main$7 from "../../../icons/navigation/IconMute.vue.js";
|
|
15
15
|
import { state, actions } from "../../store/player.js";
|
|
16
16
|
/* empty css */
|
|
17
17
|
import _export_sfc from "../../../../../../_virtual/_plugin-vue_export-helper.js";
|
|
@@ -89,10 +89,7 @@ const _sfc_main = {
|
|
|
89
89
|
showSucces: false
|
|
90
90
|
}, {
|
|
91
91
|
default: withCtx(() => [
|
|
92
|
-
createVNode(_sfc_main$2, {
|
|
93
|
-
fill: "rgb(var(--white))",
|
|
94
|
-
class: "like-icon"
|
|
95
|
-
})
|
|
92
|
+
createVNode(_sfc_main$2, { class: "like-icon" })
|
|
96
93
|
]),
|
|
97
94
|
_: 1
|
|
98
95
|
}, 8, ["class"])
|
|
@@ -107,7 +104,7 @@ const _sfc_main = {
|
|
|
107
104
|
}, {
|
|
108
105
|
default: withCtx(() => [
|
|
109
106
|
createVNode(_sfc_main$3, {
|
|
110
|
-
fill: "rgb(var(--
|
|
107
|
+
fill: "rgb(var(--black))",
|
|
111
108
|
class: "control-icon"
|
|
112
109
|
})
|
|
113
110
|
]),
|
|
@@ -121,7 +118,7 @@ const _sfc_main = {
|
|
|
121
118
|
}, {
|
|
122
119
|
default: withCtx(() => [
|
|
123
120
|
createVNode(IconPrevious, {
|
|
124
|
-
fill: "rgb(var(--
|
|
121
|
+
fill: "rgb(var(--black))",
|
|
125
122
|
class: "control-icon"
|
|
126
123
|
})
|
|
127
124
|
]),
|
|
@@ -136,9 +133,11 @@ const _sfc_main = {
|
|
|
136
133
|
default: withCtx(() => [
|
|
137
134
|
isPlaying.value ? (openBlock(), createBlock(_sfc_main$4, {
|
|
138
135
|
key: 0,
|
|
136
|
+
fill: "white",
|
|
139
137
|
class: "play-icon"
|
|
140
138
|
})) : (openBlock(), createBlock(_sfc_main$5, {
|
|
141
139
|
key: 1,
|
|
140
|
+
fill: "white",
|
|
142
141
|
class: "play-icon"
|
|
143
142
|
}))
|
|
144
143
|
]),
|
|
@@ -152,7 +151,7 @@ const _sfc_main = {
|
|
|
152
151
|
}, {
|
|
153
152
|
default: withCtx(() => [
|
|
154
153
|
createVNode(IconNext, {
|
|
155
|
-
fill: "rgb(var(--
|
|
154
|
+
fill: "rgb(var(--black))",
|
|
156
155
|
class: "control-icon"
|
|
157
156
|
})
|
|
158
157
|
]),
|
|
@@ -166,7 +165,7 @@ const _sfc_main = {
|
|
|
166
165
|
}, {
|
|
167
166
|
default: withCtx(() => [
|
|
168
167
|
createVNode(_sfc_main$6, {
|
|
169
|
-
fill: "rgb(var(--
|
|
168
|
+
fill: "rgb(var(--black))",
|
|
170
169
|
class: "control-icon"
|
|
171
170
|
})
|
|
172
171
|
]),
|
|
@@ -185,17 +184,13 @@ const _sfc_main = {
|
|
|
185
184
|
showSucces: false
|
|
186
185
|
}, {
|
|
187
186
|
default: withCtx(() => [
|
|
188
|
-
|
|
187
|
+
muted.value || volume.value < 5e-3 ? (openBlock(), createBlock(_sfc_main$7, {
|
|
189
188
|
key: 0,
|
|
190
|
-
fill: "rgb(var(--
|
|
191
|
-
class: "volume-icon"
|
|
192
|
-
})) : !muted.value && volume.value > 0 ? (openBlock(), createBlock(_sfc_main$7, {
|
|
193
|
-
key: 1,
|
|
194
|
-
fill: "rgb(var(--white))",
|
|
189
|
+
fill: "rgb(var(--black))",
|
|
195
190
|
class: "volume-icon"
|
|
196
191
|
})) : (openBlock(), createBlock(_sfc_main$8, {
|
|
197
|
-
key:
|
|
198
|
-
fill: "rgb(var(--
|
|
192
|
+
key: 1,
|
|
193
|
+
fill: "rgb(var(--black))",
|
|
199
194
|
class: "volume-icon"
|
|
200
195
|
}))
|
|
201
196
|
]),
|
|
@@ -210,7 +205,7 @@ const _sfc_main = {
|
|
|
210
205
|
};
|
|
211
206
|
}
|
|
212
207
|
};
|
|
213
|
-
const MusicPlayer = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
208
|
+
const MusicPlayer = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-f4886dd7"]]);
|
|
214
209
|
export {
|
|
215
210
|
MusicPlayer as default
|
|
216
211
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MusicPlayer.vue.js","sources":["../../../../../../../src/modules/music/components/player/MusicPlayer.vue"],"sourcesContent":["<!-- components/player/MusicPlayer.vue -->\n<template>\n <div class=\"player-container\">\n <div class=\"player\">\n <!-- Track Info Section -->\n <div class=\"track-info\">\n <div class=\"track-image\">\n <Media \n :url=\"currentTrack?.coverUrl || (currentTrack?.album && currentTrack.album.coverUrl) || '/assets/placeholder-track.jpg'\" \n class=\"track-image-media\"\n />\n </div>\n <div class=\"track-details\">\n <h3 class=\"track-title\">{{ currentTrack?.title || 'No track playing' }}</h3>\n <p class=\"track-artist\">{{ getArtistName(currentTrack) }}</p>\n </div>\n <Button \n @click=\"toggleFavorite\" \n class=\"like-btn\"\n :class=\"{ liked: isFavorite }\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconLike fill=\"rgb(var(--white))\" class=\"like-icon\"/>\n </Button>\n </div>\n\n <!-- Control Section -->\n <div class=\"controls\">\n <div class=\"control-buttons\">\n <Button \n @click=\"toggleShuffle\" \n class=\"control-btn secondary\"\n :class=\"{ active: shuffle }\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconShuffle fill=\"rgb(var(--white))\" class=\"control-icon\"/>\n </Button>\n \n <Button \n @click=\"playPrevious\" \n class=\"control-btn secondary\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconPrevious fill=\"rgb(var(--white))\" class=\"control-icon\"/>\n </Button>\n \n <Button \n @click=\"togglePlay\" \n class=\"control-btn primary\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconPause v-if=\"isPlaying\" class=\"play-icon\"/>\n <IconPlay v-else class=\"play-icon\"/>\n </Button>\n \n <Button \n @click=\"playNext\" \n class=\"control-btn secondary\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconNext fill=\"rgb(var(--white))\" class=\"control-icon\"/>\n </Button>\n \n <Button \n @click=\"toggleRepeat\" \n class=\"control-btn secondary\"\n :class=\"{ active: repeat !== 'off' }\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconRepeat fill=\"rgb(var(--white))\" class=\"control-icon\"/>\n </Button>\n </div>\n \n <!-- Progress Bar -->\n <div class=\"progress-section\">\n <TrackProgress />\n </div>\n </div>\n\n <!-- Volume Section -->\n <div class=\"volume-section\">\n <Button \n @click=\"toggleMute\" \n class=\"volume-btn\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconVolume fill=\"rgb(var(--white))\" v-if=\"!muted && volume > 0.5\" class=\"volume-icon\"/>\n <IconVolumeHalf fill=\"rgb(var(--white))\" v-else-if=\"!muted && volume > 0\" class=\"volume-icon\"/>\n <IconVolumeMute fill=\"rgb(var(--white))\" v-else class=\"volume-icon\"/>\n </Button>\n \n <div class=\"volume-slider\">\n <VolumeControl />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { computed, ref } from 'vue';\nimport Media from '@martyrs/src/components/Media/Media.vue';\nimport Button from '@martyrs/src/components/Button/Button.vue';\nimport TrackProgress from './TrackProgress.vue';\nimport VolumeControl from './VolumeControl.vue';\n\n// Import icons\nimport IconPlay from '@martyrs/src/modules/icons/navigation/IconPlay.vue';\nimport IconPause from '@martyrs/src/modules/icons/navigation/IconPause.vue';\nimport IconNext from '@martyrs/src/modules/icons/navigation/IconChevronRight.vue';\nimport IconPrevious from '@martyrs/src/modules/icons/navigation/IconChevronLeft.vue';\nimport IconShuffle from '@martyrs/src/modules/icons/navigation/IconShuffle.vue';\nimport IconRepeat from '@martyrs/src/modules/icons/navigation/IconRefresh.vue';\nimport IconLike from '@martyrs/src/modules/icons/navigation/IconLike.vue';\nimport IconVolume from '@martyrs/src/modules/icons/navigation/IconVolume.vue';\nimport IconVolumeHalf from '@martyrs/src/modules/icons/navigation/IconVolume.vue';\nimport IconVolumeMute from '@martyrs/src/modules/icons/navigation/IconMute.vue';\n\n// Import player store\nimport { state as playerState, actions as playerActions } from '../../store/player.js';\n\n// State\nconst isFavorite = ref(false);\n\n// Computed properties\nconst currentTrack = computed(() => playerState.currentTrack);\nconst isPlaying = computed(() => playerState.isPlaying);\nconst volume = computed(() => playerState.volume);\nconst muted = computed(() => playerState.muted);\nconst shuffle = computed(() => playerState.shuffle);\nconst repeat = computed(() => playerState.repeat);\n\n// Methods\nconst togglePlay = () => {\n playerActions.togglePlay();\n};\n\nconst playNext = () => {\n playerActions.playNext();\n};\n\nconst playPrevious = () => {\n playerActions.playPrevious();\n};\n\nconst toggleShuffle = () => {\n playerActions.toggleShuffle();\n};\n\nconst toggleRepeat = () => {\n playerActions.toggleRepeat();\n};\n\nconst toggleMute = () => {\n playerActions.toggleMute();\n};\n\nconst toggleFavorite = () => {\n isFavorite.value = !isFavorite.value;\n // Implement favorite track logic here\n};\n\nconst getArtistName = (track) => {\n if (!track) return 'Unknown Artist';\n \n if (track.artist) {\n if (typeof track.artist === 'object') {\n return track.artist.name || 'Unknown Artist';\n }\n return track.artist;\n }\n return 'Unknown Artist';\n};\n</script>\n\n<style scoped>\n.player-container {\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 1000;\n background: linear-gradient(135deg, rgb(24, 24, 24) 0%, rgb(18, 18, 18) 100%);\n border-top: 1px solid rgb(40, 40, 40);\n backdrop-filter: blur(10px);\n}\n\n.player {\n display: grid;\n grid-template-columns: 1fr 2fr 1fr;\n align-items: center;\n padding: 12px 16px;\n gap: 16px;\n height: 90px;\n max-width: 100%;\n}\n\n/* Track Info Section */\n.track-info {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.track-image {\n width: 56px;\n height: 56px;\n border-radius: 4px;\n overflow: hidden;\n flex-shrink: 0;\n}\n\n.track-image-media {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transition: transform 0.3s ease;\n}\n\n.track-image:hover .track-image-media {\n transform: scale(1.05);\n}\n\n.track-details {\n min-width: 0;\n flex: 1;\n}\n\n.track-title {\n font-size: 14px;\n font-weight: 600;\n color: rgb(var(--white));\n margin: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n line-height: 1.2;\n}\n\n.track-artist {\n font-size: 12px;\n color: rgb(var(--grey));\n margin: 2px 0 0 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.like-btn {\n background: none;\n border: none;\n color: rgb(var(--grey));\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.like-icon {\n width: 16px;\n height: 16px;\n}\n\n.like-btn:hover {\n color: rgb(var(--white));\n background: rgba(255, 255, 255, 0.1);\n}\n\n.like-btn.liked {\n color: rgb(var(--main));\n}\n\n.like-btn.liked .like-icon {\n fill: rgb(var(--main));\n}\n\n.like-btn.liked:hover {\n color: rgb(var(--main));\n opacity: 0.8;\n}\n\n/* Controls Section */\n.controls {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n width: 100%;\n}\n\n.control-buttons {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.control-btn {\n background: none;\n border: none;\n color: rgb(var(--grey));\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.control-icon {\n width: 16px;\n height: 16px;\n}\n\n.control-btn.primary {\n background: rgb(var(--white));\n color: rgb(var(--black));\n width: 32px;\n height: 32px;\n}\n\n.play-icon {\n width: 14px;\n height: 14px;\n fill: rgb(var(--black));\n}\n\n.control-btn.primary:hover {\n background: rgb(240, 240, 240);\n transform: scale(1.06);\n}\n\n.control-btn.secondary:hover {\n color: rgb(var(--white));\n background: rgba(255, 255, 255, 0.1);\n}\n\n.control-btn.secondary:hover .control-icon {\n fill: rgb(var(--white));\n}\n\n.control-btn.active {\n color: rgb(var(--main));\n}\n\n.control-btn.active .control-icon {\n fill: rgb(var(--main));\n}\n\n.control-btn.active:hover {\n color: rgb(var(--main));\n opacity: 0.8;\n}\n\n/* Progress Section */\n.progress-section {\n width: 100%;\n max-width: 600px;\n}\n\n/* Volume Section */\n.volume-section {\n display: flex;\n align-items: center;\n gap: 12px;\n justify-content: flex-end;\n}\n\n.volume-btn {\n background: none;\n border: none;\n color: rgb(var(--grey));\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.volume-icon {\n width: 16px;\n height: 16px;\n}\n\n.volume-btn:hover {\n color: rgb(var(--white));\n background: rgba(255, 255, 255, 0.1);\n}\n\n.volume-btn:hover .volume-icon {\n fill: rgb(var(--white));\n}\n\n.volume-slider {\n width: 100px;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .player {\n grid-template-columns: 1fr;\n grid-template-rows: auto auto auto;\n height: auto;\n padding: 8px 12px 12px;\n gap: 12px;\n }\n\n .track-info {\n order: 1;\n }\n\n .controls {\n order: 2;\n }\n\n .volume-section {\n order: 3;\n justify-content: center;\n }\n\n .volume-slider {\n width: 120px;\n }\n\n .progress-section {\n max-width: 100%;\n }\n}\n\n/* Animations */\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.player-container {\n animation: fadeIn 0.3s ease-out;\n}\n\n@keyframes pulse {\n 0% {\n transform: scale(1);\n }\n 50% {\n transform: scale(1.05);\n }\n 100% {\n transform: scale(1);\n }\n}\n\n.control-btn.primary:active {\n animation: pulse 0.3s ease;\n}\n</style>"],"names":["playerState","playerActions"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiIA,UAAM,aAAa,IAAI,KAAK;AAG5B,UAAM,eAAe,SAAS,MAAMA,MAAY,YAAY;AAC5D,UAAM,YAAY,SAAS,MAAMA,MAAY,SAAS;AACtD,UAAM,SAAS,SAAS,MAAMA,MAAY,MAAM;AAChD,UAAM,QAAQ,SAAS,MAAMA,MAAY,KAAK;AAC9C,UAAM,UAAU,SAAS,MAAMA,MAAY,OAAO;AAClD,UAAM,SAAS,SAAS,MAAMA,MAAY,MAAM;AAGhD,UAAM,aAAa,MAAM;AACvBC,cAAc,WAAU;AAAA,IAC1B;AAEA,UAAM,WAAW,MAAM;AACrBA,cAAc,SAAQ;AAAA,IACxB;AAEA,UAAM,eAAe,MAAM;AACzBA,cAAc,aAAY;AAAA,IAC5B;AAEA,UAAM,gBAAgB,MAAM;AAC1BA,cAAc,cAAa;AAAA,IAC7B;AAEA,UAAM,eAAe,MAAM;AACzBA,cAAc,aAAY;AAAA,IAC5B;AAEA,UAAM,aAAa,MAAM;AACvBA,cAAc,WAAU;AAAA,IAC1B;AAEA,UAAM,iBAAiB,MAAM;AAC3B,iBAAW,QAAQ,CAAC,WAAW;AAAA,IAEjC;AAEA,UAAM,gBAAgB,CAAC,UAAU;AAC/B,UAAI,CAAC,MAAO,QAAO;AAEnB,UAAI,MAAM,QAAQ;AAChB,YAAI,OAAO,MAAM,WAAW,UAAU;AACpC,iBAAO,MAAM,OAAO,QAAQ;AAAA,QAC9B;AACA,eAAO,MAAM;AAAA,MACf;AACA,aAAO;AAAA,IACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"MusicPlayer.vue.js","sources":["../../../../../../../src/modules/music/components/player/MusicPlayer.vue"],"sourcesContent":["<!-- components/player/MusicPlayer.vue -->\n<template>\n <div class=\"player-container\">\n <div class=\"player\">\n <!-- Track Info Section -->\n <div class=\"track-info\">\n <div class=\"track-image\">\n <Media \n :url=\"currentTrack?.coverUrl || (currentTrack?.album && currentTrack.album.coverUrl) || '/assets/placeholder-track.jpg'\" \n class=\"track-image-media\"\n />\n </div>\n <div class=\"track-details\">\n <h3 class=\"track-title\">{{ currentTrack?.title || 'No track playing' }}</h3>\n <p class=\"track-artist\">{{ getArtistName(currentTrack) }}</p>\n </div>\n <Button \n @click=\"toggleFavorite\" \n class=\"like-btn\"\n :class=\"{ liked: isFavorite }\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconLike class=\"like-icon\"/>\n </Button>\n </div>\n\n <!-- Control Section -->\n <div class=\"controls\">\n <div class=\"control-buttons\">\n <Button \n @click=\"toggleShuffle\" \n class=\"control-btn secondary\"\n :class=\"{ active: shuffle }\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconShuffle fill=\"rgb(var(--black))\" class=\"control-icon\"/>\n </Button>\n \n <Button \n @click=\"playPrevious\" \n class=\"control-btn secondary\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconPrevious fill=\"rgb(var(--black))\" class=\"control-icon\"/>\n </Button>\n \n <Button \n @click=\"togglePlay\" \n class=\"control-btn primary\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconPause v-if=\"isPlaying\" fill=\"white\" class=\"play-icon\"/>\n <IconPlay fill=\"white\" v-else class=\"play-icon\"/>\n </Button>\n \n <Button \n @click=\"playNext\" \n class=\"control-btn secondary\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconNext fill=\"rgb(var(--black))\" class=\"control-icon\"/>\n </Button>\n \n <Button \n @click=\"toggleRepeat\" \n class=\"control-btn secondary\"\n :class=\"{ active: repeat !== 'off' }\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconRepeat fill=\"rgb(var(--black))\" class=\"control-icon\"/>\n </Button>\n </div>\n \n <!-- Progress Bar -->\n <div class=\"progress-section\">\n <TrackProgress />\n </div>\n </div>\n\n <!-- Volume Section -->\n <div class=\"volume-section\">\n <Button \n @click=\"toggleMute\" \n class=\"volume-btn\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n <IconVolumeMute fill=\"rgb(var(--black))\" v-if=\"muted || volume < 0.005\" class=\"volume-icon\"/>\n <!-- <IconVolumeHalf fill=\"rgb(var(--black))\" v-else-if=\"!muted && volume > 0\" class=\"volume-icon\"/> -->\n <IconUnMute fill=\"rgb(var(--black))\" v-else class=\"volume-icon\"/>\n </Button>\n \n <div class=\"volume-slider\">\n <VolumeControl />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { computed, ref } from 'vue';\nimport Media from '@martyrs/src/components/Media/Media.vue';\nimport Button from '@martyrs/src/components/Button/Button.vue';\nimport TrackProgress from './TrackProgress.vue';\nimport VolumeControl from './VolumeControl.vue';\n\n// Import icons\nimport IconPlay from '@martyrs/src/modules/icons/navigation/IconPlay.vue';\nimport IconPause from '@martyrs/src/modules/icons/navigation/IconPause.vue';\nimport IconNext from '@martyrs/src/modules/icons/navigation/IconChevronRight.vue';\nimport IconPrevious from '@martyrs/src/modules/icons/navigation/IconChevronLeft.vue';\nimport IconShuffle from '@martyrs/src/modules/icons/navigation/IconShuffle.vue';\nimport IconRepeat from '@martyrs/src/modules/icons/navigation/IconRefresh.vue';\nimport IconLike from '@martyrs/src/modules/icons/navigation/IconLike.vue';\nimport IconVolume from '@martyrs/src/modules/icons/navigation/IconVolume.vue';\nimport IconUnMute from '@martyrs/src/modules/icons/navigation/IconUnMute.vue';\nimport IconVolumeHalf from '@martyrs/src/modules/icons/navigation/IconVolume.vue';\nimport IconVolumeMute from '@martyrs/src/modules/icons/navigation/IconMute.vue';\n\n// Import player store\nimport { state as playerState, actions as playerActions } from '../../store/player.js';\n\n// State\nconst isFavorite = ref(false);\n\n// Computed properties\nconst currentTrack = computed(() => playerState.currentTrack);\nconst isPlaying = computed(() => playerState.isPlaying);\nconst volume = computed(() => playerState.volume);\nconst muted = computed(() => playerState.muted);\nconst shuffle = computed(() => playerState.shuffle);\nconst repeat = computed(() => playerState.repeat);\n\n// Methods\nconst togglePlay = () => {\n playerActions.togglePlay();\n};\n\nconst playNext = () => {\n playerActions.playNext();\n};\n\nconst playPrevious = () => {\n playerActions.playPrevious();\n};\n\nconst toggleShuffle = () => {\n playerActions.toggleShuffle();\n};\n\nconst toggleRepeat = () => {\n playerActions.toggleRepeat();\n};\n\nconst toggleMute = () => {\n playerActions.toggleMute();\n};\n\nconst toggleFavorite = () => {\n isFavorite.value = !isFavorite.value;\n // Implement favorite track logic here\n};\n\nconst getArtistName = (track) => {\n if (!track) return 'Unknown Artist';\n \n if (track.artist) {\n if (typeof track.artist === 'object') {\n return track.artist.name || 'Unknown Artist';\n }\n return track.artist;\n }\n return 'Unknown Artist';\n};\n</script>\n\n<style scoped>\n.player-container {\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 1000;\n background: linear-gradient(135deg, rgb(var(--white)) 0%, rgb(var(--light)));\n border-top: 1px solid rgb(var(--light));\n backdrop-filter: blur(10px);\n}\n\n.player {\n display: grid;\n grid-template-columns: 1fr 2fr 1fr;\n align-items: center;\n padding: 12px 16px;\n gap: 16px;\n height: 90px;\n max-width: 100%;\n}\n\n/* Track Info Section */\n.track-info {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.track-image {\n width: 56px;\n height: 56px;\n border-radius: 4px;\n overflow: hidden;\n flex-shrink: 0;\n}\n\n.track-image-media {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transition: transform 0.3s ease;\n}\n\n.track-image:hover .track-image-media {\n transform: scale(1.05);\n}\n\n.track-details {\n min-width: 0;\n flex: 1;\n}\n\n.track-title {\n font-size: 14px;\n font-weight: 600;\n color: rgb(var(--black));\n margin: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n line-height: 1.2;\n}\n\n.track-artist {\n font-size: 12px;\n color: rgb(var(--grey));\n margin: 2px 0 0 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.like-btn {\n background: none;\n border: none;\n color: rgb(var(--grey));\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.like-icon {\n width: 16px;\n height: 16px;\n}\n\n.like-btn:hover {\n color: rgb(var(--black));\n background: rgba(var(--black),0.1);\n}\n\n.like-btn.liked {\n color: rgb(var(--main));\n}\n\n.like-btn.liked .like-icon {\n fill: rgb(var(--main));\n}\n\n.like-btn.liked:hover {\n color: rgb(var(--main));\n opacity: 0.8;\n}\n\n/* Controls Section */\n.controls {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n width: 100%;\n}\n\n.control-buttons {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.control-btn {\n background: none;\n border: none;\n color: rgb(var(--grey));\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.control-icon {\n width: 16px;\n height: 16px;\n}\n\n.control-btn.primary {\n background: rgb(var(--second));\n color: rgb(var(--white));\n width: 32px;\n height: 32px;\n}\n\n.play-icon {\n width: 14px;\n height: 14px;\n fill: rgb(var(--white));\n}\n\n.control-btn.primary:hover {\n background: rgb(var(--second));\n transform: scale(1.06);\n}\n\n.control-btn.secondary:hover {\n color: rgb(var(--white));\n background: rgba(var(--black),0.1);\n}\n\n.control-btn.secondary:hover .control-icon {\n fill: rgb(var(--white));\n}\n\n.control-btn.active {\n color: rgb(var(--main));\n background: rgba(var(--second),0.1);\n}\n\n.control-btn.active .control-icon {\n fill: rgb(var(--main));\n}\n\n.control-btn.active:hover {\n color: rgb(var(--main));\n opacity: 0.8;\n background: rgba(var(--second),0.2);\n}\n\n/* Progress Section */\n.progress-section {\n width: 100%;\n max-width: 600px;\n}\n\n/* Volume Section */\n.volume-section {\n display: flex;\n align-items: center;\n gap: 12px;\n justify-content: flex-end;\n}\n\n.volume-btn {\n background: none;\n border: none;\n color: rgb(var(--grey));\n cursor: pointer;\n padding: 8px;\n border-radius: 50%;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.volume-icon {\n width: 16px;\n height: 16px;\n}\n\n.volume-btn:hover {\n color: rgb(var(--white));\n background: rgba(var(--white),0.1);\n}\n\n.volume-btn:hover .volume-icon {\n fill: rgb(var(--white));\n}\n\n.volume-slider {\n width: 100px;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .player {\n grid-template-columns: 1fr;\n grid-template-rows: auto auto auto;\n height: auto;\n padding: 8px 12px 12px;\n gap: 12px;\n }\n\n .track-info {\n order: 1;\n }\n\n .controls {\n order: 2;\n }\n\n .volume-section {\n order: 3;\n justify-content: center;\n }\n\n .volume-slider {\n width: 120px;\n }\n\n .progress-section {\n max-width: 100%;\n }\n}\n\n/* Animations */\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.player-container {\n animation: fadeIn 0.3s ease-out;\n}\n\n@keyframes pulse {\n 0% {\n transform: scale(1);\n }\n 50% {\n transform: scale(1.05);\n }\n 100% {\n transform: scale(1);\n }\n}\n\n.control-btn.primary:active {\n animation: pulse 0.3s ease;\n}\n</style>"],"names":["playerState","playerActions"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkIA,UAAM,aAAa,IAAI,KAAK;AAG5B,UAAM,eAAe,SAAS,MAAMA,MAAY,YAAY;AAC5D,UAAM,YAAY,SAAS,MAAMA,MAAY,SAAS;AACtD,UAAM,SAAS,SAAS,MAAMA,MAAY,MAAM;AAChD,UAAM,QAAQ,SAAS,MAAMA,MAAY,KAAK;AAC9C,UAAM,UAAU,SAAS,MAAMA,MAAY,OAAO;AAClD,UAAM,SAAS,SAAS,MAAMA,MAAY,MAAM;AAGhD,UAAM,aAAa,MAAM;AACvBC,cAAc,WAAU;AAAA,IAC1B;AAEA,UAAM,WAAW,MAAM;AACrBA,cAAc,SAAQ;AAAA,IACxB;AAEA,UAAM,eAAe,MAAM;AACzBA,cAAc,aAAY;AAAA,IAC5B;AAEA,UAAM,gBAAgB,MAAM;AAC1BA,cAAc,cAAa;AAAA,IAC7B;AAEA,UAAM,eAAe,MAAM;AACzBA,cAAc,aAAY;AAAA,IAC5B;AAEA,UAAM,aAAa,MAAM;AACvBA,cAAc,WAAU;AAAA,IAC1B;AAEA,UAAM,iBAAiB,MAAM;AAC3B,iBAAW,QAAQ,CAAC,WAAW;AAAA,IAEjC;AAEA,UAAM,gBAAgB,CAAC,UAAU;AAC/B,UAAI,CAAC,MAAO,QAAO;AAEnB,UAAI,MAAM,QAAQ;AAChB,YAAI,OAAO,MAAM,WAAW,UAAU;AACpC,iBAAO,MAAM,OAAO,QAAQ;AAAA,QAC9B;AACA,eAAO,MAAM;AAAA,MACf;AACA,aAAO;AAAA,IACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -5,7 +5,7 @@ const player = require("../../store/player.cjs");
|
|
|
5
5
|
;/* empty css */
|
|
6
6
|
const _pluginVue_exportHelper = require("../../../../../../_virtual/_plugin-vue_export-helper.cjs");
|
|
7
7
|
const _hoisted_1 = { class: "progress-section" };
|
|
8
|
-
const _hoisted_2 = { class: "time-current" };
|
|
8
|
+
const _hoisted_2 = { class: "time-current t-transp" };
|
|
9
9
|
const _hoisted_3 = { class: "progress-track" };
|
|
10
10
|
const _hoisted_4 = { class: "time-total" };
|
|
11
11
|
const _sfc_main = {
|
|
@@ -84,6 +84,6 @@ const _sfc_main = {
|
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
86
|
};
|
|
87
|
-
const TrackProgress = /* @__PURE__ */ _pluginVue_exportHelper.default(_sfc_main, [["__scopeId", "data-v-
|
|
87
|
+
const TrackProgress = /* @__PURE__ */ _pluginVue_exportHelper.default(_sfc_main, [["__scopeId", "data-v-a338a0bc"]]);
|
|
88
88
|
exports.default = TrackProgress;
|
|
89
89
|
//# sourceMappingURL=TrackProgress.vue.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TrackProgress.vue.cjs","sources":["../../../../../../../src/modules/music/components/player/TrackProgress.vue"],"sourcesContent":["<!-- components/player/TrackProgress.vue -->\n<template>\n <div class=\"progress-section\">\n <span class=\"time-current\">{{ formatTime(currentTime) }}</span>\n <div \n ref=\"progressBarContainer\"\n class=\"progress-bar\"\n @click=\"seek\"\n @mousedown=\"startSeek\"\n @mousemove=\"updateSeekPosition\"\n @mouseup=\"endSeek\"\n @mouseleave=\"endSeek\"\n >\n <div class=\"progress-track\">\n <div \n class=\"progress-fill\" \n :style=\"{ width: progressPercentage + '%' }\"\n ></div>\n <div \n class=\"progress-thumb\"\n :style=\"{ left: progressPercentage + '%' }\"\n ></div>\n </div>\n </div>\n <span class=\"time-total\">{{ formatTime(duration) }}</span>\n </div>\n</template>\n\n<script setup>\nimport { ref, computed, onUnmounted } from 'vue';\n\n// Import player store\nimport { state as playerState, actions as playerActions } from '../../store/player.js';\n\n// Refs\nconst progressBarContainer = ref(null);\nconst isSeeking = ref(false);\nconst seekPosition = ref(0);\n\n// Computed properties\nconst currentTime = computed(() => playerState.currentTime);\nconst duration = computed(() => playerState.duration);\nconst progressPercentage = computed(() => {\n if (!duration.value) return 0;\n return Math.min(100, (currentTime.value / duration.value) * 100);\n});\n\n// Methods\nconst formatTime = (seconds) => {\n if (!seconds) return '0:00';\n \n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = Math.floor(seconds % 60);\n \n return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;\n};\n\nconst calculateSeekTime = (event) => {\n if (!progressBarContainer.value || !duration.value) return 0;\n \n const rect = progressBarContainer.value.getBoundingClientRect();\n const offsetX = event.clientX - rect.left;\n const percentage = Math.max(0, Math.min(1, offsetX / rect.width));\n \n return percentage * duration.value;\n};\n\nconst seek = (event) => {\n const seekTime = calculateSeekTime(event);\n playerActions.seek(seekTime);\n};\n\nconst startSeek = (event) => {\n isSeeking.value = true;\n seekPosition.value = calculateSeekTime(event);\n};\n\nconst updateSeekPosition = (event) => {\n if (isSeeking.value) {\n seekPosition.value = calculateSeekTime(event);\n }\n};\n\nconst endSeek = () => {\n if (isSeeking.value) {\n isSeeking.value = false;\n playerActions.seek(seekPosition.value);\n }\n};\n\n// Clean up event listeners when component is unmounted\nonUnmounted(() => {\n isSeeking.value = false;\n});\n</script>\n\n<style scoped>\n/* Progress Section */\n.progress-section {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n}\n\n.time-current,\n.time-total {\n font-size: 11px;\n color: rgb(var(--
|
|
1
|
+
{"version":3,"file":"TrackProgress.vue.cjs","sources":["../../../../../../../src/modules/music/components/player/TrackProgress.vue"],"sourcesContent":["<!-- components/player/TrackProgress.vue -->\n<template>\n <div class=\"progress-section\">\n <span class=\"time-current t-transp\">{{ formatTime(currentTime) }}</span>\n <div \n ref=\"progressBarContainer\"\n class=\"progress-bar\"\n @click=\"seek\"\n @mousedown=\"startSeek\"\n @mousemove=\"updateSeekPosition\"\n @mouseup=\"endSeek\"\n @mouseleave=\"endSeek\"\n >\n <div class=\"progress-track\">\n <div \n class=\"progress-fill\" \n :style=\"{ width: progressPercentage + '%' }\"\n ></div>\n <div \n class=\"progress-thumb\"\n :style=\"{ left: progressPercentage + '%' }\"\n ></div>\n </div>\n </div>\n <span class=\"time-total \">{{ formatTime(duration) }}</span>\n </div>\n</template>\n\n<script setup>\nimport { ref, computed, onUnmounted } from 'vue';\n\n// Import player store\nimport { state as playerState, actions as playerActions } from '../../store/player.js';\n\n// Refs\nconst progressBarContainer = ref(null);\nconst isSeeking = ref(false);\nconst seekPosition = ref(0);\n\n// Computed properties\nconst currentTime = computed(() => playerState.currentTime);\nconst duration = computed(() => playerState.duration);\nconst progressPercentage = computed(() => {\n if (!duration.value) return 0;\n return Math.min(100, (currentTime.value / duration.value) * 100);\n});\n\n// Methods\nconst formatTime = (seconds) => {\n if (!seconds) return '0:00';\n \n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = Math.floor(seconds % 60);\n \n return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;\n};\n\nconst calculateSeekTime = (event) => {\n if (!progressBarContainer.value || !duration.value) return 0;\n \n const rect = progressBarContainer.value.getBoundingClientRect();\n const offsetX = event.clientX - rect.left;\n const percentage = Math.max(0, Math.min(1, offsetX / rect.width));\n \n return percentage * duration.value;\n};\n\nconst seek = (event) => {\n const seekTime = calculateSeekTime(event);\n playerActions.seek(seekTime);\n};\n\nconst startSeek = (event) => {\n isSeeking.value = true;\n seekPosition.value = calculateSeekTime(event);\n};\n\nconst updateSeekPosition = (event) => {\n if (isSeeking.value) {\n seekPosition.value = calculateSeekTime(event);\n }\n};\n\nconst endSeek = () => {\n if (isSeeking.value) {\n isSeeking.value = false;\n playerActions.seek(seekPosition.value);\n }\n};\n\n// Clean up event listeners when component is unmounted\nonUnmounted(() => {\n isSeeking.value = false;\n});\n</script>\n\n<style scoped>\n/* Progress Section */\n.progress-section {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n}\n\n.time-current,\n.time-total {\n font-size: 11px;\n color: rgb(var(--black));\n font-weight: 400;\n min-width: 32px;\n text-align: center;\n}\n\n.progress-bar {\n flex: 1;\n height: 12px;\n display: flex;\n align-items: center;\n cursor: pointer;\n padding: 4px 0;\n}\n\n.progress-track {\n position: relative;\n width: 100%;\n height: 4px;\n background: rgb(var(--grey));\n border-radius: 2px;\n/* overflow: hidden;*/\n transition: height 0.2s ease;\n}\n\n.progress-fill {\n height: 100%;\n background: rgb(var(--second));\n border-radius: 2px;\n transition: width 0.1s ease;\n}\n\n.progress-thumb {\n position: absolute;\n top: 50%;\n width: 12px;\n height: 12px;\n background: rgb(var(--second));\n border: 1px solid rgba(var(--black),0.1);\n border-radius: 50%;\n transform: translate(-50%, -50%);\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.progress-bar:hover .progress-thumb {\n opacity: 1;\n}\n\n.progress-bar:hover .progress-track {\n height: 6px;\n}\n\n.progress-bar:hover .progress-fill {\n background: rgba(var(--second),0.9);\n}\n</style>"],"names":["ref","computed","playerState","playerActions","onUnmounted"],"mappings":";;;;;;;;;;;;;AAmCA,UAAM,uBAAuBA,IAAAA,IAAI,IAAI;AACrC,UAAM,YAAYA,IAAAA,IAAI,KAAK;AAC3B,UAAM,eAAeA,IAAAA,IAAI,CAAC;AAG1B,UAAM,cAAcC,IAAAA,SAAS,MAAMC,OAAAA,MAAY,WAAW;AAC1D,UAAM,WAAWD,IAAAA,SAAS,MAAMC,OAAAA,MAAY,QAAQ;AACpD,UAAM,qBAAqBD,IAAAA,SAAS,MAAM;AACxC,UAAI,CAAC,SAAS,MAAO,QAAO;AAC5B,aAAO,KAAK,IAAI,KAAM,YAAY,QAAQ,SAAS,QAAS,GAAG;AAAA,IACjE,CAAC;AAGD,UAAM,aAAa,CAAC,YAAY;AAC9B,UAAI,CAAC,QAAS,QAAO;AAErB,YAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,YAAM,mBAAmB,KAAK,MAAM,UAAU,EAAE;AAEhD,aAAO,GAAG,OAAO,IAAI,iBAAiB,SAAQ,EAAG,SAAS,GAAG,GAAG,CAAC;AAAA,IACnE;AAEA,UAAM,oBAAoB,CAAC,UAAU;AACnC,UAAI,CAAC,qBAAqB,SAAS,CAAC,SAAS,MAAO,QAAO;AAE3D,YAAM,OAAO,qBAAqB,MAAM,sBAAqB;AAC7D,YAAM,UAAU,MAAM,UAAU,KAAK;AACrC,YAAM,aAAa,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,UAAU,KAAK,KAAK,CAAC;AAEhE,aAAO,aAAa,SAAS;AAAA,IAC/B;AAEA,UAAM,OAAO,CAAC,UAAU;AACtB,YAAM,WAAW,kBAAkB,KAAK;AACxCE,aAAAA,QAAc,KAAK,QAAQ;AAAA,IAC7B;AAEA,UAAM,YAAY,CAAC,UAAU;AAC3B,gBAAU,QAAQ;AAClB,mBAAa,QAAQ,kBAAkB,KAAK;AAAA,IAC9C;AAEA,UAAM,qBAAqB,CAAC,UAAU;AACpC,UAAI,UAAU,OAAO;AACnB,qBAAa,QAAQ,kBAAkB,KAAK;AAAA,MAC9C;AAAA,IACF;AAEA,UAAM,UAAU,MAAM;AACpB,UAAI,UAAU,OAAO;AACnB,kBAAU,QAAQ;AAClBA,uBAAc,KAAK,aAAa,KAAK;AAAA,MACvC;AAAA,IACF;AAGAC,QAAAA,YAAY,MAAM;AAChB,gBAAU,QAAQ;AAAA,IACpB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -3,7 +3,7 @@ import { state, actions } from "../../store/player.js";
|
|
|
3
3
|
/* empty css */
|
|
4
4
|
import _export_sfc from "../../../../../../_virtual/_plugin-vue_export-helper.js";
|
|
5
5
|
const _hoisted_1 = { class: "progress-section" };
|
|
6
|
-
const _hoisted_2 = { class: "time-current" };
|
|
6
|
+
const _hoisted_2 = { class: "time-current t-transp" };
|
|
7
7
|
const _hoisted_3 = { class: "progress-track" };
|
|
8
8
|
const _hoisted_4 = { class: "time-total" };
|
|
9
9
|
const _sfc_main = {
|
|
@@ -82,7 +82,7 @@ const _sfc_main = {
|
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
84
|
};
|
|
85
|
-
const TrackProgress = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
85
|
+
const TrackProgress = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-a338a0bc"]]);
|
|
86
86
|
export {
|
|
87
87
|
TrackProgress as default
|
|
88
88
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TrackProgress.vue.js","sources":["../../../../../../../src/modules/music/components/player/TrackProgress.vue"],"sourcesContent":["<!-- components/player/TrackProgress.vue -->\n<template>\n <div class=\"progress-section\">\n <span class=\"time-current\">{{ formatTime(currentTime) }}</span>\n <div \n ref=\"progressBarContainer\"\n class=\"progress-bar\"\n @click=\"seek\"\n @mousedown=\"startSeek\"\n @mousemove=\"updateSeekPosition\"\n @mouseup=\"endSeek\"\n @mouseleave=\"endSeek\"\n >\n <div class=\"progress-track\">\n <div \n class=\"progress-fill\" \n :style=\"{ width: progressPercentage + '%' }\"\n ></div>\n <div \n class=\"progress-thumb\"\n :style=\"{ left: progressPercentage + '%' }\"\n ></div>\n </div>\n </div>\n <span class=\"time-total\">{{ formatTime(duration) }}</span>\n </div>\n</template>\n\n<script setup>\nimport { ref, computed, onUnmounted } from 'vue';\n\n// Import player store\nimport { state as playerState, actions as playerActions } from '../../store/player.js';\n\n// Refs\nconst progressBarContainer = ref(null);\nconst isSeeking = ref(false);\nconst seekPosition = ref(0);\n\n// Computed properties\nconst currentTime = computed(() => playerState.currentTime);\nconst duration = computed(() => playerState.duration);\nconst progressPercentage = computed(() => {\n if (!duration.value) return 0;\n return Math.min(100, (currentTime.value / duration.value) * 100);\n});\n\n// Methods\nconst formatTime = (seconds) => {\n if (!seconds) return '0:00';\n \n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = Math.floor(seconds % 60);\n \n return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;\n};\n\nconst calculateSeekTime = (event) => {\n if (!progressBarContainer.value || !duration.value) return 0;\n \n const rect = progressBarContainer.value.getBoundingClientRect();\n const offsetX = event.clientX - rect.left;\n const percentage = Math.max(0, Math.min(1, offsetX / rect.width));\n \n return percentage * duration.value;\n};\n\nconst seek = (event) => {\n const seekTime = calculateSeekTime(event);\n playerActions.seek(seekTime);\n};\n\nconst startSeek = (event) => {\n isSeeking.value = true;\n seekPosition.value = calculateSeekTime(event);\n};\n\nconst updateSeekPosition = (event) => {\n if (isSeeking.value) {\n seekPosition.value = calculateSeekTime(event);\n }\n};\n\nconst endSeek = () => {\n if (isSeeking.value) {\n isSeeking.value = false;\n playerActions.seek(seekPosition.value);\n }\n};\n\n// Clean up event listeners when component is unmounted\nonUnmounted(() => {\n isSeeking.value = false;\n});\n</script>\n\n<style scoped>\n/* Progress Section */\n.progress-section {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n}\n\n.time-current,\n.time-total {\n font-size: 11px;\n color: rgb(var(--
|
|
1
|
+
{"version":3,"file":"TrackProgress.vue.js","sources":["../../../../../../../src/modules/music/components/player/TrackProgress.vue"],"sourcesContent":["<!-- components/player/TrackProgress.vue -->\n<template>\n <div class=\"progress-section\">\n <span class=\"time-current t-transp\">{{ formatTime(currentTime) }}</span>\n <div \n ref=\"progressBarContainer\"\n class=\"progress-bar\"\n @click=\"seek\"\n @mousedown=\"startSeek\"\n @mousemove=\"updateSeekPosition\"\n @mouseup=\"endSeek\"\n @mouseleave=\"endSeek\"\n >\n <div class=\"progress-track\">\n <div \n class=\"progress-fill\" \n :style=\"{ width: progressPercentage + '%' }\"\n ></div>\n <div \n class=\"progress-thumb\"\n :style=\"{ left: progressPercentage + '%' }\"\n ></div>\n </div>\n </div>\n <span class=\"time-total \">{{ formatTime(duration) }}</span>\n </div>\n</template>\n\n<script setup>\nimport { ref, computed, onUnmounted } from 'vue';\n\n// Import player store\nimport { state as playerState, actions as playerActions } from '../../store/player.js';\n\n// Refs\nconst progressBarContainer = ref(null);\nconst isSeeking = ref(false);\nconst seekPosition = ref(0);\n\n// Computed properties\nconst currentTime = computed(() => playerState.currentTime);\nconst duration = computed(() => playerState.duration);\nconst progressPercentage = computed(() => {\n if (!duration.value) return 0;\n return Math.min(100, (currentTime.value / duration.value) * 100);\n});\n\n// Methods\nconst formatTime = (seconds) => {\n if (!seconds) return '0:00';\n \n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = Math.floor(seconds % 60);\n \n return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;\n};\n\nconst calculateSeekTime = (event) => {\n if (!progressBarContainer.value || !duration.value) return 0;\n \n const rect = progressBarContainer.value.getBoundingClientRect();\n const offsetX = event.clientX - rect.left;\n const percentage = Math.max(0, Math.min(1, offsetX / rect.width));\n \n return percentage * duration.value;\n};\n\nconst seek = (event) => {\n const seekTime = calculateSeekTime(event);\n playerActions.seek(seekTime);\n};\n\nconst startSeek = (event) => {\n isSeeking.value = true;\n seekPosition.value = calculateSeekTime(event);\n};\n\nconst updateSeekPosition = (event) => {\n if (isSeeking.value) {\n seekPosition.value = calculateSeekTime(event);\n }\n};\n\nconst endSeek = () => {\n if (isSeeking.value) {\n isSeeking.value = false;\n playerActions.seek(seekPosition.value);\n }\n};\n\n// Clean up event listeners when component is unmounted\nonUnmounted(() => {\n isSeeking.value = false;\n});\n</script>\n\n<style scoped>\n/* Progress Section */\n.progress-section {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n}\n\n.time-current,\n.time-total {\n font-size: 11px;\n color: rgb(var(--black));\n font-weight: 400;\n min-width: 32px;\n text-align: center;\n}\n\n.progress-bar {\n flex: 1;\n height: 12px;\n display: flex;\n align-items: center;\n cursor: pointer;\n padding: 4px 0;\n}\n\n.progress-track {\n position: relative;\n width: 100%;\n height: 4px;\n background: rgb(var(--grey));\n border-radius: 2px;\n/* overflow: hidden;*/\n transition: height 0.2s ease;\n}\n\n.progress-fill {\n height: 100%;\n background: rgb(var(--second));\n border-radius: 2px;\n transition: width 0.1s ease;\n}\n\n.progress-thumb {\n position: absolute;\n top: 50%;\n width: 12px;\n height: 12px;\n background: rgb(var(--second));\n border: 1px solid rgba(var(--black),0.1);\n border-radius: 50%;\n transform: translate(-50%, -50%);\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.progress-bar:hover .progress-thumb {\n opacity: 1;\n}\n\n.progress-bar:hover .progress-track {\n height: 6px;\n}\n\n.progress-bar:hover .progress-fill {\n background: rgba(var(--second),0.9);\n}\n</style>"],"names":["playerState","playerActions"],"mappings":";;;;;;;;;;;AAmCA,UAAM,uBAAuB,IAAI,IAAI;AACrC,UAAM,YAAY,IAAI,KAAK;AAC3B,UAAM,eAAe,IAAI,CAAC;AAG1B,UAAM,cAAc,SAAS,MAAMA,MAAY,WAAW;AAC1D,UAAM,WAAW,SAAS,MAAMA,MAAY,QAAQ;AACpD,UAAM,qBAAqB,SAAS,MAAM;AACxC,UAAI,CAAC,SAAS,MAAO,QAAO;AAC5B,aAAO,KAAK,IAAI,KAAM,YAAY,QAAQ,SAAS,QAAS,GAAG;AAAA,IACjE,CAAC;AAGD,UAAM,aAAa,CAAC,YAAY;AAC9B,UAAI,CAAC,QAAS,QAAO;AAErB,YAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,YAAM,mBAAmB,KAAK,MAAM,UAAU,EAAE;AAEhD,aAAO,GAAG,OAAO,IAAI,iBAAiB,SAAQ,EAAG,SAAS,GAAG,GAAG,CAAC;AAAA,IACnE;AAEA,UAAM,oBAAoB,CAAC,UAAU;AACnC,UAAI,CAAC,qBAAqB,SAAS,CAAC,SAAS,MAAO,QAAO;AAE3D,YAAM,OAAO,qBAAqB,MAAM,sBAAqB;AAC7D,YAAM,UAAU,MAAM,UAAU,KAAK;AACrC,YAAM,aAAa,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,UAAU,KAAK,KAAK,CAAC;AAEhE,aAAO,aAAa,SAAS;AAAA,IAC/B;AAEA,UAAM,OAAO,CAAC,UAAU;AACtB,YAAM,WAAW,kBAAkB,KAAK;AACxCC,cAAc,KAAK,QAAQ;AAAA,IAC7B;AAEA,UAAM,YAAY,CAAC,UAAU;AAC3B,gBAAU,QAAQ;AAClB,mBAAa,QAAQ,kBAAkB,KAAK;AAAA,IAC9C;AAEA,UAAM,qBAAqB,CAAC,UAAU;AACpC,UAAI,UAAU,OAAO;AACnB,qBAAa,QAAQ,kBAAkB,KAAK;AAAA,MAC9C;AAAA,IACF;AAEA,UAAM,UAAU,MAAM;AACpB,UAAI,UAAU,OAAO;AACnB,kBAAU,QAAQ;AAClBA,gBAAc,KAAK,aAAa,KAAK;AAAA,MACvC;AAAA,IACF;AAGA,gBAAY,MAAM;AAChB,gBAAU,QAAQ;AAAA,IACpB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -56,7 +56,7 @@ const _sfc_main = {
|
|
|
56
56
|
vue.createElementVNode("div", {
|
|
57
57
|
class: "volume-track",
|
|
58
58
|
style: vue.normalizeStyle({
|
|
59
|
-
background: `linear-gradient(to right, rgb(var(--
|
|
59
|
+
background: `linear-gradient(to right, rgb(var(--black)) 0%, rgb(var(--black)) ${volumePercentage.value}%, rgb(var(--grey)) ${volumePercentage.value}%, rgb(var(--grey)) 100%)`
|
|
60
60
|
})
|
|
61
61
|
}, [
|
|
62
62
|
vue.createElementVNode("div", {
|
|
@@ -72,6 +72,6 @@ const _sfc_main = {
|
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
74
|
};
|
|
75
|
-
const VolumeControl = /* @__PURE__ */ _pluginVue_exportHelper.default(_sfc_main, [["__scopeId", "data-v-
|
|
75
|
+
const VolumeControl = /* @__PURE__ */ _pluginVue_exportHelper.default(_sfc_main, [["__scopeId", "data-v-d29a4209"]]);
|
|
76
76
|
exports.default = VolumeControl;
|
|
77
77
|
//# sourceMappingURL=VolumeControl.vue.cjs.map
|