|
@@ -6,7 +6,9 @@ import {
|
|
|
ReleaseTemp,
|
|
|
YoutubeChannelTemp,
|
|
|
RecordingTemp,
|
|
|
- ReleaseGroupTemp
|
|
|
+ ReleaseGroupTemp,
|
|
|
+ RecordingEntity,
|
|
|
+ VideoEntity
|
|
|
} from "@/types/artist";
|
|
|
import { useConfigStore } from "@/stores/config";
|
|
|
|
|
@@ -117,6 +119,16 @@ export const useImportArtistStore = ({ modalUuid }: { modalUuid: string }) =>
|
|
|
|
|
|
const showOnlyVideosWithoutAutoLinks = ref(false);
|
|
|
|
|
|
+ const recordingEntities = ref<RecordingEntity[]>([]);
|
|
|
+ const collapsedRecordingEntityGroupKeys = ref<{
|
|
|
+ [entityGroupKey: string]: boolean;
|
|
|
+ }>({});
|
|
|
+
|
|
|
+ const videoEntities = ref<VideoEntity[]>([]);
|
|
|
+ const collapsedVideoEntityGroupKeys = ref<{
|
|
|
+ [entityGroupKey: string]: boolean;
|
|
|
+ }>({});
|
|
|
+
|
|
|
const releaseGroupIdsForRecordingIdMap = computed<{
|
|
|
[recordingId: string]: string[];
|
|
|
}>(() => {
|
|
@@ -143,6 +155,53 @@ export const useImportArtistStore = ({ modalUuid }: { modalUuid: string }) =>
|
|
|
return map;
|
|
|
});
|
|
|
|
|
|
+ const youtubeVideoTitleNormalizedNew = title =>
|
|
|
+ title
|
|
|
+ .replaceAll(/\(.+\)/g, "")
|
|
|
+ .replaceAll(/\[.+\]/g, "")
|
|
|
+ .replaceAll(/\{.+\}/g, "")
|
|
|
+ // .replace(new RegExp(`.*${artist.value.name}.* - `, "i"), "")
|
|
|
+ .replace(
|
|
|
+ new RegExp(
|
|
|
+ `^[\\p{L}0-9&, ]*${artist.value.name}[\\p{L}0-9&, ]* - `,
|
|
|
+ "i"
|
|
|
+ ),
|
|
|
+ ""
|
|
|
+ )
|
|
|
+ // .replace(new RegExp(` - .*${artist.value.name}.*`, "i"), "")
|
|
|
+ .replace(
|
|
|
+ new RegExp(
|
|
|
+ ` - [\\p{L}0-9&, ]*${artist.value.name}[\\p{L}0-9&, ]*$`, // Doesn't work if an extra artist has a "-" in it, and adding it to the regex matches too much
|
|
|
+ "ui"
|
|
|
+ ),
|
|
|
+ ""
|
|
|
+ )
|
|
|
+ .replaceAll(/-[\p{L}0-9 ]+-$/gu, "") // For things like "Some title -Instrumental-", where it ends with that
|
|
|
+ .replaceAll(/ - demo/gi, "")
|
|
|
+ .replaceAll(/[^\p{L}0-9 ]/gu, "")
|
|
|
+ .replaceAll(/[ ]{2,}/g, " ")
|
|
|
+ .trim();
|
|
|
+ const musicbrainzRecordingTitleNormalizedNew = title =>
|
|
|
+ title
|
|
|
+ .replaceAll(/\(.+\)/g, "")
|
|
|
+ .replaceAll(/\[.+\]/g, "")
|
|
|
+ .replaceAll(/\{.+\}/g, "")
|
|
|
+ .replaceAll(/-[\p{L}0-9 ]+-$/gu, "") // For things like "Some title -Instrumental-", where it ends with that
|
|
|
+ .replaceAll(/ - demo/gi, "")
|
|
|
+ .replaceAll(/[^\p{L}0-9 ]/gu, "")
|
|
|
+ .replaceAll(/[ ]{2,}/g, " ")
|
|
|
+ .trim();
|
|
|
+ const youtubeVideoTitleNormalizedNewExtra = title =>
|
|
|
+ youtubeVideoTitleNormalizedNew(title)
|
|
|
+ .toLowerCase()
|
|
|
+ .replaceAll(/[^\p{L}0-9]/gu, "") // Also removes spaces
|
|
|
+ .trim();
|
|
|
+ const musicbrainzRecordingTitleNormalizedNewExtra = title =>
|
|
|
+ musicbrainzRecordingTitleNormalizedNew(title)
|
|
|
+ .toLowerCase()
|
|
|
+ .replaceAll(/[^\p{L}0-9]/gu, "") // Also removes spaces
|
|
|
+ .trim();
|
|
|
+
|
|
|
const recordingSortTitleFn = (recordingA, recordingB) =>
|
|
|
`${recordingA.title} (${recordingA.disambiguation})`.localeCompare(
|
|
|
`${recordingB.title} (${recordingB.disambiguation})`
|
|
@@ -377,6 +436,13 @@ export const useImportArtistStore = ({ modalUuid }: { modalUuid: string }) =>
|
|
|
.toLowerCase()
|
|
|
.trim()
|
|
|
.replaceAll(/[^\p{L}0-9 ]/gu, "");
|
|
|
+ const titleNormalizedNew = youtubeVideoTitleNormalizedNew(
|
|
|
+ youtubeVideo.rawData.snippet.title
|
|
|
+ );
|
|
|
+ const titleNormalizedNewExtra =
|
|
|
+ youtubeVideoTitleNormalizedNewExtra(
|
|
|
+ youtubeVideo.rawData.snippet.title
|
|
|
+ );
|
|
|
|
|
|
return [
|
|
|
youtubeVideoId,
|
|
@@ -385,6 +451,8 @@ export const useImportArtistStore = ({ modalUuid }: { modalUuid: string }) =>
|
|
|
title,
|
|
|
strippedAdjustedYoutubeVideoTitle,
|
|
|
strippedYoutubeVideoTitle,
|
|
|
+ titleNormalizedNew,
|
|
|
+ titleNormalizedNewExtra,
|
|
|
hide
|
|
|
}
|
|
|
];
|
|
@@ -682,6 +750,16 @@ export const useImportArtistStore = ({ modalUuid }: { modalUuid: string }) =>
|
|
|
])
|
|
|
);
|
|
|
measureFinish("setYoutubeVideos method part two");
|
|
|
+
|
|
|
+ measureStart("setYoutubeVideos set videoEntities");
|
|
|
+ videoEntities.value = youtubeVideoIds.value.map(videoId => ({
|
|
|
+ type: "single",
|
|
|
+ key: videoId,
|
|
|
+ sortTitle:
|
|
|
+ youtubeVideoMapAdjusted.value[videoId].titleNormalizedNew,
|
|
|
+ videoId
|
|
|
+ }));
|
|
|
+ measureFinish("setYoutubeVideos set videoEntities");
|
|
|
};
|
|
|
const resetLinkingData = () => {
|
|
|
recordingSort.value = "title";
|
|
@@ -731,10 +809,16 @@ export const useImportArtistStore = ({ modalUuid }: { modalUuid: string }) =>
|
|
|
);
|
|
|
measureStart("setMusicBrainzRecordingsReleasesReleaseGroups");
|
|
|
|
|
|
+ measureStart(
|
|
|
+ "setMusicBrainzRecordingsReleasesReleaseGroups set recordingsReleasesReleaseGroups"
|
|
|
+ );
|
|
|
recordingsReleasesReleaseGroups.value = [
|
|
|
...artistReleases,
|
|
|
...trackArtistReleases
|
|
|
];
|
|
|
+ measureFinish(
|
|
|
+ "setMusicBrainzRecordingsReleasesReleaseGroups set recordingsReleasesReleaseGroups"
|
|
|
+ );
|
|
|
|
|
|
const _recordingMap = {};
|
|
|
const _releaseMap = {};
|
|
@@ -751,13 +835,25 @@ export const useImportArtistStore = ({ modalUuid }: { modalUuid: string }) =>
|
|
|
_releaseGroupMap[releaseGroup.id] = releaseGroup;
|
|
|
});
|
|
|
|
|
|
+ measureStart(
|
|
|
+ "setMusicBrainzRecordingsReleasesReleaseGroups set maps"
|
|
|
+ );
|
|
|
recordingMap.value = _recordingMap;
|
|
|
releaseMap.value = _releaseMap;
|
|
|
releaseGroupMap.value = _releaseGroupMap;
|
|
|
+ measureFinish(
|
|
|
+ "setMusicBrainzRecordingsReleasesReleaseGroups set maps"
|
|
|
+ );
|
|
|
|
|
|
+ measureStart(
|
|
|
+ "setMusicBrainzRecordingsReleasesReleaseGroups set ids"
|
|
|
+ );
|
|
|
recordingIds.value = Object.keys(recordingMap.value);
|
|
|
releaseIds.value = Object.keys(releaseMap.value);
|
|
|
releaseGroupIds.value = Object.keys(releaseGroupMap.value);
|
|
|
+ measureFinish(
|
|
|
+ "setMusicBrainzRecordingsReleasesReleaseGroups set ids"
|
|
|
+ );
|
|
|
|
|
|
// E.g. various artist release groups
|
|
|
const trackArtistReleaseIds = trackArtistReleases.map(
|
|
@@ -769,54 +865,67 @@ export const useImportArtistStore = ({ modalUuid }: { modalUuid: string }) =>
|
|
|
measureStart(
|
|
|
"setMusicBrainzRecordingsReleasesReleaseGroups trackArtistOnlyRecordingIds"
|
|
|
);
|
|
|
- // TODO improve performance of below. The if () return; are meant to improve performance, but don't do too much
|
|
|
- trackArtistOnlyRecordingIds.value = recordingIds.value.filter(
|
|
|
- recordingId => {
|
|
|
- let dontInclude = false;
|
|
|
- trackArtistReleaseIds.forEach(releaseId => {
|
|
|
- if (dontInclude) return;
|
|
|
- const release = releaseMap.value[releaseId];
|
|
|
- release.media.forEach(media => {
|
|
|
- if (dontInclude) return;
|
|
|
- media.tracks?.forEach(track => {
|
|
|
- if (dontInclude) return;
|
|
|
- const { recording } = track;
|
|
|
- if (recording.id === recordingId)
|
|
|
- dontInclude = true;
|
|
|
- });
|
|
|
- });
|
|
|
+ // TODO improve performance of below if it's still needed
|
|
|
+ const _trackArtistOnlyRecordingIdsDontIncludeMap = {};
|
|
|
+ const _trackArtistOnlyRecordingIdsIncludeMap = {};
|
|
|
+ recordingIds.value.forEach(recordingId => {
|
|
|
+ _trackArtistOnlyRecordingIdsDontIncludeMap[recordingId] = false;
|
|
|
+ _trackArtistOnlyRecordingIdsIncludeMap[recordingId] = false;
|
|
|
+ });
|
|
|
+ trackArtistReleaseIds.forEach(releaseId => {
|
|
|
+ const release = releaseMap.value[releaseId];
|
|
|
+ release.media.forEach(media => {
|
|
|
+ media.tracks?.forEach(track => {
|
|
|
+ const { recording } = track;
|
|
|
+ _trackArtistOnlyRecordingIdsDontIncludeMap[
|
|
|
+ recording.id
|
|
|
+ ] = true;
|
|
|
});
|
|
|
-
|
|
|
- let include = false;
|
|
|
- nonTrackArtistReleaseIds.forEach(releaseId => {
|
|
|
- if (include) return;
|
|
|
- const release = releaseMap.value[releaseId];
|
|
|
- release.media.forEach(media => {
|
|
|
- if (include) return;
|
|
|
- media.tracks?.forEach(track => {
|
|
|
- if (include) return;
|
|
|
- const { recording } = track;
|
|
|
- if (recording.id === recordingId)
|
|
|
- include = true;
|
|
|
- });
|
|
|
- });
|
|
|
+ });
|
|
|
+ });
|
|
|
+ nonTrackArtistReleaseIds.forEach(releaseId => {
|
|
|
+ const release = releaseMap.value[releaseId];
|
|
|
+ release.media.forEach(media => {
|
|
|
+ media.tracks?.forEach(track => {
|
|
|
+ const { recording } = track;
|
|
|
+ _trackArtistOnlyRecordingIdsIncludeMap[recording.id] =
|
|
|
+ true;
|
|
|
});
|
|
|
-
|
|
|
- // TODO use the below to test if the above is all needed
|
|
|
- // console.log(
|
|
|
- // `dontInclude: ${dontInclude}, include: ${include}, return: ${dontInclude && !include}`
|
|
|
- // );
|
|
|
-
|
|
|
- //
|
|
|
- return dontInclude && !include;
|
|
|
-
|
|
|
- // return dontInclude;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ trackArtistOnlyRecordingIds.value = recordingIds.value.filter(
|
|
|
+ recordingId => {
|
|
|
+ if (
|
|
|
+ _trackArtistOnlyRecordingIdsIncludeMap[recordingId] &&
|
|
|
+ _trackArtistOnlyRecordingIdsDontIncludeMap[recordingId]
|
|
|
+ ) {
|
|
|
+ console.log(recordingId);
|
|
|
+ }
|
|
|
+ return (
|
|
|
+ _trackArtistOnlyRecordingIdsDontIncludeMap[
|
|
|
+ recordingId
|
|
|
+ ] &&
|
|
|
+ !_trackArtistOnlyRecordingIdsIncludeMap[recordingId]
|
|
|
+ );
|
|
|
}
|
|
|
);
|
|
|
+
|
|
|
measureFinish(
|
|
|
"setMusicBrainzRecordingsReleasesReleaseGroups trackArtistOnlyRecordingIds"
|
|
|
);
|
|
|
- console.log(trackArtistOnlyRecordingIds.value);
|
|
|
+
|
|
|
+ measureStart(
|
|
|
+ "setMusicBrainzRecordingsReleasesReleaseGroups set recordingEntities"
|
|
|
+ );
|
|
|
+ recordingEntities.value = sortedRecordings.value.map(recording => ({
|
|
|
+ type: "single",
|
|
|
+ key: recording.id,
|
|
|
+ sortTitle: recording.title,
|
|
|
+ recording
|
|
|
+ }));
|
|
|
+ measureFinish(
|
|
|
+ "setMusicBrainzRecordingsReleasesReleaseGroups set recordingEntities"
|
|
|
+ );
|
|
|
|
|
|
measureFinish("setMusicBrainzRecordingsReleasesReleaseGroups");
|
|
|
};
|
|
@@ -1054,6 +1163,231 @@ export const useImportArtistStore = ({ modalUuid }: { modalUuid: string }) =>
|
|
|
}
|
|
|
);
|
|
|
|
|
|
+ const toggleCollapseRecordingEntityGroup = recordingEntityGroupKey => {
|
|
|
+ measureStart("toggleCollapseRecordingEntityGroup");
|
|
|
+ console.log(
|
|
|
+ `toggleCollapseRecordingEntityGroup: ${recordingEntityGroupKey} - new value: ${!collapsedRecordingEntityGroupKeys.value[recordingEntityGroupKey]}`
|
|
|
+ );
|
|
|
+ collapsedRecordingEntityGroupKeys.value[recordingEntityGroupKey] =
|
|
|
+ !collapsedRecordingEntityGroupKeys.value[
|
|
|
+ recordingEntityGroupKey
|
|
|
+ ];
|
|
|
+ measureFinish("toggleCollapseRecordingEntityGroup");
|
|
|
+ };
|
|
|
+
|
|
|
+ const recordingEntitiesCollapseAll = () => {
|
|
|
+ measureStart("recordingEntitiesCollapseAll");
|
|
|
+ console.log("recordingEntitiesCollapseAll");
|
|
|
+ const _collapsedRecordingEntityGroupKeys = {};
|
|
|
+ recordingEntities.value.forEach(recordingEntity => {
|
|
|
+ if (recordingEntity.type !== "group") return;
|
|
|
+ _collapsedRecordingEntityGroupKeys[recordingEntity.key] = true;
|
|
|
+ });
|
|
|
+ collapsedRecordingEntityGroupKeys.value =
|
|
|
+ _collapsedRecordingEntityGroupKeys;
|
|
|
+ measureFinish("recordingEntitiesCollapseAll");
|
|
|
+ };
|
|
|
+
|
|
|
+ const recordingEntitiesExpandAll = () => {
|
|
|
+ measureStart("recordingEntitiesExpandAll");
|
|
|
+ console.log("recordingEntitiesExpandAll");
|
|
|
+ const _collapsedRecordingEntityGroupKeys = {};
|
|
|
+ recordingEntities.value.forEach(recordingEntity => {
|
|
|
+ if (recordingEntity.type !== "group") return;
|
|
|
+ _collapsedRecordingEntityGroupKeys[recordingEntity.key] = false;
|
|
|
+ });
|
|
|
+ collapsedRecordingEntityGroupKeys.value =
|
|
|
+ _collapsedRecordingEntityGroupKeys;
|
|
|
+ measureFinish("recordingEntitiesExpandAll");
|
|
|
+ };
|
|
|
+
|
|
|
+ const recordingEntitiesGroupAuto = () => {
|
|
|
+ measureStart("recordingEntitiesGroupAuto");
|
|
|
+ const _recordingGroupMap: {
|
|
|
+ [recordingGroupKey: string]: RecordingTemp[];
|
|
|
+ } = {};
|
|
|
+ const _recordingEntities = [];
|
|
|
+
|
|
|
+ sortedRecordings.value.forEach(recording => {
|
|
|
+ const recordingGroupKey =
|
|
|
+ musicbrainzRecordingTitleNormalizedNewExtra(
|
|
|
+ recording.title
|
|
|
+ );
|
|
|
+ if (!_recordingGroupMap[recordingGroupKey])
|
|
|
+ _recordingGroupMap[recordingGroupKey] = [];
|
|
|
+ _recordingGroupMap[recordingGroupKey].push(recording);
|
|
|
+ });
|
|
|
+
|
|
|
+ Object.keys(_recordingGroupMap).forEach(recordingGroupKey => {
|
|
|
+ const recordingGroup = _recordingGroupMap[recordingGroupKey];
|
|
|
+ if (recordingGroup.length === 1)
|
|
|
+ delete _recordingGroupMap[recordingGroupKey];
|
|
|
+ });
|
|
|
+ const groupedRecordingIds = Object.values(_recordingGroupMap)
|
|
|
+ .map(recordingGroup =>
|
|
|
+ recordingGroup.map(recording => recording.id)
|
|
|
+ )
|
|
|
+ .flat();
|
|
|
+ const ungroupedRecordings = sortedRecordings.value.filter(
|
|
|
+ recording => !groupedRecordingIds.includes(recording.id)
|
|
|
+ );
|
|
|
+
|
|
|
+ Object.keys(_recordingGroupMap).forEach(recordingGroupKey => {
|
|
|
+ const recordingGroup = _recordingGroupMap[recordingGroupKey];
|
|
|
+ _recordingEntities.push({
|
|
|
+ type: "group",
|
|
|
+ key: recordingGroup[0].id,
|
|
|
+ sortTitle: recordingGroupKey,
|
|
|
+ title: musicbrainzRecordingTitleNormalizedNew(
|
|
|
+ recordingGroup[0].title
|
|
|
+ ),
|
|
|
+ recordings: recordingGroup
|
|
|
+ });
|
|
|
+ });
|
|
|
+ ungroupedRecordings.forEach(recording => {
|
|
|
+ _recordingEntities.push({
|
|
|
+ type: "single",
|
|
|
+ key: recording.id,
|
|
|
+ sortTitle: musicbrainzRecordingTitleNormalizedNewExtra(
|
|
|
+ recording.title
|
|
|
+ ),
|
|
|
+ recording
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ recordingEntities.value = _recordingEntities.sort();
|
|
|
+ console.log(_recordingEntities);
|
|
|
+ measureFinish("recordingEntitiesGroupAuto");
|
|
|
+ recordingEntitiesCollapseAll();
|
|
|
+ };
|
|
|
+
|
|
|
+ const sortedRecordingEntities = computed(() => {
|
|
|
+ measureStart("computed sortedRecordingEntities");
|
|
|
+ const result = recordingEntities.value.toSorted(
|
|
|
+ (recordingEntityA, recordingEntityB) =>
|
|
|
+ recordingEntityA.sortTitle.localeCompare(
|
|
|
+ recordingEntityB.sortTitle
|
|
|
+ )
|
|
|
+ );
|
|
|
+ measureFinish("computed sortedRecordingEntities");
|
|
|
+
|
|
|
+ return result;
|
|
|
+ });
|
|
|
+
|
|
|
+ // --------- videos
|
|
|
+ const toggleCollapseVideoEntityGroup = videoEntityGroupKey => {
|
|
|
+ measureStart("toggleCollapseVideoEntityGroup");
|
|
|
+ console.log(
|
|
|
+ `toggleCollapseVideoEntityGroup: ${videoEntityGroupKey} - new value: ${!collapsedVideoEntityGroupKeys.value[videoEntityGroupKey]}`
|
|
|
+ );
|
|
|
+ collapsedVideoEntityGroupKeys.value[videoEntityGroupKey] =
|
|
|
+ !collapsedVideoEntityGroupKeys.value[videoEntityGroupKey];
|
|
|
+ measureFinish("toggleCollapseVideoEntityGroup");
|
|
|
+ };
|
|
|
+
|
|
|
+ const videoEntitiesCollapseAll = () => {
|
|
|
+ measureStart("videoEntitiesCollapseAll");
|
|
|
+ console.log("videoEntitiesCollapseAll");
|
|
|
+ const _collapsedVideoEntityGroupKeys = {};
|
|
|
+ videoEntities.value.forEach(videoEntity => {
|
|
|
+ if (videoEntity.type !== "group") return;
|
|
|
+ _collapsedVideoEntityGroupKeys[videoEntity.key] = true;
|
|
|
+ });
|
|
|
+ collapsedVideoEntityGroupKeys.value =
|
|
|
+ _collapsedVideoEntityGroupKeys;
|
|
|
+ measureFinish("videoEntitiesCollapseAll");
|
|
|
+ };
|
|
|
+
|
|
|
+ const videoEntitiesExpandAll = () => {
|
|
|
+ measureStart("videoEntitiesExpandAll");
|
|
|
+ console.log("videoEntitiesExpandAll");
|
|
|
+ const _collapsedVideoEntityGroupKeys = {};
|
|
|
+ videoEntities.value.forEach(videoEntity => {
|
|
|
+ if (videoEntity.type !== "group") return;
|
|
|
+ _collapsedVideoEntityGroupKeys[videoEntity.key] = false;
|
|
|
+ });
|
|
|
+ collapsedVideoEntityGroupKeys.value =
|
|
|
+ _collapsedVideoEntityGroupKeys;
|
|
|
+ measureFinish("videoEntitiesExpandAll");
|
|
|
+ };
|
|
|
+
|
|
|
+ const videoEntitiesGroupAuto = () => {
|
|
|
+ measureStart("videoEntitiesGroupAuto");
|
|
|
+ const _videoIdGroupMap: {
|
|
|
+ [videoGroupKey: string]: string[];
|
|
|
+ } = {};
|
|
|
+ const _videoEntities = [];
|
|
|
+
|
|
|
+ youtubeVideoIds.value.forEach(videoId => {
|
|
|
+ const videoGroupKey = youtubeVideoMap.value[videoId].title
|
|
|
+ .toLowerCase()
|
|
|
+ .replace(new RegExp(`.*${artist.value.name}.* - `, "i"), "")
|
|
|
+ .replace(new RegExp(` - .*${artist.value.name}.*`, "i"), "")
|
|
|
+ .replaceAll(/\(.+\)/g, "")
|
|
|
+ .replaceAll(/\[.+\]/g, "")
|
|
|
+ .replaceAll(/\{.+\}/g, "")
|
|
|
+ .replaceAll(/-[\p{L}0-9 ]+-/gu, "") // For things like "Some title -Instrumental-"
|
|
|
+ .replaceAll(" - demo", "")
|
|
|
+ .replaceAll(/[^\p{L}0-9]/gu, "") // Also removes spaces
|
|
|
+ .trim();
|
|
|
+ if (!_videoIdGroupMap[videoGroupKey])
|
|
|
+ _videoIdGroupMap[videoGroupKey] = [];
|
|
|
+ _videoIdGroupMap[videoGroupKey].push(videoId);
|
|
|
+ });
|
|
|
+
|
|
|
+ Object.keys(_videoIdGroupMap).forEach(videoGroupKey => {
|
|
|
+ const videoGroup = _videoIdGroupMap[videoGroupKey];
|
|
|
+ if (videoGroup.length === 1)
|
|
|
+ delete _videoIdGroupMap[videoGroupKey];
|
|
|
+ });
|
|
|
+ const groupedVideoIds = Object.values(_videoIdGroupMap)
|
|
|
+ // .map(videoGroup =>
|
|
|
+ // videoGroup.map(video => video.id)
|
|
|
+ // )
|
|
|
+ .flat();
|
|
|
+ const ungroupedVideoIds = youtubeVideoIds.value.filter(
|
|
|
+ videoId => !groupedVideoIds.includes(videoId)
|
|
|
+ );
|
|
|
+
|
|
|
+ Object.keys(_videoIdGroupMap).forEach(videoGroupKey => {
|
|
|
+ const videoIdGroup = _videoIdGroupMap[videoGroupKey];
|
|
|
+ _videoEntities.push({
|
|
|
+ type: "group",
|
|
|
+ key: `${videoIdGroup[0]}-group`,
|
|
|
+ sortTitle: videoGroupKey,
|
|
|
+ title: youtubeVideoMapAdjusted.value[videoIdGroup[0]]
|
|
|
+ .titleNormalizedNew,
|
|
|
+ videoIds: videoIdGroup
|
|
|
+ });
|
|
|
+ });
|
|
|
+ ungroupedVideoIds.forEach(videoId => {
|
|
|
+ _videoEntities.push({
|
|
|
+ type: "single",
|
|
|
+ key: videoId,
|
|
|
+ sortTitle:
|
|
|
+ youtubeVideoMapAdjusted.value[videoId]
|
|
|
+ .titleNormalizedNewExtra,
|
|
|
+ videoId
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ videoEntities.value = _videoEntities.sort();
|
|
|
+ console.log(_videoEntities);
|
|
|
+ measureFinish("videoEntitiesGroupAuto");
|
|
|
+ videoEntitiesCollapseAll();
|
|
|
+ };
|
|
|
+
|
|
|
+ const sortedVideoEntities = computed(() => {
|
|
|
+ measureStart("computed sortedVideoEntities");
|
|
|
+ const result = videoEntities.value.toSorted(
|
|
|
+ (videoEntityA, videoEntityB) =>
|
|
|
+ videoEntityA.sortTitle.localeCompare(videoEntityB.sortTitle)
|
|
|
+ );
|
|
|
+ measureFinish("computed sortedVideoEntities");
|
|
|
+
|
|
|
+ return result;
|
|
|
+ });
|
|
|
+
|
|
|
return {
|
|
|
artist,
|
|
|
youtubeChannels,
|
|
@@ -1099,6 +1433,12 @@ export const useImportArtistStore = ({ modalUuid }: { modalUuid: string }) =>
|
|
|
autoLinkedRecordingsMap,
|
|
|
linkedRecordingsMap,
|
|
|
showOnlyVideosWithoutAutoLinks,
|
|
|
+ sortedRecordingEntities,
|
|
|
+ recordingEntities,
|
|
|
+ collapsedRecordingEntityGroupKeys,
|
|
|
+ sortedVideoEntities,
|
|
|
+ videoEntities,
|
|
|
+ collapsedVideoEntityGroupKeys,
|
|
|
recordingsPreviousPage,
|
|
|
recordingsNextPage,
|
|
|
// methods
|
|
@@ -1111,6 +1451,14 @@ export const useImportArtistStore = ({ modalUuid }: { modalUuid: string }) =>
|
|
|
toggleHideRecording,
|
|
|
toggleShowRecordingReleaseGroup,
|
|
|
toggleLockRecording,
|
|
|
- resetLinkingData
|
|
|
+ resetLinkingData,
|
|
|
+ recordingEntitiesGroupAuto,
|
|
|
+ toggleCollapseRecordingEntityGroup,
|
|
|
+ recordingEntitiesCollapseAll,
|
|
|
+ recordingEntitiesExpandAll,
|
|
|
+ videoEntitiesGroupAuto,
|
|
|
+ toggleCollapseVideoEntityGroup,
|
|
|
+ videoEntitiesCollapseAll,
|
|
|
+ videoEntitiesExpandAll
|
|
|
};
|
|
|
});
|