1
0

useSortablePlaylists.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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. socket.on(
  61. "event:playlist.created",
  62. res => addPlaylist(res.data.playlist),
  63. { replaceable: true }
  64. );
  65. socket.on(
  66. "event:playlist.deleted",
  67. res => removePlaylist(res.data.playlistId),
  68. { replaceable: true }
  69. );
  70. socket.on(
  71. "event:playlist.song.added",
  72. res => {
  73. playlists.value.forEach((playlist, index) => {
  74. if (playlist._id === res.data.playlistId) {
  75. playlists.value[index].songs.push(res.data.song);
  76. }
  77. });
  78. },
  79. { replaceable: true }
  80. );
  81. socket.on(
  82. "event:playlist.song.removed",
  83. res => {
  84. playlists.value.forEach((playlist, playlistIndex) => {
  85. if (playlist._id === res.data.playlistId) {
  86. playlists.value[playlistIndex].songs.forEach(
  87. (song, songIndex) => {
  88. if (song.youtubeId === res.data.youtubeId) {
  89. playlists.value[
  90. playlistIndex
  91. ].songs.splice(songIndex, 1);
  92. }
  93. }
  94. );
  95. }
  96. });
  97. },
  98. { replaceable: true }
  99. );
  100. socket.on(
  101. "event:playlist.displayName.updated",
  102. res => {
  103. playlists.value.forEach((playlist, index) => {
  104. if (playlist._id === res.data.playlistId) {
  105. playlists.value[index].displayName =
  106. res.data.displayName;
  107. }
  108. });
  109. },
  110. { replaceable: true }
  111. );
  112. socket.on(
  113. "event:playlist.privacy.updated",
  114. res => {
  115. playlists.value.forEach((playlist, index) => {
  116. if (playlist._id === res.data.playlist._id) {
  117. playlists.value[index].privacy =
  118. res.data.playlist.privacy;
  119. }
  120. });
  121. },
  122. { replaceable: true }
  123. );
  124. socket.on(
  125. "event:user.orderOfPlaylists.updated",
  126. res => {
  127. const order = res.data.order.filter(playlistId =>
  128. playlists.value.find(
  129. playlist =>
  130. playlist._id === playlistId &&
  131. (isCurrentUser.value ||
  132. playlist.privacy === "public")
  133. )
  134. );
  135. const sortedPlaylists = [];
  136. playlists.value.forEach(playlist => {
  137. const playlistOrder = order.indexOf(playlist._id);
  138. if (playlistOrder >= 0)
  139. sortedPlaylists[playlistOrder] = playlist;
  140. });
  141. playlists.value = sortedPlaylists;
  142. orderOfPlaylists.value = calculatePlaylistOrder();
  143. },
  144. { replaceable: true }
  145. );
  146. });
  147. });
  148. onBeforeUnmount(() => {
  149. if (!isCurrentUser.value)
  150. socket.dispatch(
  151. "apis.leaveRoom",
  152. `profile.${userId.value}.playlists`,
  153. () => {}
  154. );
  155. });
  156. return {
  157. DraggableList,
  158. drag,
  159. userId,
  160. isCurrentUser,
  161. playlists,
  162. orderOfPlaylists,
  163. myUserId,
  164. savePlaylistOrder,
  165. calculatePlaylistOrder
  166. };
  167. };