xref: /MusicFree/src/utils/mediaItem.ts (revision 5589cdf32b2bb0f641e5ac7bf1f6152cd6b9b70e)
1import {
2    internalSerializeKey,
3    localPluginPlatform,
4    sortIndexSymbol,
5    timeStampSymbol,
6} from '@/constants/commonConst';
7import MediaMeta from '@/core/mediaExtra';
8import {produce} from 'immer';
9import objectPath from 'object-path';
10
11/** 获取mediakey */
12export function getMediaKey(mediaItem: ICommon.IMediaBase) {
13    return `${mediaItem.platform}@${mediaItem.id}`;
14}
15
16/** 解析mediakey */
17export function parseMediaKey(key: string): ICommon.IMediaBase {
18    try {
19        const str = JSON.parse(key.trim());
20        let platform, id;
21        if (typeof str === 'string') {
22            [platform, id] = str.split('@');
23        } else {
24            platform = str?.platform;
25            id = str?.id;
26        }
27        if (!platform || !id) {
28            throw new Error('mediakey不完整');
29        }
30        return {
31            platform,
32            id,
33        };
34    } catch (e: any) {
35        throw e;
36    }
37}
38
39/** 比较两media是否相同 */
40export function isSameMediaItem(
41    a: ICommon.IMediaBase | null | undefined,
42    b: ICommon.IMediaBase | null | undefined,
43) {
44    // eslint-disable-next-line eqeqeq
45    return a && b && a.id == b.id && a.platform === b.platform;
46}
47
48/** 查找是否存在 */
49export function includesMedia(
50    a: ICommon.IMediaBase[] | null | undefined,
51    b: ICommon.IMediaBase | null | undefined,
52) {
53    if (!a || !b) {
54        return false;
55    }
56    return a.findIndex(_ => isSameMediaItem(_, b)) !== -1;
57}
58
59/** 获取复位的mediaItem */
60export function resetMediaItem<T extends Partial<ICommon.IMediaBase>>(
61    mediaItem: T,
62    platform?: string,
63    newObj?: boolean,
64): T {
65    // 本地音乐不做处理
66    if (
67        mediaItem.platform === localPluginPlatform ||
68        platform === localPluginPlatform
69    ) {
70        return newObj ? {...mediaItem} : mediaItem;
71    }
72    if (!newObj) {
73        mediaItem.platform = platform ?? mediaItem.platform;
74        mediaItem[internalSerializeKey] = undefined;
75        return mediaItem;
76    } else {
77        return produce(mediaItem, _ => {
78            _.platform = platform ?? mediaItem.platform;
79            _[internalSerializeKey] = undefined;
80        });
81    }
82}
83
84export function mergeProps(
85    mediaItem: ICommon.IMediaBase,
86    props: Record<string, any> | undefined,
87    anotherProps?: Record<string, any> | undefined | null,
88) {
89    return props
90        ? {
91              ...mediaItem,
92              ...props,
93              ...(anotherProps ?? {}),
94              id: mediaItem.id,
95              platform: mediaItem.platform,
96          }
97        : mediaItem;
98}
99
100export enum InternalDataType {
101    LOCALPATH = 'localPath',
102}
103
104export function setInternalData<T extends ICommon.IMediaBase>(
105    mediaItem: T,
106    key: InternalDataType,
107    value: string | number | undefined | null,
108): T {
109    return produce(mediaItem, draft => {
110        objectPath.set(draft, `${internalSerializeKey}.${key}`, value);
111    });
112}
113
114export function getInternalData<T>(
115    mediaItem: ICommon.IMediaBase | null | undefined,
116    key: InternalDataType,
117): T | undefined {
118    if (!mediaItem) {
119        return undefined;
120    }
121    return objectPath.get(mediaItem, `${internalSerializeKey}.${key}`);
122}
123
124export function trimInternalData(
125    mediaItem: ICommon.IMediaBase | null | undefined,
126) {
127    if (!mediaItem) {
128        return undefined;
129    }
130    return {
131        ...mediaItem,
132        [internalSerializeKey]: undefined,
133    };
134}
135
136/** 关联歌词 */
137export async function associateLrc(
138    musicItem: ICommon.IMediaBase,
139    linkto: ICommon.IMediaBase,
140) {
141    if (!musicItem || !linkto) {
142        throw new Error('');
143    }
144
145    // 如果相同直接断链
146    MediaMeta.update(musicItem, {
147        associatedLrc: isSameMediaItem(musicItem, linkto) ? undefined : linkto,
148    });
149}
150
151export function sortByTimestampAndIndex(array: any[], newArray = false) {
152    if (newArray) {
153        array = [...array];
154    }
155    return array.sort((a, b) => {
156        const ts = a[timeStampSymbol] - b[timeStampSymbol];
157        if (ts !== 0) {
158            return ts;
159        }
160        return a[sortIndexSymbol] - b[sortIndexSymbol];
161    });
162}
163