xref: /MusicFree/src/utils/mediaItem.ts (revision 6613e77203923e5b1742a49281bfa5de03fc1440)
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    TIMESTAMP = 'timestamp',
104    // 如果时间相同,辅助排序
105    SORTINDEX = 'sortIndex',
106}
107
108export function setInternalData<T extends ICommon.IMediaBase>(
109    mediaItem: T,
110    key: InternalDataType,
111    value: string | number | undefined | null,
112): T {
113    return produce(mediaItem, draft => {
114        objectPath.set(draft, `${internalSerializeKey}.${key}`, value);
115    });
116}
117
118export function getInternalData<T>(
119    mediaItem: ICommon.IMediaBase | null | undefined,
120    key: InternalDataType,
121): T | undefined {
122    if (!mediaItem) {
123        return undefined;
124    }
125    return objectPath.get(mediaItem, `${internalSerializeKey}.${key}`);
126}
127
128export function trimInternalData(
129    mediaItem: ICommon.IMediaBase | null | undefined,
130) {
131    if (!mediaItem) {
132        return undefined;
133    }
134    return {
135        ...mediaItem,
136        [internalSerializeKey]: undefined,
137    };
138}
139
140/** 关联歌词 */
141export async function associateLrc(
142    musicItem: ICommon.IMediaBase,
143    linkto: ICommon.IMediaBase,
144) {
145    if (!musicItem || !linkto) {
146        throw new Error('');
147    }
148
149    // 如果相同直接断链
150    MediaMeta.update(musicItem, {
151        associatedLrc: isSameMediaItem(musicItem, linkto) ? undefined : linkto,
152    });
153}
154
155export function sortByTimestampAndIndex(array: any[], newArray = false) {
156    if (newArray) {
157        array = [...array];
158    }
159    return array.sort((a, b) => {
160        const ts = a[timeStampSymbol] - b[timeStampSymbol];
161        if (ts !== 0) {
162            return ts;
163        }
164        return a[sortIndexSymbol] - b[sortIndexSymbol];
165    });
166}
167