station.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. import { defineStore, storeToRefs } from "pinia";
  2. import { Playlist } from "@/types/playlist";
  3. import { Song, CurrentSong } from "@/types/song";
  4. import { Station } from "@/types/station";
  5. import { User } from "@/types/user";
  6. import { StationHistory } from "@/types/stationHistory";
  7. import { useWebsocketsStore } from "@/stores/websockets";
  8. import { useUserPreferencesStore } from "@/stores/userPreferences";
  9. import { useConfigStore } from "@/stores/config";
  10. import { useSortablePlaylists } from "@/composables/useSortablePlaylists";
  11. const userPreferencesStore = useUserPreferencesStore();
  12. const configStore = useConfigStore();
  13. const { autoSkipDisliked } = storeToRefs(userPreferencesStore);
  14. const { experimental } = storeToRefs(configStore);
  15. const { playlists } = useSortablePlaylists();
  16. export const useStationStore = defineStore("station", {
  17. state: (): {
  18. station: Station;
  19. autoRequest: Playlist[];
  20. autoRequestLock: boolean;
  21. userCount: number;
  22. users: {
  23. loggedIn: User[];
  24. loggedOut: User[];
  25. };
  26. currentSong: CurrentSong | undefined;
  27. nextSong: Song | undefined | null;
  28. songsList: Song[];
  29. stationPaused: boolean;
  30. localPaused: boolean;
  31. noSong: boolean;
  32. autofill: Playlist[];
  33. blacklist: Playlist[];
  34. mediaModalPlayingAudio: boolean;
  35. permissions: Record<string, boolean>;
  36. history: StationHistory[];
  37. } => ({
  38. station: {},
  39. autoRequest: [],
  40. autoRequestLock: false,
  41. userCount: 0,
  42. users: {
  43. loggedIn: [],
  44. loggedOut: []
  45. },
  46. currentSong: {},
  47. nextSong: null,
  48. songsList: [],
  49. stationPaused: true,
  50. localPaused: false,
  51. noSong: true,
  52. autofill: [],
  53. blacklist: [],
  54. mediaModalPlayingAudio: false,
  55. permissions: {},
  56. history: []
  57. }),
  58. getters: {
  59. dislikedPlaylist() {
  60. return playlists.value.find(
  61. playlist => playlist.type === "user-disliked"
  62. );
  63. },
  64. // List of media sources that will not be allowed to be autorequested
  65. autorequestExcludedMediaSources() {
  66. const mediaSources = new Set();
  67. // Exclude the current song
  68. if (this.currentSong && this.currentSong.mediaSource)
  69. mediaSources.add(this.currentSong.mediaSource);
  70. // Exclude songs in the queue
  71. if (this.songsList) {
  72. this.songsList.forEach(song => {
  73. mediaSources.add(song.mediaSource);
  74. });
  75. }
  76. // If auto skip disliked preference is enabled, exclude all songs in the disliked playlist
  77. if (autoSkipDisliked.value && this.dislikedPlaylist) {
  78. this.dislikedPlaylist.songs.forEach(song => {
  79. mediaSources.add(song.mediaSource);
  80. });
  81. }
  82. // If no history exists, just stop here
  83. if (!this.history) Array.from(mediaSources);
  84. const {
  85. autorequestDisallowRecentlyPlayedEnabled,
  86. autorequestDisallowRecentlyPlayedNumber
  87. } = this.station.requests;
  88. // If the station is set to disallow recently played songs, and station history is enabled, exclude the last X history songs
  89. if (
  90. autorequestDisallowRecentlyPlayedEnabled &&
  91. experimental.value.station_history
  92. ) {
  93. this.history.forEach((historyItem, index) => {
  94. if (index < autorequestDisallowRecentlyPlayedNumber)
  95. mediaSources.add(historyItem.payload.song.mediaSource);
  96. });
  97. }
  98. return Array.from(mediaSources);
  99. }
  100. },
  101. actions: {
  102. joinStation(station) {
  103. this.station = { ...station };
  104. },
  105. leaveStation() {
  106. this.station = {};
  107. this.autoRequest = [];
  108. this.autoRequestLock = false;
  109. this.editing = {};
  110. this.userCount = 0;
  111. this.users = {
  112. loggedIn: [],
  113. loggedOut: []
  114. };
  115. this.currentSong = {};
  116. this.nextSong = null;
  117. this.songsList = [];
  118. this.stationPaused = true;
  119. this.localPaused = false;
  120. this.noSong = true;
  121. this.autofill = [];
  122. this.blacklist = [];
  123. this.permissions = {};
  124. },
  125. editStation(station) {
  126. this.editing = { ...station };
  127. },
  128. updateStation(station) {
  129. this.station = { ...this.station, ...station };
  130. },
  131. updateUserCount(userCount) {
  132. this.userCount = userCount;
  133. },
  134. updateUsers(users) {
  135. this.users = users;
  136. },
  137. updateCurrentSong(currentSong) {
  138. this.currentSong = currentSong;
  139. },
  140. updateNextSong(nextSong) {
  141. this.nextSong = nextSong;
  142. },
  143. updateSongsList(songsList) {
  144. this.songsList = songsList;
  145. },
  146. repositionSongInList(song) {
  147. if (
  148. this.songsList[song.newIndex] &&
  149. this.songsList[song.newIndex].mediaSource === song.mediaSource
  150. )
  151. return;
  152. this.songsList.splice(
  153. song.newIndex,
  154. 0,
  155. this.songsList.splice(song.oldIndex, 1)[0]
  156. );
  157. },
  158. updateStationPaused(stationPaused) {
  159. this.stationPaused = stationPaused;
  160. },
  161. updateLocalPaused(localPaused) {
  162. this.localPaused = localPaused;
  163. },
  164. updateNoSong(noSong) {
  165. this.noSong = noSong;
  166. },
  167. updateAutoRequest(playlists) {
  168. this.autoRequest = playlists;
  169. },
  170. updateAutoRequestLock(lock) {
  171. this.autoRequestLock = lock;
  172. },
  173. updateIfStationIsFavorited(isFavorited) {
  174. this.station.isFavorited = isFavorited;
  175. },
  176. setAutofillPlaylists(autofillPlaylists) {
  177. this.autofill = JSON.parse(JSON.stringify(autofillPlaylists));
  178. },
  179. setBlacklist(blacklist) {
  180. this.blacklist = JSON.parse(JSON.stringify(blacklist));
  181. },
  182. updateCurrentSongRatings(songRatings) {
  183. this.currentSong.likes = songRatings.likes;
  184. this.currentSong.dislikes = songRatings.dislikes;
  185. },
  186. updateOwnCurrentSongRatings(ownSongRatings) {
  187. this.currentSong.liked = ownSongRatings.liked;
  188. this.currentSong.disliked = ownSongRatings.disliked;
  189. },
  190. updateCurrentSongSkipVotes({ skipVotes, skipVotesCurrent, voted }) {
  191. this.currentSong.skipVotes = skipVotes;
  192. if (skipVotesCurrent !== null)
  193. this.currentSong.skipVotesCurrent = skipVotesCurrent;
  194. this.currentSong.voted = voted;
  195. },
  196. addAutorequestPlaylists(playlists) {
  197. playlists.forEach(playlist => {
  198. this.autoRequest.push(playlist);
  199. });
  200. this.updateAutorequestLocalStorage();
  201. },
  202. addPlaylistToAutoRequest(playlist) {
  203. this.autoRequest.push(playlist);
  204. this.updateAutorequestLocalStorage();
  205. },
  206. removePlaylistFromAutoRequest(playlistId) {
  207. this.autoRequest.forEach((playlist, index) => {
  208. if (playlist._id === playlistId) {
  209. this.autoRequest.splice(index, 1);
  210. }
  211. });
  212. this.updateAutorequestLocalStorage();
  213. },
  214. updateAutorequestLocalStorage() {
  215. const key = `autorequest-${this.station._id}`;
  216. const playlistIds = Array.from(
  217. new Set(this.autoRequest.map(playlist => playlist._id))
  218. );
  219. const value = {
  220. updatedAt: new Date(),
  221. playlistIds
  222. };
  223. localStorage.setItem(key, JSON.stringify(value));
  224. },
  225. updateMediaModalPlayingAudio(mediaModalPlayingAudio) {
  226. this.mediaModalPlayingAudio = mediaModalPlayingAudio;
  227. },
  228. hasPermission(permission) {
  229. return !!(this.permissions && this.permissions[permission]);
  230. },
  231. updatePermissions() {
  232. return new Promise(resolve => {
  233. const { socket } = useWebsocketsStore();
  234. socket.dispatch(
  235. "utils.getPermissions",
  236. this.station._id,
  237. res => {
  238. this.permissions = res.data.permissions;
  239. resolve(this.permissions);
  240. }
  241. );
  242. });
  243. },
  244. addDj(user) {
  245. this.station.djs.push(user);
  246. },
  247. removeDj(user) {
  248. this.station.djs.forEach((dj, index) => {
  249. if (dj._id === user._id) {
  250. this.station.djs.splice(index, 1);
  251. }
  252. });
  253. },
  254. setHistory(history: StationHistory[]) {
  255. this.history = history;
  256. },
  257. addHistoryItem(historyItem: StationHistory) {
  258. this.history.unshift(historyItem);
  259. }
  260. }
  261. });