diff --git a/app/src/main/java/com/stormtales/notevault/data/MusicDatabase.java b/app/src/main/java/com/stormtales/notevault/data/MusicDatabase.java index 4983bfa..f22b907 100644 --- a/app/src/main/java/com/stormtales/notevault/data/MusicDatabase.java +++ b/app/src/main/java/com/stormtales/notevault/data/MusicDatabase.java @@ -5,12 +5,13 @@ import androidx.room.Database; import androidx.room.Room; import androidx.room.RoomDatabase; import androidx.room.TypeConverters; +import com.stormtales.notevault.data.entities.NoteSheet; import com.stormtales.notevault.data.entities.Song; import com.stormtales.notevault.data.dao.SongDao; import com.stormtales.notevault.data.sync.DateConverter; import com.stormtales.notevault.data.sync.SyncStatusConverter; -@Database(entities = {Song.class}, version = 1, exportSchema = false) +@Database(entities = {Song.class, NoteSheet.class}, version = 1, exportSchema = false) @TypeConverters({SyncStatusConverter.class, DateConverter.class}) public abstract class MusicDatabase extends RoomDatabase { public abstract SongDao getSongTable(); diff --git a/app/src/main/java/com/stormtales/notevault/data/dao/SongDao.java b/app/src/main/java/com/stormtales/notevault/data/dao/SongDao.java index f8a7d15..e3a8773 100644 --- a/app/src/main/java/com/stormtales/notevault/data/dao/SongDao.java +++ b/app/src/main/java/com/stormtales/notevault/data/dao/SongDao.java @@ -1,10 +1,8 @@ package com.stormtales.notevault.data.dao; import androidx.lifecycle.LiveData; -import androidx.room.Dao; -import androidx.room.Insert; -import androidx.room.Query; -import androidx.room.Update; +import androidx.room.*; +import com.stormtales.notevault.data.entities.NoteSheet; import com.stormtales.notevault.data.entities.Song; import java.util.List; @@ -12,11 +10,19 @@ import java.util.List; @Dao public interface SongDao { @Insert - void insert(Song song); + long insert(Song song); @Query("SELECT * FROM song WHERE syncStatus != 1") List getAllSongs(); @Update void update(Song song); + + @Insert + void insert(List noteSheets); + + @Delete + void deleteNoteSheets(List noteSheets); + + List getNoteSheetsBySong(int songID); } diff --git a/app/src/main/java/com/stormtales/notevault/data/entities/NoteSheet.java b/app/src/main/java/com/stormtales/notevault/data/entities/NoteSheet.java index 8f65f08..4520136 100644 --- a/app/src/main/java/com/stormtales/notevault/data/entities/NoteSheet.java +++ b/app/src/main/java/com/stormtales/notevault/data/entities/NoteSheet.java @@ -7,13 +7,17 @@ import java.util.Objects; @Entity public class NoteSheet { - @PrimaryKey + @PrimaryKey(autoGenerate = true) private int localID; - private int songID; private String localFileName; private String hash; + public NoteSheet(String localFileName, String hash) { + this.localFileName = localFileName; + this.hash = hash; + } + public int getLocalID() { return localID; } @@ -49,4 +53,12 @@ public class NoteSheet { public int hashCode() { return Objects.hash(localID, localFileName, hash); } + + public int getSongID() { + return songID; + } + + public void setSongID(int songID) { + this.songID = songID; + } } diff --git a/app/src/main/java/com/stormtales/notevault/data/repositories/SongRepository.java b/app/src/main/java/com/stormtales/notevault/data/repositories/SongRepository.java index 1d7f984..3c62e67 100644 --- a/app/src/main/java/com/stormtales/notevault/data/repositories/SongRepository.java +++ b/app/src/main/java/com/stormtales/notevault/data/repositories/SongRepository.java @@ -7,7 +7,9 @@ import android.os.Looper; import androidx.lifecycle.LiveData; import com.stormtales.notevault.data.MusicDatabase; import com.stormtales.notevault.data.dao.SongDao; +import com.stormtales.notevault.data.entities.NoteSheet; import com.stormtales.notevault.data.entities.Song; +import com.stormtales.notevault.data.sync.SyncStatus; import java.util.List; import java.util.concurrent.ExecutorService; @@ -19,9 +21,11 @@ public class SongRepository { MusicDatabase database = MusicDatabase.getDatabase(context); songDao = database.getSongTable(); } - public void insert(Song song) { + public void insert(Song song, Callback callback) { Executors.newSingleThreadExecutor().execute(() -> { - songDao.insert(song); + long result = songDao.insert(song); + Handler mainHandler = new Handler(Looper.getMainLooper()); + mainHandler.post(()-> callback.onResult(result)); }); } @@ -43,4 +47,19 @@ public class SongRepository { songDao.update(song); }); } + + public void insertNoteSheets(List noteSheets) { + Executors.newSingleThreadExecutor().execute(() -> { + songDao.insert(noteSheets); + }); + } + + public interface Callback { + void onResult(T result); + } + + public void deleteSong(Song song) { + song.setSyncStatus(SyncStatus.DELETED); + songDao.update(song); + } } diff --git a/app/src/main/java/com/stormtales/notevault/ui/home/HomeViewModel.java b/app/src/main/java/com/stormtales/notevault/ui/home/HomeViewModel.java index 33a9deb..51d79cd 100644 --- a/app/src/main/java/com/stormtales/notevault/ui/home/HomeViewModel.java +++ b/app/src/main/java/com/stormtales/notevault/ui/home/HomeViewModel.java @@ -1,15 +1,13 @@ package com.stormtales.notevault.ui.home; -import android.app.Application; import android.util.Log; -import androidx.annotation.NonNull; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; +import com.stormtales.notevault.data.entities.NoteSheet; import com.stormtales.notevault.data.entities.Song; import com.stormtales.notevault.data.repositories.SongRepository; import com.stormtales.notevault.data.sync.SyncStatus; -import kotlinx.coroutines.CoroutineScope; import java.util.ArrayList; import java.util.List; @@ -25,8 +23,15 @@ public class HomeViewModel extends ViewModel { /*this.allSongs.setValue(songRepository.getAllSongs());*/ } - public void addSong(Song song) { - songRepository.insert(song); + public void addSong(Song song, List noteSheetList) { + songRepository.insert(song, internalSongID -> { + for(NoteSheet noteSheet : noteSheetList) { + noteSheet.setSongID(Math.toIntExact(internalSongID)); + } + songRepository.insertNoteSheets(noteSheetList); + }); + + List currentSongs = allSongs.getValue(); if(currentSongs == null) { currentSongs = new ArrayList<>(); @@ -54,8 +59,7 @@ public class HomeViewModel extends ViewModel { } public void deleteSong(Song song) { - song.setSyncStatus(SyncStatus.DELETED); - songRepository.updateSong(song); + songRepository.deleteSong(song); List currentSongs = allSongs.getValue(); if(currentSongs != null) { diff --git a/app/src/main/java/com/stormtales/notevault/ui/songeditor/SongEditorDialog.java b/app/src/main/java/com/stormtales/notevault/ui/songeditor/SongEditorDialog.java index 328a6fb..b8af916 100644 --- a/app/src/main/java/com/stormtales/notevault/ui/songeditor/SongEditorDialog.java +++ b/app/src/main/java/com/stormtales/notevault/ui/songeditor/SongEditorDialog.java @@ -2,6 +2,7 @@ package com.stormtales.notevault.ui.songeditor; import android.app.AlertDialog; import android.app.Dialog; +import android.content.Context; import android.net.Uri; import android.os.Bundle; import android.text.Layout; @@ -16,11 +17,17 @@ import android.view.View; import android.view.ViewGroup; import androidx.lifecycle.ViewModelProvider; import com.stormtales.notevault.R; +import com.stormtales.notevault.data.entities.NoteSheet; import com.stormtales.notevault.data.entities.Song; import com.stormtales.notevault.data.sync.SyncStatus; import com.stormtales.notevault.ui.home.HomeViewModel; +import com.stormtales.notevault.utils.NoteSheetsUtil; +import com.stormtales.notevault.utils.Tupel; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; + public class SongEditorDialog extends DialogFragment { @@ -89,7 +96,15 @@ public class SongEditorDialog extends DialogFragment { homeViewModel.updateSong(editedSong); } else { Song song = new Song(title, composer, genre, releaseYear); - homeViewModel.addSong(song); + + List noteSheetList = new ArrayList<>(); + Context context = this.getContext(); + for(Uri uri : noteSheetFiles) { + Tupel result = NoteSheetsUtil.saveImageInternally(context.getContentResolver(), uri, context.getFilesDir()); + noteSheetList.add(new NoteSheet(result.getValue00(), result.getValue01())); + } + + homeViewModel.addSong(song, noteSheetList); } diff --git a/app/src/main/java/com/stormtales/notevault/utils/NoteSheetsUtil.java b/app/src/main/java/com/stormtales/notevault/utils/NoteSheetsUtil.java index 388a7be..ae21a14 100644 --- a/app/src/main/java/com/stormtales/notevault/utils/NoteSheetsUtil.java +++ b/app/src/main/java/com/stormtales/notevault/utils/NoteSheetsUtil.java @@ -1,5 +1,6 @@ package com.stormtales.notevault.utils; +import android.content.ContentResolver; import android.content.Context; import android.media.ExifInterface; import android.net.Uri; @@ -7,6 +8,10 @@ import android.net.Uri; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; @@ -46,4 +51,37 @@ public class NoteSheetsUtil { } } + public static Tupel saveImageInternally(ContentResolver contentResolver, Uri uri, File filesDir) { + try (InputStream inputStream = contentResolver.openInputStream(uri)) { + // Datei erstellen + File imageFile = new File(filesDir, "saved_image_" + System.currentTimeMillis() + ".jpg"); + try (OutputStream outputStream = Files.newOutputStream(imageFile.toPath())) { + // SHA-256 Hash-Funktion initialisieren + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + + // Daten blockweise lesen und gleichzeitig schreiben und hashen + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + digest.update(buffer, 0, bytesRead); // Hash aktualisieren + } + + // Hash berechnen + byte[] hashBytes = digest.digest(); + StringBuilder hashString = new StringBuilder(); + for (byte b : hashBytes) { + hashString.append(String.format("%02x", b)); // Bytes in Hexadezimal umwandeln + } + + // Hashwert zurückgeben (kann auch zusammen mit dem Pfad gespeichert werden) + return new Tupel<>(imageFile.getAbsolutePath(), hashString.toString()); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } } diff --git a/app/src/main/java/com/stormtales/notevault/utils/Tupel.java b/app/src/main/java/com/stormtales/notevault/utils/Tupel.java new file mode 100644 index 0000000..c9074d8 --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/utils/Tupel.java @@ -0,0 +1,33 @@ +package com.stormtales.notevault.utils; + +import java.util.Objects; + +public class Tupel { + private final A value00; + private final B value01; + + public Tupel(A value00, B value01) { + this.value00 = value00; + this.value01 = value01; + } + + public A getValue00() { + return value00; + } + + public B getValue01() { + return value01; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + Tupel tupel = (Tupel) o; + return Objects.equals(value00, tupel.value00) && Objects.equals(value01, tupel.value01); + } + + @Override + public int hashCode() { + return Objects.hash(value00, value01); + } +}