Spaces:
Running
Running
File size: 3,699 Bytes
f23825d |
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 |
import {
addDoc,
Bytes,
collection,
deleteDoc,
DocumentReference,
FirestoreDataConverter,
getDoc,
getDocs,
query,
QueryDocumentSnapshot,
serverTimestamp,
Timestamp,
updateDoc,
where,
} from "firebase/firestore"
import { songFromMidi, songToMidi } from "../common/midi/midiConversion"
import Song from "../common/song"
import { auth, firestore } from "./firebase"
export interface FirestoreSongData {
createdAt: Timestamp
updatedAt: Timestamp
data?: Bytes
userId: string
}
export interface FirestoreSong {
name: string
createdAt: Timestamp
updatedAt: Timestamp
dataRef: DocumentReference
userId: string
}
export const songConverter: FirestoreDataConverter<FirestoreSong> = {
fromFirestore(snapshot, options) {
const data = snapshot.data(options)
return data as FirestoreSong
},
toFirestore(song) {
return song
},
}
export const songDataConverter: FirestoreDataConverter<FirestoreSongData> = {
fromFirestore(snapshot, options) {
const data = snapshot.data(options)
return data as FirestoreSongData
},
toFirestore(song) {
return song
},
}
export const songCollection = collection(firestore, "songs").withConverter(
songConverter,
)
export const songDataCollection = collection(
firestore,
"songData",
).withConverter(songDataConverter)
export const loadSong = async (
songSnapshot: QueryDocumentSnapshot<FirestoreSong>,
) => {
const snapshot = await getDoc(
songSnapshot.data().dataRef.withConverter(songDataConverter),
)
const data = snapshot.data()?.data
if (data === undefined) {
throw new Error("Song data does not exist")
}
const song = songFromMidi(data.toUint8Array())
song.name = songSnapshot.data().name
song.firestoreReference = songSnapshot.ref
song.firestoreDataReference = snapshot.ref
song.isSaved = true
return song
}
export const createSong = async (song: Song) => {
if (auth.currentUser === null) {
throw new Error("You must be logged in to save songs to the cloud")
}
const bytes = songToMidi(song)
const dataDoc = await addDoc(songDataCollection, {
createdAt: serverTimestamp(),
updatedAt: serverTimestamp(),
data: Bytes.fromUint8Array(bytes),
userId: auth.currentUser.uid,
})
const doc = await addDoc(songCollection, {
name: song.name,
createdAt: serverTimestamp(),
updatedAt: serverTimestamp(),
dataRef: dataDoc,
userId: auth.currentUser.uid,
})
song.firestoreDataReference = dataDoc
song.firestoreReference = doc
song.isSaved = true
}
export const updateSong = async (song: Song) => {
if (auth.currentUser === null) {
throw new Error("You must be logged in to save songs to the cloud")
}
if (
song.firestoreReference === null ||
song.firestoreDataReference === null
) {
throw new Error("This song is not loaded from the cloud")
}
const bytes = songToMidi(song)
await updateDoc(song.firestoreReference, {
updatedAt: serverTimestamp(),
name: song.name,
})
await updateDoc(song.firestoreDataReference, {
updatedAt: serverTimestamp(),
data: Bytes.fromUint8Array(bytes),
})
song.isSaved = true
}
export const deleteSong = async (
song: QueryDocumentSnapshot<FirestoreSong>,
) => {
if (auth.currentUser === null) {
throw new Error("You must be logged in to save songs to the cloud")
}
await deleteDoc(song.data().dataRef)
await deleteDoc(song.ref)
}
export const getCurrentUserSongs = async () => {
if (auth.currentUser === null) {
throw new Error("You must be logged in to get songs from the cloud")
}
return await getDocs(
query(songCollection, where("userId", "==", auth.currentUser.uid)),
)
}
|