useSortablePlaylists.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. import { ref, computed, onMounted, onBeforeUnmount, nextTick } from "vue";
  2. import Toast from "toasters";
  3. import { storeToRefs } from "pinia";
  4. import { DraggableList } from "vue-draggable-list";
  5. import { useWebsocketsStore } from "@/stores/websockets";
  6. import { useUserAuthStore } from "@/stores/userAuth";
  7. import { useUserPlaylistsStore } from "@/stores/userPlaylists";
  8. export const useSortablePlaylists = () => {
  9. const orderOfPlaylists = ref([]);
  10. const drag = ref(false);
  11. const userId = ref();
  12. const userAuthStore = useUserAuthStore();
  13. const userPlaylistsStore = useUserPlaylistsStore();
  14. const { userId: myUserId } = storeToRefs(userAuthStore);
  15. const playlists = computed({
  16. get: () => userPlaylistsStore.playlists,
  17. set: playlists => {
  18. userPlaylistsStore.updatePlaylists(playlists);
  19. }
  20. });
  21. const isCurrentUser = computed(() => userId.value === myUserId.value);
  22. const { socket } = useWebsocketsStore();
  23. const { setPlaylists, addPlaylist, removePlaylist } = userPlaylistsStore;
  24. const calculatePlaylistOrder = () => {
  25. const calculatedOrder = [];
  26. playlists.value.forEach(playlist => calculatedOrder.push(playlist._id));
  27. return calculatedOrder;
  28. };
  29. const savePlaylistOrder = () => {
  30. const recalculatedOrder = calculatePlaylistOrder();
  31. if (
  32. JSON.stringify(orderOfPlaylists.value) ===
  33. JSON.stringify(recalculatedOrder)
  34. )
  35. return; // nothing has changed
  36. socket.dispatch(
  37. "users.updateOrderOfPlaylists",
  38. recalculatedOrder,
  39. res => {
  40. if (res.status === "error") return new Toast(res.message);
  41. orderOfPlaylists.value = calculatePlaylistOrder(); // new order in regards to the database
  42. return new Toast(res.message);
  43. }
  44. );
  45. };
  46. onMounted(async () => {
  47. await nextTick();
  48. if (!userId.value) userId.value = myUserId.value;
  49. socket.onConnect(() => {
  50. if (!isCurrentUser.value)
  51. socket.dispatch(
  52. "apis.joinRoom",
  53. `profile.${userId.value}.playlists`,
  54. () => {}
  55. );
  56. socket.dispatch("playlists.indexForUser", userId.value, res => {
  57. if (res.status === "success") setPlaylists(res.data.playlists);
  58. orderOfPlaylists.value = calculatePlaylistOrder(); // order in regards to the database
  59. });
  60. });
  61. socket.on(
  62. "event:playlist.created",
  63. res => addPlaylist(res.data.playlist),
  64. { replaceable: true }
  65. );
  66. socket.on(
  67. "event:playlist.deleted",
  68. res => removePlaylist(res.data.playlistId),
  69. { replaceable: true }
  70. );
  71. socket.on(
  72. "event:playlist.song.added",
  73. res => {
  74. playlists.value.forEach((playlist, index) => {
  75. if (playlist._id === res.data.playlistId) {
  76. playlists.value[index].songs.push(res.data.song);
  77. }
  78. });
  79. },
  80. { replaceable: true }
  81. );
  82. socket.on(
  83. "event:playlist.song.removed",
  84. res => {
  85. playlists.value.forEach((playlist, playlistIndex) => {
  86. if (playlist._id === res.data.playlistId) {
  87. playlists.value[playlistIndex].songs.forEach(
  88. (song, songIndex) => {
  89. if (song.mediaSource === res.data.mediaSource) {
  90. playlists.value[playlistIndex].songs.splice(
  91. songIndex,
  92. 1
  93. );
  94. }
  95. }
  96. );
  97. }
  98. });
  99. },
  100. { replaceable: true }
  101. );
  102. socket.on(
  103. "event:playlist.displayName.updated",
  104. res => {
  105. playlists.value.forEach((playlist, index) => {
  106. if (playlist._id === res.data.playlistId) {
  107. playlists.value[index].displayName =
  108. res.data.displayName;
  109. }
  110. });
  111. },
  112. { replaceable: true }
  113. );
  114. socket.on(
  115. "event:playlist.privacy.updated",
  116. res => {
  117. playlists.value.forEach((playlist, index) => {
  118. if (playlist._id === res.data.playlist._id) {
  119. playlists.value[index].privacy =
  120. res.data.playlist.privacy;
  121. }
  122. });
  123. },
  124. { replaceable: true }
  125. );
  126. socket.on(
  127. "event:user.orderOfPlaylists.updated",
  128. res => {
  129. const order = res.data.order.filter(playlistId =>
  130. playlists.value.find(
  131. playlist =>
  132. playlist._id === playlistId &&
  133. (isCurrentUser.value ||
  134. playlist.privacy === "public")
  135. )
  136. );
  137. const sortedPlaylists = [];
  138. playlists.value.forEach(playlist => {
  139. const playlistOrder = order.indexOf(playlist._id);
  140. if (playlistOrder >= 0)
  141. sortedPlaylists[playlistOrder] = playlist;
  142. });
  143. playlists.value = sortedPlaylists;
  144. orderOfPlaylists.value = calculatePlaylistOrder();
  145. },
  146. { replaceable: true }
  147. );
  148. });
  149. onBeforeUnmount(() => {
  150. if (!isCurrentUser.value)
  151. socket.dispatch(
  152. "apis.leaveRoom",
  153. `profile.${userId.value}.playlists`,
  154. () => {}
  155. );
  156. });
  157. return {
  158. DraggableList,
  159. drag,
  160. userId,
  161. isCurrentUser,
  162. playlists,
  163. orderOfPlaylists,
  164. myUserId,
  165. savePlaylistOrder,
  166. calculatePlaylistOrder
  167. };
  168. };