Repository navigation
Expand file tree
/
Copy pathcuratedLibrarySync.ts
More file actions
186 lines (159 loc) · 5.01 KB
/
Copy pathcuratedLibrarySync.ts
File metadata and controls
186 lines (159 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
export const CURATED_LIBRARY_SYNC_PROTOCOL_VERSION = 1
export const CURATED_LIBRARY_SYNC_PROGRESS_ID = 'curated-library-sync'
export const CURATED_LIBRARY_SYNC_CANCEL_CHANNEL = 'curatedLibrarySync/cancel'
/** 精选库同步改了哪些歌单文件。渲染进程按路径就地增删,不要整表重扫。 */
export const CURATED_LIBRARY_SYNC_PLAYLISTS_CHANGED_CHANNEL = 'curatedLibrarySync/playlistsChanged'
export type CuratedLibrarySyncListFileChange = {
listUUID: string
absPath: string
libraryPath: string
trackNumber: number | null
addedAtMs: number | null
}
export type CuratedLibrarySyncPlaylistsChangedPayload = {
uuids: string[]
removed: CuratedLibrarySyncListFileChange[]
added: CuratedLibrarySyncListFileChange[]
updated: CuratedLibrarySyncListFileChange[]
}
export const CURATED_LIBRARY_SYNC_BLOB_CHUNK_SIZE = 8 * 1024 * 1024
/** 云端快照里代表「精选库根」的父节点。各机精选库 library 节点 UUID 不同,不能直接当 parentUuid。 */
export const CURATED_LIBRARY_SYNC_ROOT_PARENT_UUID = '00000000-0000-4000-8000-000000000000'
export type CuratedLibrarySyncJoinMode = 'merge' | 'cloud-wins' | 'local-wins'
export type CuratedLibrarySyncTrigger = 'manual' | 'scheduled' | 'realtime'
export type CuratedLibrarySyncLocation = 'curated' | 'recycle' | 'custody' | 'missing'
export type CuratedLibrarySyncNodeType = 'dir' | 'songList'
export type CuratedLibrarySyncCloudNode = {
uuid: string
parentUuid: string
name: string
nodeType: CuratedLibrarySyncNodeType
sortOrder: number | null
updatedAtMs: number
revision?: number
}
export type CuratedLibrarySyncCloudFile = {
fileId: string
parentUuid: string
fileName: string
sha256: string
size: number
trackNumber: number | null
addedAtMs: number | null
updatedAtMs: number
revision?: number
}
export type CuratedLibrarySyncTombstone = {
kind: 'file' | 'node'
id: string
revision: number
deletedAtMs: number
}
export type CuratedLibrarySyncSnapshot = {
protocolVersion: number
revision: number
snapshotReady: boolean
full?: boolean
nodes: CuratedLibrarySyncCloudNode[]
files: CuratedLibrarySyncCloudFile[]
tombstones: CuratedLibrarySyncTombstone[]
}
export type CuratedLibrarySyncOp =
| { type: 'upsertNode'; node: CuratedLibrarySyncCloudNode }
| { type: 'deleteNode'; uuid: string; updatedAtMs: number }
| { type: 'upsertFile'; file: CuratedLibrarySyncCloudFile }
| { type: 'deleteFile'; fileId: string; updatedAtMs: number }
| { type: 'undeleteFile'; file: CuratedLibrarySyncCloudFile }
export type CuratedLibrarySyncConflictKind =
| 'file-move-lost'
| 'file-rename-lost'
| 'file-content-lost'
| 'file-delete-lost'
| 'file-undelete-lost'
| 'file-order-lost'
| 'node-change-lost'
| 'node-delete-lost'
export type CuratedLibrarySyncConflictItem = {
kind: CuratedLibrarySyncConflictKind
name: string
otherName?: string
}
export type CuratedLibrarySyncFailureItem = {
direction: 'upload' | 'download'
name: string
errorKey: string
atMs: number
sha256?: string
fileId?: string
}
export type CuratedLibrarySyncActivityPhase =
| 'idle'
| 'scanning'
| 'downloading'
| 'uploading'
| 'waiting-first-snapshot'
| 'applying'
export type CuratedLibrarySyncActivity = {
running: boolean
phase: CuratedLibrarySyncActivityPhase
now: number
total: number
}
export type CuratedLibrarySyncTerminalStatus =
| 'idle'
| 'success'
| 'up_to_date'
| 'failed'
| 'cancelled'
/** 主进程唯一精选库同步会话的实时状态。 */
export type CuratedLibrarySyncStatus = CuratedLibrarySyncActivity & {
trigger: CuratedLibrarySyncTrigger | null
terminalStatus: CuratedLibrarySyncTerminalStatus
message?: string
updatedAtMs: number
}
export type CuratedLibrarySyncOverview = {
liveConnected: boolean
snapshotReady: boolean
revision: number
fileCount: number
quotaUsedBytes: number
quotaBytes: number
conflicts: CuratedLibrarySyncConflictItem[]
failures: CuratedLibrarySyncFailureItem[]
activity: CuratedLibrarySyncActivity
}
export type CuratedLibrarySyncNotice = {
kind: 'conflicts' | 'failures'
conflictCount: number
failureCount: number
}
export type CuratedLibrarySyncStartPayload = {
trigger?: CuratedLibrarySyncTrigger
joinMode?: CuratedLibrarySyncJoinMode
confirmOverwriteCloud?: boolean
/** 一次性手动同步:允许在未开启「同步精选库」实时开关时仍然跑一次 */
allowWhenDisabled?: boolean
}
export type CuratedLibrarySyncStartResult =
| { status: 'success'; changed?: boolean }
| { status: 'already_running' }
| { status: 'cancelled' }
| { status: 'not_enabled' }
| { status: 'not_configured' }
| { status: 'busy_library' }
| { status: 'disk_full' }
| { status: 'paused_offline' }
| { status: 'failed'; message: string }
| {
status: 'needs_join_choice'
localFileCount: number
cloudFileCount: number
cloudRevision: number
}
| {
status: 'needs_overwrite_cloud_confirm'
localFileCount: number
cloudFileCount: number
cloudRevision: number
}