useSortablePlaylists.ts 4.6 KB

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