Compare commits
1 Commits
master
...
view-songs
Author | SHA1 | Date | |
---|---|---|---|
|
d3d1f482a8 |
6
.gitignore
vendored
@ -13,9 +13,3 @@
|
|||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
.cxx
|
.cxx
|
||||||
local.properties
|
local.properties
|
||||||
/music_database
|
|
||||||
/music_database-shm
|
|
||||||
/music_database-wal
|
|
||||||
/note_database
|
|
||||||
/note_database-shm
|
|
||||||
/note_database-wal
|
|
||||||
|
1
.idea/.gitignore
vendored
@ -6,4 +6,3 @@
|
|||||||
# Datasource local storage ignored files
|
# Datasource local storage ignored files
|
||||||
/dataSources/
|
/dataSources/
|
||||||
/dataSources.local.xml
|
/dataSources.local.xml
|
||||||
/AndroidProjectSystem.xml
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
NoteVault
|
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="AndroidProjectSystem">
|
|
||||||
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,10 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<code_scheme name="Project" version="173">
|
|
||||||
<JetCodeStyleSettings>
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
</JetCodeStyleSettings>
|
|
||||||
<codeStyleSettings language="kotlin">
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
</codeStyleSettings>
|
|
||||||
</code_scheme>
|
|
||||||
</component>
|
|
@ -1,5 +1,5 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
<state>
|
<state>
|
||||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||||
</state>
|
</state>
|
||||||
</component>
|
</component>
|
@ -1,71 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
|
||||||
<data-source source="LOCAL" name="music_database" uuid="95a3c2ec-2c29-4336-900a-3993de90ae66">
|
|
||||||
<driver-ref>sqlite.xerial</driver-ref>
|
|
||||||
<synchronize>true</synchronize>
|
|
||||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
|
||||||
<jdbc-url>jdbc:sqlite:$USER_HOME$/.cache/JetBrains/IntelliJIdea2025.1/device-explorer/samsung SM-P610/_/data/data/com.stormtales.notevault/databases/music_database</jdbc-url>
|
|
||||||
<jdbc-additional-properties>
|
|
||||||
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
|
||||||
</jdbc-additional-properties>
|
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
|
||||||
<libraries>
|
|
||||||
<library>
|
|
||||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
|
|
||||||
</library>
|
|
||||||
<library>
|
|
||||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
|
||||||
</library>
|
|
||||||
</libraries>
|
|
||||||
</data-source>
|
|
||||||
<data-source source="LOCAL" name="note_database" uuid="b3770d7c-0a73-40c6-aab8-010effaa19b6">
|
|
||||||
<driver-ref>sqlite.xerial</driver-ref>
|
|
||||||
<synchronize>true</synchronize>
|
|
||||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
|
||||||
<jdbc-url>jdbc:sqlite:$USER_HOME$/.cache/JetBrains/IntelliJIdea2025.1/device-explorer/samsung SM-P610/_/data/data/come.stormborntales.notevault/databases/note_database</jdbc-url>
|
|
||||||
<jdbc-additional-properties>
|
|
||||||
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
|
||||||
</jdbc-additional-properties>
|
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
|
||||||
<libraries>
|
|
||||||
<library>
|
|
||||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
|
|
||||||
</library>
|
|
||||||
<library>
|
|
||||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
|
||||||
</library>
|
|
||||||
<library>
|
|
||||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
|
|
||||||
</library>
|
|
||||||
<library>
|
|
||||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
|
||||||
</library>
|
|
||||||
</libraries>
|
|
||||||
</data-source>
|
|
||||||
<data-source source="LOCAL" name="note_database [2]" uuid="ad94cfd9-e485-4151-8bf4-a080c51fa27c">
|
|
||||||
<driver-ref>sqlite.xerial</driver-ref>
|
|
||||||
<synchronize>true</synchronize>
|
|
||||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
|
||||||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/note_database</jdbc-url>
|
|
||||||
<jdbc-additional-properties>
|
|
||||||
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
|
||||||
</jdbc-additional-properties>
|
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
|
||||||
<libraries>
|
|
||||||
<library>
|
|
||||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
|
|
||||||
</library>
|
|
||||||
<library>
|
|
||||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
|
||||||
</library>
|
|
||||||
<library>
|
|
||||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
|
|
||||||
</library>
|
|
||||||
<library>
|
|
||||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
|
||||||
</library>
|
|
||||||
</libraries>
|
|
||||||
</data-source>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
13
.idea/deploymentTargetDropDown.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="deploymentTargetDropDown">
|
||||||
|
<value>
|
||||||
|
<entry key="NoteVault">
|
||||||
|
<State />
|
||||||
|
</entry>
|
||||||
|
<entry key="app">
|
||||||
|
<State />
|
||||||
|
</entry>
|
||||||
|
</value>
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -4,14 +4,6 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2025-05-03T08:34:29.354537334Z">
|
|
||||||
<Target type="DEFAULT_BOOT">
|
|
||||||
<handle>
|
|
||||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=R52N50NLGRT" />
|
|
||||||
</handle>
|
|
||||||
</Target>
|
|
||||||
</DropdownSelection>
|
|
||||||
<DialogSelection />
|
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="gradleJvm" value="21" />
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<profile version="1.0">
|
|
||||||
<option name="myName" value="Project Default" />
|
|
||||||
<inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="GlancePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="GlancePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="GlancePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewDeviceShouldUseNewSpec" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewParameterProviderOnFirstParameter" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
</profile>
|
|
||||||
</component>
|
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="KotlinJpsPluginSettings">
|
|
||||||
<option name="version" value="2.0.0" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -3,5 +3,10 @@
|
|||||||
<component name="FrameworkDetectionExcludesConfiguration">
|
<component name="FrameworkDetectionExcludesConfiguration">
|
||||||
<file type="web" url="file://$PROJECT_DIR$" />
|
<file type="web" url="file://$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK" />
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectType">
|
||||||
|
<option name="id" value="Android" />
|
||||||
|
</component>
|
||||||
</project>
|
</project>
|
@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="RunConfigurationProducerService">
|
|
||||||
<option name="ignoredProducers">
|
|
||||||
<set>
|
|
||||||
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
|
||||||
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
|
||||||
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
|
||||||
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
|
||||||
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
|
||||||
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
|
||||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
|
||||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -1,17 +1,15 @@
|
|||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.application)
|
alias(libs.plugins.android.application)
|
||||||
alias(libs.plugins.kotlin.android)
|
|
||||||
alias(libs.plugins.kotlin.compose)
|
|
||||||
alias(libs.plugins.ksp) // NEU
|
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "come.stormborntales.notevault"
|
namespace = "core.notevault"
|
||||||
compileSdk = 34
|
compileSdk = 34
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "come.stormborntales.notevault"
|
applicationId = "core.notevault"
|
||||||
minSdk = 24
|
minSdk = 26
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 1
|
versionCode = 1
|
||||||
versionName = "1.0"
|
versionName = "1.0"
|
||||||
@ -26,41 +24,35 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
}
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = "11"
|
|
||||||
}
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose = true
|
viewBinding = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation(libs.androidx.core.ktx)
|
implementation(libs.appcompat)
|
||||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
implementation(libs.material)
|
||||||
implementation(libs.androidx.activity.compose)
|
implementation(libs.constraintlayout)
|
||||||
implementation(platform(libs.androidx.compose.bom))
|
|
||||||
implementation(libs.androidx.ui)
|
|
||||||
implementation(libs.androidx.ui.graphics)
|
|
||||||
implementation(libs.androidx.ui.tooling.preview)
|
|
||||||
implementation(libs.androidx.material3)
|
|
||||||
implementation(libs.androidx.navigation.compose)
|
|
||||||
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
|
||||||
testImplementation(libs.junit)
|
|
||||||
androidTestImplementation(libs.androidx.junit)
|
|
||||||
androidTestImplementation(libs.androidx.espresso.core)
|
|
||||||
androidTestImplementation(platform(libs.androidx.compose.bom))
|
|
||||||
androidTestImplementation(libs.androidx.ui.test.junit4)
|
|
||||||
debugImplementation(libs.androidx.ui.tooling)
|
|
||||||
debugImplementation(libs.androidx.ui.test.manifest)
|
|
||||||
implementation(libs.androidx.foundation)
|
|
||||||
implementation(libs.androidx.room.runtime)
|
|
||||||
implementation(libs.androidx.room.ktx)
|
|
||||||
implementation(libs.lifecycle.livedata.ktx)
|
implementation(libs.lifecycle.livedata.ktx)
|
||||||
implementation(libs.compose.runtime.livedata)
|
implementation(libs.lifecycle.viewmodel.ktx)
|
||||||
implementation(libs.coil.compose)
|
implementation(libs.navigation.fragment)
|
||||||
ksp(libs.androidx.room.compiler)
|
implementation(libs.navigation.ui)
|
||||||
|
implementation(libs.room.common)
|
||||||
|
implementation("androidx.recyclerview:recyclerview:1.3.2")
|
||||||
|
testImplementation(libs.junit)
|
||||||
|
androidTestImplementation(libs.ext.junit)
|
||||||
|
androidTestImplementation(libs.espresso.core)
|
||||||
|
|
||||||
|
val room_version = "2.6.1" // Aktuelle Room-Version
|
||||||
|
|
||||||
|
implementation("androidx.room:room-runtime:$room_version")
|
||||||
|
annotationProcessor("androidx.room:room-compiler:$room_version") // Für Annotation Processing
|
||||||
|
|
||||||
|
// Optional: Unterstützung für Kotlin Coroutines oder RxJava
|
||||||
|
implementation("androidx.room:room-ktx:$room_version") // Für Kotlin-Extensions
|
||||||
|
implementation("androidx.room:room-rxjava3:$room_version") // Für RxJava-Unterstützung
|
||||||
}
|
}
|
@ -1,24 +0,0 @@
|
|||||||
package come.stormborntales.notevault
|
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
fun useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
|
||||||
assertEquals("come.stormborntales.notevault", appContext.packageName)
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,25 @@
|
|||||||
|
package core.notevault;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class ExampleInstrumentedTest {
|
||||||
|
@Test
|
||||||
|
public void useAppContext() {
|
||||||
|
// Context of the app under test.
|
||||||
|
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||||
|
assertEquals("core.notevault", appContext.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
@ -16,14 +16,13 @@
|
|||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/Theme.NoteVault">
|
android:theme="@style/Theme.NoteVault.NoActionBar">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".FullscreenImageViewerActivity" />
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 197 KiB |
@ -1,26 +0,0 @@
|
|||||||
package come.stormborntales.notevault
|
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.activity.compose.setContent
|
|
||||||
import come.stormborntales.notevault.ui.screens.FullscreenImageViewer
|
|
||||||
import come.stormborntales.notevault.ui.theme.NoteVaultTheme
|
|
||||||
|
|
||||||
// FullscreenImageViewerActivity.kt
|
|
||||||
class FullscreenImageViewerActivity : ComponentActivity() {
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
val imageUris = intent.getParcelableArrayListExtra<Uri>("imageUris") ?: emptyList()
|
|
||||||
|
|
||||||
setContent {
|
|
||||||
NoteVaultTheme {
|
|
||||||
FullscreenImageViewer(
|
|
||||||
images = imageUris,
|
|
||||||
onClose = { finish() }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,253 +0,0 @@
|
|||||||
package come.stormborntales.notevault
|
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
|
||||||
import androidx.activity.compose.setContent
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.AccountCircle
|
|
||||||
import androidx.compose.material.icons.filled.Menu
|
|
||||||
import androidx.compose.material3.DrawerValue
|
|
||||||
import androidx.compose.material3.DropdownMenu
|
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.ModalDrawerSheet
|
|
||||||
import androidx.compose.material3.ModalNavigationDrawer
|
|
||||||
import androidx.compose.material3.NavigationDrawerItem
|
|
||||||
import androidx.compose.material3.NavigationDrawerItemDefaults
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextField
|
|
||||||
import androidx.compose.material3.TextFieldDefaults
|
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.material3.rememberDrawerState
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
|
||||||
import androidx.navigation.compose.NavHost
|
|
||||||
import androidx.navigation.compose.composable
|
|
||||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
|
||||||
import androidx.navigation.compose.rememberNavController
|
|
||||||
import come.stormborntales.notevault.data.local.AppDatabase
|
|
||||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
|
||||||
import come.stormborntales.notevault.data.repository.NoteRepository
|
|
||||||
import come.stormborntales.notevault.ui.screens.AddNoteDialog
|
|
||||||
import come.stormborntales.notevault.ui.screens.MainScreen
|
|
||||||
import come.stormborntales.notevault.ui.screens.NotesScreen
|
|
||||||
import come.stormborntales.notevault.ui.screens.SettingsScreen
|
|
||||||
import come.stormborntales.notevault.ui.theme.NoteVaultTheme
|
|
||||||
import come.stormborntales.notevault.ui.viewmodel.NoteViewModel
|
|
||||||
import come.stormborntales.notevault.ui.viewmodel.NoteViewModelFactory
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
val applicationContext = applicationContext
|
|
||||||
val database = AppDatabase.getDatabase(applicationContext)
|
|
||||||
val repository = NoteRepository(database.noteDao())
|
|
||||||
val viewModelFactory = NoteViewModelFactory(repository)
|
|
||||||
|
|
||||||
setContent {
|
|
||||||
NoteVaultTheme {
|
|
||||||
val navController = rememberNavController()
|
|
||||||
val viewModel: NoteViewModel = viewModel(factory = viewModelFactory)
|
|
||||||
|
|
||||||
var selectedUris by remember { mutableStateOf<List<Uri>>(emptyList()) }
|
|
||||||
var showDialog by remember { mutableStateOf(false) }
|
|
||||||
var noteToEdit by remember { mutableStateOf<NoteEntity?>(null) }
|
|
||||||
val drawerState = rememberDrawerState(DrawerValue.Closed)
|
|
||||||
val scope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
val imagePickerLauncher = rememberLauncherForActivityResult(
|
|
||||||
contract = ActivityResultContracts.OpenMultipleDocuments(),
|
|
||||||
onResult = { uris ->
|
|
||||||
if (uris.isNotEmpty()) {
|
|
||||||
selectedUris = uris
|
|
||||||
showDialog = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
val openDialog: (NoteEntity?) -> Unit = { note ->
|
|
||||||
Log.d("EditNote", "NoteEntity: ${note?.title}")
|
|
||||||
noteToEdit = note
|
|
||||||
showDialog = true
|
|
||||||
}
|
|
||||||
|
|
||||||
val navItems = listOf(
|
|
||||||
"Home" to "main",
|
|
||||||
"Notes" to "notes",
|
|
||||||
"Einstellungen" to "settings"
|
|
||||||
)
|
|
||||||
|
|
||||||
ModalNavigationDrawer(
|
|
||||||
drawerState = drawerState,
|
|
||||||
drawerContent = {
|
|
||||||
ModalDrawerSheet {
|
|
||||||
Text("Navigation", modifier = Modifier.padding(16.dp), style = MaterialTheme.typography.titleMedium)
|
|
||||||
navItems.forEach { (label, route) ->
|
|
||||||
NavigationDrawerItem(
|
|
||||||
label = { Text(label) },
|
|
||||||
selected = false,
|
|
||||||
onClick = {
|
|
||||||
navController.navigate(route) {
|
|
||||||
popUpTo(navController.graph.startDestinationId) { saveState = true }
|
|
||||||
launchSingleTop = true
|
|
||||||
restoreState = true
|
|
||||||
}
|
|
||||||
scope.launch { drawerState.close() }
|
|
||||||
},
|
|
||||||
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Scaffold(
|
|
||||||
topBar = {
|
|
||||||
var searchQuery by remember { mutableStateOf("") }
|
|
||||||
var isMenuExpanded by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
|
||||||
val currentRoute = navBackStackEntry?.destination?.route
|
|
||||||
|
|
||||||
TopAppBar(
|
|
||||||
title = {
|
|
||||||
if(currentRoute == "main") {
|
|
||||||
TextField(
|
|
||||||
value = searchQuery,
|
|
||||||
onValueChange = {
|
|
||||||
searchQuery = it
|
|
||||||
viewModel.searchQuery.value = it
|
|
||||||
},
|
|
||||||
placeholder = { Text("Suche...") },
|
|
||||||
singleLine = true,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(end = 48.dp), // Platz für Avatar
|
|
||||||
textStyle = MaterialTheme.typography.bodyLarge,
|
|
||||||
colors = TextFieldDefaults.textFieldColors(
|
|
||||||
containerColor = Color.Transparent,
|
|
||||||
unfocusedIndicatorColor = Color.Transparent,
|
|
||||||
focusedIndicatorColor = Color.Transparent
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Text("NoteVault")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = { scope.launch { drawerState.open() } }) {
|
|
||||||
Icon(Icons.Default.Menu, contentDescription = "Menü öffnen")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions = {
|
|
||||||
Box {
|
|
||||||
IconButton(onClick = { isMenuExpanded = true }) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.AccountCircle, // Avatar-Icon
|
|
||||||
contentDescription = "Benutzerprofil"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
DropdownMenu(
|
|
||||||
expanded = isMenuExpanded,
|
|
||||||
onDismissRequest = { isMenuExpanded = false }
|
|
||||||
) {
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text("Profil") },
|
|
||||||
onClick = {
|
|
||||||
isMenuExpanded = false
|
|
||||||
// TODO: Navigiere ggf. zu Profilscreen
|
|
||||||
}
|
|
||||||
)
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text("Abmelden") },
|
|
||||||
onClick = {
|
|
||||||
isMenuExpanded = false
|
|
||||||
// TODO: Logout-Logik
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { innerPadding ->
|
|
||||||
NavHost(
|
|
||||||
navController = navController,
|
|
||||||
startDestination = "main",
|
|
||||||
modifier = Modifier.padding(innerPadding)
|
|
||||||
) {
|
|
||||||
composable("main") {
|
|
||||||
MainScreen(
|
|
||||||
viewModel = viewModel,
|
|
||||||
onAddNoteClicked = {
|
|
||||||
imagePickerLauncher.launch(arrayOf("image/*"))
|
|
||||||
},
|
|
||||||
onEditNote = openDialog
|
|
||||||
)
|
|
||||||
}
|
|
||||||
composable("settings") {
|
|
||||||
SettingsScreen()
|
|
||||||
}
|
|
||||||
composable("notes") {
|
|
||||||
NotesScreen()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showDialog) {
|
|
||||||
val context = LocalContext.current
|
|
||||||
AddNoteDialog(
|
|
||||||
onDismiss = { showDialog = false },
|
|
||||||
onSave = { title, composer, year, genre, description ->
|
|
||||||
if (noteToEdit == null) {
|
|
||||||
viewModel.addNote(
|
|
||||||
context = context,
|
|
||||||
title = title,
|
|
||||||
composer = composer,
|
|
||||||
year = year,
|
|
||||||
genre = genre,
|
|
||||||
description = description,
|
|
||||||
selectedUris = selectedUris,
|
|
||||||
onDone = { showDialog = false }
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
viewModel.updateNote(
|
|
||||||
editedNote = noteToEdit!!,
|
|
||||||
updatedTitle = title,
|
|
||||||
updatedComposer = composer,
|
|
||||||
updatedYear = year,
|
|
||||||
updatedGenre = genre,
|
|
||||||
updatedDescription = description,
|
|
||||||
onDone = { showDialog = false }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initialTitle = noteToEdit?.title ?: "",
|
|
||||||
initialComposer = noteToEdit?.composer,
|
|
||||||
initialYear = noteToEdit?.year,
|
|
||||||
initialGenre = noteToEdit?.genre,
|
|
||||||
initialDescription = noteToEdit?.description
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package come.stormborntales.notevault.data.local
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.room.Database
|
|
||||||
import androidx.room.Room
|
|
||||||
import androidx.room.RoomDatabase
|
|
||||||
import androidx.room.TypeConverters
|
|
||||||
import come.stormborntales.notevault.data.local.dao.NoteDao
|
|
||||||
import come.stormborntales.notevault.data.local.entity.NoteCollection
|
|
||||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
|
||||||
|
|
||||||
@Database(entities = [NoteEntity::class, NoteCollection::class], version = 1)
|
|
||||||
@TypeConverters(UriListConverter::class)
|
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
|
||||||
abstract fun noteDao(): NoteDao
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Volatile
|
|
||||||
private var INSTANCE: AppDatabase? = null
|
|
||||||
|
|
||||||
fun getDatabase(context: Context): AppDatabase {
|
|
||||||
return INSTANCE ?: synchronized(this) {
|
|
||||||
val instance = Room.databaseBuilder(
|
|
||||||
context.applicationContext,
|
|
||||||
AppDatabase::class.java,
|
|
||||||
"note_database"
|
|
||||||
).build()
|
|
||||||
INSTANCE = instance
|
|
||||||
Log.d("AppDatabase", "Datenbank erstellt: ${instance.openHelper.writableDatabase}")
|
|
||||||
instance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package come.stormborntales.notevault.data.local
|
|
||||||
|
|
||||||
import androidx.room.TypeConverter
|
|
||||||
|
|
||||||
class UriListConverter {
|
|
||||||
@TypeConverter
|
|
||||||
fun fromList(list: List<String>): String = list.joinToString(",")
|
|
||||||
|
|
||||||
@TypeConverter
|
|
||||||
fun toList(data: String): List<String> = if (data.isBlank()) emptyList() else data.split(",")
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package come.stormborntales.notevault.data.local.dao
|
|
||||||
|
|
||||||
import androidx.room.Dao
|
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.OnConflictStrategy
|
|
||||||
import androidx.room.Query
|
|
||||||
import androidx.room.Update
|
|
||||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
interface NoteDao {
|
|
||||||
@Query("SELECT * FROM notes")
|
|
||||||
fun getAll(): Flow<List<NoteEntity>>
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
suspend fun insert(note: NoteEntity)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
suspend fun delete(note: NoteEntity)
|
|
||||||
|
|
||||||
@Update
|
|
||||||
suspend fun update(note: NoteEntity)
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package come.stormborntales.notevault.data.local.entity
|
|
||||||
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
|
|
||||||
@Entity("note_collections")
|
|
||||||
data class NoteCollection(
|
|
||||||
@PrimaryKey(autoGenerate = true) var id: Int = 0,
|
|
||||||
var name: String,
|
|
||||||
var parentId: Int? = null
|
|
||||||
)
|
|
@ -1,24 +0,0 @@
|
|||||||
package come.stormborntales.notevault.data.local.entity
|
|
||||||
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.ForeignKey
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
|
|
||||||
@Entity(tableName = "notes",
|
|
||||||
foreignKeys = [ForeignKey(
|
|
||||||
entity = NoteCollection::class,
|
|
||||||
parentColumns = ["id"],
|
|
||||||
childColumns = ["collectionId"],
|
|
||||||
onDelete = ForeignKey.CASCADE
|
|
||||||
)])
|
|
||||||
data class NoteEntity(
|
|
||||||
@PrimaryKey(autoGenerate = true) val id: Int = 0,
|
|
||||||
var title: String,
|
|
||||||
val images: List<String>, // oder String + TypeConverter
|
|
||||||
var composer: String?,
|
|
||||||
var year: Int?,
|
|
||||||
var genre: String?,
|
|
||||||
var description: String?,
|
|
||||||
val imagePreview: String,
|
|
||||||
val collectionId: Int?
|
|
||||||
)
|
|
@ -1,10 +0,0 @@
|
|||||||
package come.stormborntales.notevault.data.model
|
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
|
|
||||||
class NoteEntry(
|
|
||||||
val title: String, val images: List<Uri>, val composer: String?, val year: Int?,
|
|
||||||
val genre: String?, val description: String?
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package come.stormborntales.notevault.data.repository
|
|
||||||
|
|
||||||
import come.stormborntales.notevault.data.local.dao.NoteDao
|
|
||||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
|
|
||||||
class NoteRepository(private val dao: NoteDao) {
|
|
||||||
val allNotes: Flow<List<NoteEntity>> = dao.getAll()
|
|
||||||
|
|
||||||
suspend fun insert(note: NoteEntity) = dao.insert(note)
|
|
||||||
suspend fun delete(note: NoteEntity) = dao.delete(note)
|
|
||||||
|
|
||||||
suspend fun update(note: NoteEntity) = dao.update(note);
|
|
||||||
}
|
|
@ -1,126 +0,0 @@
|
|||||||
package come.stormborntales.notevault.ui.screens
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.*
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun AddNoteDialog(
|
|
||||||
onDismiss: () -> Unit,
|
|
||||||
onSave: (title: String, composer: String?, year: Int?, genre: String?, description: String?) -> Unit,
|
|
||||||
initialTitle: String = "",
|
|
||||||
initialComposer: String? = null,
|
|
||||||
initialYear: Int? = null,
|
|
||||||
initialGenre: String? = null,
|
|
||||||
initialDescription: String? = null
|
|
||||||
) {
|
|
||||||
var title by remember { mutableStateOf(initialTitle) }
|
|
||||||
var composer by remember { mutableStateOf(initialComposer ?: "") }
|
|
||||||
var yearText by remember { mutableStateOf(initialYear?.toString() ?: "") }
|
|
||||||
var genre by remember { mutableStateOf(initialGenre ?: "") }
|
|
||||||
var description by remember { mutableStateOf(initialDescription ?: "") }
|
|
||||||
var showTitleError by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
|
|
||||||
AlertDialog(
|
|
||||||
onDismissRequest = onDismiss,
|
|
||||||
confirmButton = {
|
|
||||||
TextButton(onClick = {
|
|
||||||
if (title.isBlank()) {
|
|
||||||
showTitleError = true
|
|
||||||
} else {
|
|
||||||
val year = yearText.toIntOrNull()
|
|
||||||
onSave(
|
|
||||||
title.trim(),
|
|
||||||
composer.takeIf { it.isNotBlank() },
|
|
||||||
year,
|
|
||||||
genre.takeIf { it.isNotBlank() },
|
|
||||||
description.takeIf { it.isNotBlank() }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Text("Speichern")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dismissButton = {
|
|
||||||
TextButton(onClick = onDismiss) {
|
|
||||||
Text("Abbrechen")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title = {
|
|
||||||
Text("Notenblatt hinzufügen", style = MaterialTheme.typography.titleLarge)
|
|
||||||
},
|
|
||||||
text = {
|
|
||||||
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
|
|
||||||
OutlinedTextField(
|
|
||||||
value = title,
|
|
||||||
onValueChange = {
|
|
||||||
title = it
|
|
||||||
if (it.isNotBlank()) showTitleError = false
|
|
||||||
},
|
|
||||||
label = { Text("Titel*") },
|
|
||||||
isError = showTitleError,
|
|
||||||
singleLine = true,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(vertical = 4.dp)
|
|
||||||
)
|
|
||||||
if (showTitleError) {
|
|
||||||
Text(
|
|
||||||
"Titel darf nicht leer sein",
|
|
||||||
color = MaterialTheme.colorScheme.error,
|
|
||||||
style = MaterialTheme.typography.bodySmall,
|
|
||||||
modifier = Modifier.padding(start = 16.dp, bottom = 4.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
OutlinedTextField(
|
|
||||||
value = composer,
|
|
||||||
onValueChange = { composer = it },
|
|
||||||
label = { Text("Komponist (optional)") },
|
|
||||||
singleLine = true,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(vertical = 4.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
OutlinedTextField(
|
|
||||||
value = yearText,
|
|
||||||
onValueChange = { yearText = it.filter { c -> c.isDigit() } },
|
|
||||||
label = { Text("Erscheinungsjahr (optional)") },
|
|
||||||
singleLine = true,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(vertical = 4.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
OutlinedTextField(
|
|
||||||
value = genre,
|
|
||||||
onValueChange = { genre = it },
|
|
||||||
label = { Text("Genre (optional)") },
|
|
||||||
singleLine = true,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(vertical = 4.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
OutlinedTextField(
|
|
||||||
value = description,
|
|
||||||
onValueChange = { description = it },
|
|
||||||
label = { Text("Beschreibung (optional)") },
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(vertical = 4.dp),
|
|
||||||
maxLines = 4
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
package come.stormborntales.notevault.ui.screens
|
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.*
|
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
|
||||||
import androidx.compose.material3.*
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import android.net.Uri
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
||||||
import androidx.compose.material.icons.filled.Close
|
|
||||||
import androidx.compose.ui.layout.ContentScale
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
|
||||||
fun FullscreenImageViewer(
|
|
||||||
images: List<Uri>,
|
|
||||||
onClose: () -> Unit
|
|
||||||
) {
|
|
||||||
val pagerState = rememberPagerState(pageCount = { images.size })
|
|
||||||
|
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
|
||||||
HorizontalPager(state = pagerState) { page ->
|
|
||||||
val context = LocalContext.current
|
|
||||||
val imageBitmap = remember(images[page]) {
|
|
||||||
loadImageBitmap(context, images[page].toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
imageBitmap?.let {
|
|
||||||
Image(
|
|
||||||
bitmap = it,
|
|
||||||
contentDescription = "Notenbild",
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.background(Color.Black),
|
|
||||||
contentScale = ContentScale.Fit
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IconButton(
|
|
||||||
onClick = onClose,
|
|
||||||
modifier = Modifier
|
|
||||||
.align(Alignment.TopStart)
|
|
||||||
.padding(16.dp)
|
|
||||||
) {
|
|
||||||
Icon(Icons.Default.Close, contentDescription = "Schließen", tint = Color.White)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,269 +0,0 @@
|
|||||||
package come.stormborntales.notevault.ui.screens
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.graphics.ImageDecoder
|
|
||||||
import android.media.Image
|
|
||||||
import android.net.Uri
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.horizontalScroll
|
|
||||||
import androidx.compose.foundation.layout.*
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.Add
|
|
||||||
import androidx.compose.material3.*
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.graphics.ImageBitmap
|
|
||||||
import androidx.compose.ui.graphics.asImageBitmap
|
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import come.stormborntales.notevault.FullscreenImageViewerActivity
|
|
||||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
|
||||||
import come.stormborntales.notevault.data.model.NoteEntry
|
|
||||||
import come.stormborntales.notevault.ui.viewmodel.NoteViewModel
|
|
||||||
import java.io.InputStream
|
|
||||||
import androidx.core.net.toUri
|
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
|
||||||
import coil.compose.AsyncImage
|
|
||||||
|
|
||||||
fun loadImageBitmap(context: Context, uriString: String): ImageBitmap? {
|
|
||||||
return try {
|
|
||||||
val uri = uriString.toUri()
|
|
||||||
val inputStream: InputStream? = context.contentResolver.openInputStream(uri)
|
|
||||||
val bitmap = BitmapFactory.decodeStream(inputStream)
|
|
||||||
bitmap?.asImageBitmap()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}@Composable
|
|
||||||
fun NoteCard(note: NoteEntity, onDeleteNote: (NoteEntity) -> Unit, onEditNote: (NoteEntity) -> Unit) {
|
|
||||||
val context = LocalContext.current
|
|
||||||
|
|
||||||
val screenWidth = LocalConfiguration.current.screenWidthDp // Bildschirmbreite in dp
|
|
||||||
|
|
||||||
// Dynamische Bildgröße basierend auf der Bildschirmbreite
|
|
||||||
val imageSize = if (screenWidth < 400) 80.dp else 120.dp
|
|
||||||
|
|
||||||
Card(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(vertical = 8.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
|
|
||||||
) {
|
|
||||||
// Responsive Layout: Überprüfen, ob der Bildschirm schmaler als 360 dp ist
|
|
||||||
if (screenWidth < 400) {
|
|
||||||
// Wenn der Bildschirm schmal ist, arrangiere die Elemente vertikal
|
|
||||||
Row(modifier = Modifier.padding(16.dp)) {
|
|
||||||
AsyncImage(
|
|
||||||
model = note.imagePreview,
|
|
||||||
contentDescription = "Vorschaubild",
|
|
||||||
modifier = Modifier
|
|
||||||
.size(imageSize)
|
|
||||||
.clip(RoundedCornerShape(12.dp))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
Column(modifier = Modifier.padding(16.dp)) {
|
|
||||||
Text(
|
|
||||||
text = note.title,
|
|
||||||
style = MaterialTheme.typography.titleMedium
|
|
||||||
)
|
|
||||||
|
|
||||||
note.composer?.let {
|
|
||||||
Text("von $it", style = MaterialTheme.typography.labelMedium)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
|
||||||
|
|
||||||
note.year?.let {
|
|
||||||
Text("Jahr: $it", style = MaterialTheme.typography.bodySmall)
|
|
||||||
}
|
|
||||||
|
|
||||||
note.genre?.let {
|
|
||||||
Text("Genre: $it", style = MaterialTheme.typography.bodySmall)
|
|
||||||
}
|
|
||||||
|
|
||||||
note.description?.let {
|
|
||||||
Text("Beschreibung: $it", style = MaterialTheme.typography.bodySmall, maxLines = 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp)) // Abstand zwischen Text und Buttons
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Buttons unter dem Text
|
|
||||||
Row(
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
|
||||||
modifier = Modifier.fillMaxWidth().padding(16.dp),
|
|
||||||
) {
|
|
||||||
OutlinedButton(
|
|
||||||
onClick = {
|
|
||||||
val uris = ArrayList<Uri>()
|
|
||||||
note.images.forEach { uris.add(it.toUri()) }
|
|
||||||
|
|
||||||
val intent = Intent(context, FullscreenImageViewerActivity::class.java).apply {
|
|
||||||
putParcelableArrayListExtra("imageUris", ArrayList(uris))
|
|
||||||
}
|
|
||||||
context.startActivity(intent)
|
|
||||||
},
|
|
||||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp)
|
|
||||||
) {
|
|
||||||
Text("Anzeigen", style = MaterialTheme.typography.labelLarge)
|
|
||||||
}
|
|
||||||
|
|
||||||
OutlinedButton(
|
|
||||||
onClick = {
|
|
||||||
onEditNote(note)
|
|
||||||
},
|
|
||||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp)
|
|
||||||
) {
|
|
||||||
Text("Bearbeiten", style = MaterialTheme.typography.labelLarge)
|
|
||||||
}
|
|
||||||
|
|
||||||
OutlinedButton(
|
|
||||||
onClick = {
|
|
||||||
onDeleteNote(note)
|
|
||||||
},
|
|
||||||
colors = ButtonDefaults.outlinedButtonColors(
|
|
||||||
contentColor = MaterialTheme.colorScheme.error
|
|
||||||
),
|
|
||||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp)
|
|
||||||
) {
|
|
||||||
Text("Löschen", style = MaterialTheme.typography.labelLarge)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Wenn der Bildschirm breiter als 360 dp ist, arrangiere die Elemente nebeneinander
|
|
||||||
Row(modifier = Modifier.padding(16.dp)) {
|
|
||||||
// Linkes Vorschaubild
|
|
||||||
AsyncImage(
|
|
||||||
model = note.imagePreview,
|
|
||||||
contentDescription = "Vorschaubild",
|
|
||||||
modifier = Modifier
|
|
||||||
.size(imageSize)
|
|
||||||
.clip(RoundedCornerShape(12.dp))
|
|
||||||
)
|
|
||||||
|
|
||||||
// Rechte Info-Spalte
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.weight(1f) // Damit die Spalte den verfügbaren Platz nutzt
|
|
||||||
.align(Alignment.CenterVertically)
|
|
||||||
.padding(start = 16.dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = note.title,
|
|
||||||
style = MaterialTheme.typography.titleMedium
|
|
||||||
)
|
|
||||||
|
|
||||||
note.composer?.let {
|
|
||||||
Text("von $it", style = MaterialTheme.typography.labelMedium)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
|
||||||
|
|
||||||
note.year?.let {
|
|
||||||
Text("Jahr: $it", style = MaterialTheme.typography.bodySmall)
|
|
||||||
}
|
|
||||||
|
|
||||||
note.genre?.let {
|
|
||||||
Text("Genre: $it", style = MaterialTheme.typography.bodySmall)
|
|
||||||
}
|
|
||||||
|
|
||||||
note.description?.let {
|
|
||||||
Text("Beschreibung: $it", style = MaterialTheme.typography.bodySmall, maxLines = 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
|
|
||||||
// Buttons in einer Row anordnen
|
|
||||||
Row(
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
|
||||||
modifier = Modifier.fillMaxWidth() // Stellt sicher, dass die Row den gesamten verfügbaren Platz einnimmt
|
|
||||||
) {
|
|
||||||
OutlinedButton(
|
|
||||||
onClick = {
|
|
||||||
val uris = ArrayList<Uri>()
|
|
||||||
note.images.forEach { uris.add(it.toUri()) }
|
|
||||||
|
|
||||||
val intent = Intent(context, FullscreenImageViewerActivity::class.java).apply {
|
|
||||||
putParcelableArrayListExtra("imageUris", ArrayList(uris))
|
|
||||||
}
|
|
||||||
context.startActivity(intent)
|
|
||||||
},
|
|
||||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp)
|
|
||||||
) {
|
|
||||||
Text("Anzeigen", style = MaterialTheme.typography.labelLarge)
|
|
||||||
}
|
|
||||||
|
|
||||||
OutlinedButton(
|
|
||||||
onClick = {
|
|
||||||
onEditNote(note)
|
|
||||||
},
|
|
||||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp)
|
|
||||||
) {
|
|
||||||
Text("Bearbeiten", style = MaterialTheme.typography.labelLarge)
|
|
||||||
}
|
|
||||||
|
|
||||||
OutlinedButton(
|
|
||||||
onClick = {
|
|
||||||
onDeleteNote(note)
|
|
||||||
},
|
|
||||||
colors = ButtonDefaults.outlinedButtonColors(
|
|
||||||
contentColor = MaterialTheme.colorScheme.error
|
|
||||||
),
|
|
||||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp)
|
|
||||||
) {
|
|
||||||
Text("Löschen", style = MaterialTheme.typography.labelLarge)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun MainScreen(
|
|
||||||
onAddNoteClicked: () -> Unit, // Übergib hier deine Logik für den Import
|
|
||||||
viewModel: NoteViewModel,
|
|
||||||
onEditNote: (NoteEntity) -> Unit
|
|
||||||
) {
|
|
||||||
val notes by viewModel.filteredNotes.collectAsState(initial = emptyList())
|
|
||||||
Scaffold(
|
|
||||||
floatingActionButton = {
|
|
||||||
FloatingActionButton(
|
|
||||||
onClick = onAddNoteClicked
|
|
||||||
) {
|
|
||||||
Icon(Icons.Default.Add, contentDescription = "Neue Noten hinzufügen")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
floatingActionButtonPosition = FabPosition.End
|
|
||||||
) { innerPadding ->
|
|
||||||
LazyColumn(
|
|
||||||
contentPadding = innerPadding,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(16.dp)
|
|
||||||
) {
|
|
||||||
items(notes) { note ->
|
|
||||||
NoteCard(note = note, onDeleteNote = { noteEntity ->
|
|
||||||
viewModel.deleteNote(noteEntity)
|
|
||||||
}, onEditNote = onEditNote)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package come.stormborntales.notevault.ui.screens
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material3.Divider
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.OutlinedButton
|
|
||||||
import androidx.compose.material3.Switch
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun NotesScreen() {
|
|
||||||
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
package come.stormborntales.notevault.ui.screens
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material3.Divider
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.OutlinedButton
|
|
||||||
import androidx.compose.material3.Switch
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SettingsScreen() {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(16.dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = "Einstellungen",
|
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
|
||||||
modifier = Modifier.padding(bottom = 16.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
Divider()
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
|
|
||||||
// Beispielhafte Einstellung
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = "Dark Mode",
|
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
style = MaterialTheme.typography.bodyLarge
|
|
||||||
)
|
|
||||||
Switch(
|
|
||||||
checked = false,
|
|
||||||
onCheckedChange = { /* TODO: Dark Mode aktivieren */ }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = "Benachrichtigungen",
|
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
style = MaterialTheme.typography.bodyLarge
|
|
||||||
)
|
|
||||||
Switch(
|
|
||||||
checked = true,
|
|
||||||
onCheckedChange = { /* TODO: Benachrichtigungseinstellungen */ }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(32.dp))
|
|
||||||
|
|
||||||
OutlinedButton(
|
|
||||||
onClick = { /* TODO: Impressum anzeigen */ },
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
) {
|
|
||||||
Text("Impressum")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package come.stormborntales.notevault.ui.theme
|
|
||||||
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
|
|
||||||
val Purple80 = Color(0xFFD0BCFF)
|
|
||||||
val PurpleGrey80 = Color(0xFFCCC2DC)
|
|
||||||
val Pink80 = Color(0xFFEFB8C8)
|
|
||||||
|
|
||||||
val Purple40 = Color(0xFF6650a4)
|
|
||||||
val PurpleGrey40 = Color(0xFF625b71)
|
|
||||||
val Pink40 = Color(0xFF7D5260)
|
|
@ -1,58 +0,0 @@
|
|||||||
package come.stormborntales.notevault.ui.theme
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.os.Build
|
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.darkColorScheme
|
|
||||||
import androidx.compose.material3.dynamicDarkColorScheme
|
|
||||||
import androidx.compose.material3.dynamicLightColorScheme
|
|
||||||
import androidx.compose.material3.lightColorScheme
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
|
|
||||||
private val DarkColorScheme = darkColorScheme(
|
|
||||||
primary = Purple80,
|
|
||||||
secondary = PurpleGrey80,
|
|
||||||
tertiary = Pink80
|
|
||||||
)
|
|
||||||
|
|
||||||
private val LightColorScheme = lightColorScheme(
|
|
||||||
primary = Purple40,
|
|
||||||
secondary = PurpleGrey40,
|
|
||||||
tertiary = Pink40
|
|
||||||
|
|
||||||
/* Other default colors to override
|
|
||||||
background = Color(0xFFFFFBFE),
|
|
||||||
surface = Color(0xFFFFFBFE),
|
|
||||||
onPrimary = Color.White,
|
|
||||||
onSecondary = Color.White,
|
|
||||||
onTertiary = Color.White,
|
|
||||||
onBackground = Color(0xFF1C1B1F),
|
|
||||||
onSurface = Color(0xFF1C1B1F),
|
|
||||||
*/
|
|
||||||
)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun NoteVaultTheme(
|
|
||||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
|
||||||
// Dynamic color is available on Android 12+
|
|
||||||
dynamicColor: Boolean = true,
|
|
||||||
content: @Composable () -> Unit
|
|
||||||
) {
|
|
||||||
val colorScheme = when {
|
|
||||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
|
||||||
val context = LocalContext.current
|
|
||||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
darkTheme -> DarkColorScheme
|
|
||||||
else -> LightColorScheme
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialTheme(
|
|
||||||
colorScheme = colorScheme,
|
|
||||||
typography = Typography,
|
|
||||||
content = content
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
package come.stormborntales.notevault.ui.theme
|
|
||||||
|
|
||||||
import androidx.compose.material3.Typography
|
|
||||||
import androidx.compose.ui.text.TextStyle
|
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
|
|
||||||
// Set of Material typography styles to start with
|
|
||||||
val Typography = Typography(
|
|
||||||
bodyLarge = TextStyle(
|
|
||||||
fontFamily = FontFamily.Default,
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
fontSize = 16.sp,
|
|
||||||
lineHeight = 24.sp,
|
|
||||||
letterSpacing = 0.5.sp
|
|
||||||
)
|
|
||||||
/* Other default text styles to override
|
|
||||||
titleLarge = TextStyle(
|
|
||||||
fontFamily = FontFamily.Default,
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
fontSize = 22.sp,
|
|
||||||
lineHeight = 28.sp,
|
|
||||||
letterSpacing = 0.sp
|
|
||||||
),
|
|
||||||
labelSmall = TextStyle(
|
|
||||||
fontFamily = FontFamily.Default,
|
|
||||||
fontWeight = FontWeight.Medium,
|
|
||||||
fontSize = 11.sp,
|
|
||||||
lineHeight = 16.sp,
|
|
||||||
letterSpacing = 0.5.sp
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
)
|
|
@ -1,134 +0,0 @@
|
|||||||
package come.stormborntales.notevault.ui.viewmodel
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.net.Uri
|
|
||||||
import android.util.Log
|
|
||||||
import android.webkit.MimeTypeMap
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.asLiveData
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
|
||||||
import come.stormborntales.notevault.data.repository.NoteRepository
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.io.File
|
|
||||||
import androidx.core.graphics.scale
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import kotlinx.coroutines.flow.combine
|
|
||||||
import kotlinx.coroutines.flow.stateIn
|
|
||||||
|
|
||||||
class NoteViewModel(
|
|
||||||
private val repository: NoteRepository,
|
|
||||||
) : ViewModel() {
|
|
||||||
// Sucheingabe als StateFlow
|
|
||||||
val searchQuery = MutableStateFlow("")
|
|
||||||
|
|
||||||
// Alle Notizen als Flow aus der Datenbank (NICHT blockierend!)
|
|
||||||
private val allNotes: Flow<List<NoteEntity>> = repository.allNotes
|
|
||||||
|
|
||||||
// Gefilterte Notizen basierend auf Sucheingabe
|
|
||||||
val filteredNotes: StateFlow<List<NoteEntity>> = combine(searchQuery, allNotes) { query, notes ->
|
|
||||||
if (query.isBlank()) {
|
|
||||||
notes
|
|
||||||
} else {
|
|
||||||
notes.filter {
|
|
||||||
it.title.contains(query, ignoreCase = true) ||
|
|
||||||
it.description?.contains(query, ignoreCase = true) == true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
|
|
||||||
|
|
||||||
|
|
||||||
fun createPreviewImage(context: Context, uri: Uri): File? {
|
|
||||||
return try {
|
|
||||||
val inputStream = context.contentResolver.openInputStream(uri)
|
|
||||||
val originalBitmap = BitmapFactory.decodeStream(inputStream) ?: return null
|
|
||||||
|
|
||||||
val previewBitmap = originalBitmap.scale(128, 128, false)
|
|
||||||
val previewFile = File(context.filesDir, "preview_${System.currentTimeMillis()}.jpg")
|
|
||||||
previewFile.outputStream().use { out ->
|
|
||||||
previewBitmap.compress(Bitmap.CompressFormat.JPEG, 75, out)
|
|
||||||
}
|
|
||||||
previewFile
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addNote(context: Context, title: String, composer: String?, year: Int?, genre: String?, description: String?, selectedUris: List<Uri>, onDone:() -> Unit) {
|
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
val copiedUris = selectedUris.mapNotNull { uri ->
|
|
||||||
try {
|
|
||||||
val inputStream = context.contentResolver.openInputStream(uri)
|
|
||||||
val extension = MimeTypeMap.getSingleton()
|
|
||||||
.getExtensionFromMimeType(context.contentResolver.getType(uri)) ?: "jpg"
|
|
||||||
|
|
||||||
val outputFile = File(context.filesDir, "note_${System.currentTimeMillis()}.$extension")
|
|
||||||
inputStream?.use { input ->
|
|
||||||
outputFile.outputStream().use { output ->
|
|
||||||
input.copyTo(output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log.d("NoteViewModel", "NoteEntityFile" + outputFile.absolutePath)
|
|
||||||
Uri.fromFile(outputFile).toString() // speichern als String
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copiedUris.isNotEmpty()) {
|
|
||||||
val preview_image_path = createPreviewImage(context, uri = selectedUris[0])
|
|
||||||
|
|
||||||
val note = NoteEntity(
|
|
||||||
title = title,
|
|
||||||
images = copiedUris, // muss als List<String> gespeichert sein
|
|
||||||
composer = composer,
|
|
||||||
year = year,
|
|
||||||
genre = genre,
|
|
||||||
description = description,
|
|
||||||
imagePreview = preview_image_path.toString(),
|
|
||||||
collectionId = null
|
|
||||||
)
|
|
||||||
|
|
||||||
repository.insert(note)
|
|
||||||
}
|
|
||||||
|
|
||||||
onDone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteNote(note: NoteEntity) {
|
|
||||||
viewModelScope.launch {
|
|
||||||
repository.delete(note)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateNote(
|
|
||||||
editedNote: NoteEntity,
|
|
||||||
updatedTitle: String,
|
|
||||||
updatedComposer: String?,
|
|
||||||
updatedYear: Int?,
|
|
||||||
updatedGenre: String?,
|
|
||||||
updatedDescription: String?,
|
|
||||||
onDone: () -> Unit
|
|
||||||
) {
|
|
||||||
viewModelScope.launch {
|
|
||||||
editedNote.title = updatedTitle
|
|
||||||
editedNote.year = updatedYear;
|
|
||||||
editedNote.composer = updatedComposer
|
|
||||||
editedNote.genre = updatedGenre
|
|
||||||
editedNote.description = updatedDescription
|
|
||||||
|
|
||||||
repository.update(editedNote)
|
|
||||||
|
|
||||||
onDone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package come.stormborntales.notevault.ui.viewmodel
|
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import come.stormborntales.notevault.data.repository.NoteRepository
|
|
||||||
|
|
||||||
class NoteViewModelFactory(
|
|
||||||
private val repository: NoteRepository
|
|
||||||
) : ViewModelProvider.Factory {
|
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
if (modelClass.isAssignableFrom(NoteViewModel::class.java)) {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return NoteViewModel(repository) as T
|
|
||||||
}
|
|
||||||
throw IllegalArgumentException("Unknown ViewModel class")
|
|
||||||
}
|
|
||||||
}
|
|
72
app/src/main/java/core/notevault/MainActivity.java
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package core.notevault;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.Menu;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
import com.google.android.material.navigation.NavigationView;
|
||||||
|
import androidx.navigation.NavController;
|
||||||
|
import androidx.navigation.Navigation;
|
||||||
|
import androidx.navigation.ui.AppBarConfiguration;
|
||||||
|
import androidx.navigation.ui.NavigationUI;
|
||||||
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import core.notevault.data.MusicDatabase;
|
||||||
|
import core.notevault.data.MusicNote;
|
||||||
|
import core.notevault.databinding.ActivityMainBinding;
|
||||||
|
import core.notevault.ui.metadatadialog.MetaDataDialog;
|
||||||
|
|
||||||
|
public class MainActivity extends AppCompatActivity implements MetaDataDialog.OnMetadataListener {
|
||||||
|
|
||||||
|
private AppBarConfiguration mAppBarConfiguration;
|
||||||
|
private ActivityMainBinding binding;
|
||||||
|
|
||||||
|
private MusicDatabase musicDB;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||||
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
|
setSupportActionBar(binding.appBarMain.toolbar);
|
||||||
|
DrawerLayout drawer = binding.drawerLayout;
|
||||||
|
NavigationView navigationView = binding.navView;
|
||||||
|
// Passing each menu ID as a set of Ids because each
|
||||||
|
// menu should be considered as top level destinations.
|
||||||
|
mAppBarConfiguration = new AppBarConfiguration.Builder(
|
||||||
|
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
|
||||||
|
.setOpenableLayout(drawer)
|
||||||
|
.build();
|
||||||
|
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
|
||||||
|
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
|
||||||
|
NavigationUI.setupWithNavController(navigationView, navController);
|
||||||
|
|
||||||
|
musicDB = MusicDatabase.getDatabase(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
|
getMenuInflater().inflate(R.menu.main, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onSupportNavigateUp() {
|
||||||
|
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
|
||||||
|
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|
||||||
|
|| super.onSupportNavigateUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMetadataEntered(String title, String composer, int year, String genre) {
|
||||||
|
MusicNote musicNote = new MusicNote(title, null, composer, year, genre);
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
musicDB.musicNoteDao().insert(musicNote);
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
}
|
26
app/src/main/java/core/notevault/data/MusicDatabase.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package core.notevault.data;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import androidx.room.Room;
|
||||||
|
import androidx.room.RoomDatabase;
|
||||||
|
import androidx.room.Database;
|
||||||
|
|
||||||
|
@Database(entities = {MusicNote.class}, version = 1, exportSchema = false)
|
||||||
|
public abstract class MusicDatabase extends RoomDatabase {
|
||||||
|
public abstract MusicNoteDAO musicNoteDao();
|
||||||
|
|
||||||
|
private static MusicDatabase INSTANCE;
|
||||||
|
|
||||||
|
public static MusicDatabase getDatabase(final Context context) {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
synchronized (MusicDatabase.class) {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
|
||||||
|
MusicDatabase.class, "music_database")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
75
app/src/main/java/core/notevault/data/MusicNote.java
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package core.notevault.data;
|
||||||
|
|
||||||
|
import androidx.room.Entity;
|
||||||
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
@Entity(tableName = "music_notes")
|
||||||
|
public class MusicNote {
|
||||||
|
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
private int id;
|
||||||
|
private String title;
|
||||||
|
private String filePath;
|
||||||
|
private String composer;
|
||||||
|
private int year;
|
||||||
|
private String genre;
|
||||||
|
|
||||||
|
public MusicNote(String title, String filePath, String composer, int year, String genre) {
|
||||||
|
this.title = title;
|
||||||
|
this.filePath = filePath;
|
||||||
|
this.composer = composer;
|
||||||
|
this.year = year;
|
||||||
|
this.genre = genre;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MusicNote() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilePath() {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilePath(String filePath) {
|
||||||
|
this.filePath = filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getComposer() {
|
||||||
|
return composer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComposer(String composer) {
|
||||||
|
this.composer = composer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGenre() {
|
||||||
|
return genre;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGenre(String genre) {
|
||||||
|
this.genre = genre;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getYear() {
|
||||||
|
return year;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYear(int year) {
|
||||||
|
this.year = year;
|
||||||
|
}
|
||||||
|
}
|
17
app/src/main/java/core/notevault/data/MusicNoteDAO.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package core.notevault.data;
|
||||||
|
|
||||||
|
import androidx.room.Dao;
|
||||||
|
import androidx.room.Insert;
|
||||||
|
import androidx.room.Query;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
public interface MusicNoteDAO {
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
void insert(MusicNote musicNote);
|
||||||
|
|
||||||
|
@Query("SELECT * FROM music_notes")
|
||||||
|
List<MusicNote> getAllNotes();
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package core.notevault.ui.gallery;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import core.notevault.databinding.FragmentGalleryBinding;
|
||||||
|
|
||||||
|
public class GalleryFragment extends Fragment {
|
||||||
|
|
||||||
|
private FragmentGalleryBinding binding;
|
||||||
|
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
|
ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
GalleryViewModel galleryViewModel =
|
||||||
|
new ViewModelProvider(this).get(GalleryViewModel.class);
|
||||||
|
|
||||||
|
binding = FragmentGalleryBinding.inflate(inflater, container, false);
|
||||||
|
View root = binding.getRoot();
|
||||||
|
|
||||||
|
final TextView textView = binding.textGallery;
|
||||||
|
galleryViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package core.notevault.ui.gallery;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
|
public class GalleryViewModel extends ViewModel {
|
||||||
|
|
||||||
|
private final MutableLiveData<String> mText;
|
||||||
|
|
||||||
|
public GalleryViewModel() {
|
||||||
|
mText = new MutableLiveData<>();
|
||||||
|
mText.setValue("This is gallery fragment");
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<String> getText() {
|
||||||
|
return mText;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package core.notevault.ui.home;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import core.notevault.R;
|
||||||
|
|
||||||
|
public class FullScreenImageActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_full_screen_image); // Erstelle eine Layout-Datei
|
||||||
|
|
||||||
|
ImageView imageView = findViewById(R.id.fullscreen_image_view); // Angenommen, du hast ein ImageView
|
||||||
|
|
||||||
|
// Die URI aus dem Intent erhalten
|
||||||
|
Intent intent = getIntent();
|
||||||
|
String imageUriString = intent.getStringExtra("imageUri");
|
||||||
|
if (imageUriString != null) {
|
||||||
|
Uri imageUri = Uri.parse(imageUriString);
|
||||||
|
imageView.setImageURI(imageUri); // Setze die URI in das ImageView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
113
app/src/main/java/core/notevault/ui/home/HomeFragment.java
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package core.notevault.ui.home;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.OpenableColumns;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
|
import core.notevault.R;
|
||||||
|
import core.notevault.data.MusicDatabase;
|
||||||
|
import core.notevault.data.MusicNote;
|
||||||
|
import core.notevault.data.MusicNoteDAO;
|
||||||
|
import core.notevault.databinding.FragmentHomeBinding;
|
||||||
|
import core.notevault.ui.metadatadialog.MetaDataDialog;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class HomeFragment extends Fragment {
|
||||||
|
|
||||||
|
private NoteSongAdapter noteSongAdapter;
|
||||||
|
|
||||||
|
private static final int PICK_FILE_REQUEST_CODE = 1;
|
||||||
|
private FragmentHomeBinding binding;
|
||||||
|
private HomeViewModel homeViewModel;
|
||||||
|
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
|
ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
homeViewModel =
|
||||||
|
new ViewModelProvider(this).get(HomeViewModel.class);
|
||||||
|
|
||||||
|
binding = FragmentHomeBinding.inflate(inflater, container, false);
|
||||||
|
View root = binding.getRoot();
|
||||||
|
|
||||||
|
FloatingActionButton importBtn = root.findViewById(R.id.importMusicNotesBtn);
|
||||||
|
importBtn.setOnClickListener(v -> openFileChooser());
|
||||||
|
|
||||||
|
RecyclerView recyclerView = root.findViewById(R.id.note_recycler_view);
|
||||||
|
noteSongAdapter = new NoteSongAdapter();
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
|
||||||
|
new LoadSongTitlesTask().execute();
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LoadSongTitlesTask extends AsyncTask<Void, Void, List<MusicNote>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<MusicNote> doInBackground(Void... voids) {
|
||||||
|
MusicDatabase db = MusicDatabase.getDatabase(getContext());
|
||||||
|
MusicNoteDAO musicNoteDAO = db.musicNoteDao();
|
||||||
|
return musicNoteDAO.getAllNotes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(List<MusicNote> songTitles) {
|
||||||
|
noteSongAdapter.updateSongTitles(songTitles); // Aktualisiere den Adapter mit den Titeln
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if (requestCode == PICK_FILE_REQUEST_CODE && resultCode == getActivity().RESULT_OK && data != null) {
|
||||||
|
Uri uri = data.getData();
|
||||||
|
if (uri != null) {
|
||||||
|
handleFile(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleFile(Uri uri) {
|
||||||
|
// Hier kannst du die Logik zum Speichern oder Anzeigen der Datei implementieren
|
||||||
|
MetaDataDialog metaDataDialog = new MetaDataDialog();
|
||||||
|
metaDataDialog.setFileUri(uri);
|
||||||
|
metaDataDialog.show(getParentFragmentManager(), MetaDataDialog.TAG);
|
||||||
|
|
||||||
|
homeViewModel.addNote(uri); // Speichere die URI im ViewModel
|
||||||
|
Toast.makeText(getActivity(), "Datei ausgewählt: " + uri.getPath(), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openFileChooser() {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
|
intent.setType("*/*"); // Alle Dateitypen
|
||||||
|
|
||||||
|
String[] mimeTypes = {"application/pdf", "image/png", "image/jpeg"};
|
||||||
|
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
|
||||||
|
|
||||||
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
|
startActivityForResult(intent, PICK_FILE_REQUEST_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
33
app/src/main/java/core/notevault/ui/home/HomeViewModel.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package core.notevault.ui.home;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
|
import core.notevault.MainActivity;
|
||||||
|
import core.notevault.data.MusicDatabase;
|
||||||
|
import core.notevault.ui.metadatadialog.MetaDataDialog;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class HomeViewModel extends ViewModel {
|
||||||
|
|
||||||
|
private final MutableLiveData<List<String>> noteTitles;
|
||||||
|
|
||||||
|
public HomeViewModel() {
|
||||||
|
noteTitles = new MutableLiveData<>(new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<List<String>> getNoteTitles() {
|
||||||
|
return noteTitles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNoteTitles(ArrayList<String> noteTitles) {
|
||||||
|
this.noteTitles.setValue(noteTitles);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNote(Uri uri) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package core.notevault.ui.home;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import core.notevault.R;
|
||||||
|
import core.notevault.data.MusicNote;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NoteSongAdapter extends RecyclerView.Adapter<NoteSongAdapter.NoteViewHolder> {
|
||||||
|
|
||||||
|
private List<MusicNote> noteTitles;
|
||||||
|
|
||||||
|
public NoteSongAdapter(List<MusicNote> noteTitles) {
|
||||||
|
this.noteTitles = noteTitles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoteSongAdapter() {
|
||||||
|
this.noteTitles = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public NoteViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.item_song, parent, false);
|
||||||
|
return new NoteViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull NoteViewHolder holder, int position) {
|
||||||
|
holder.titleTextView.setText(noteTitles.get(position).getTitle());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return noteTitles.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateSongTitles(List<MusicNote> songTitles) {
|
||||||
|
this.noteTitles.clear();
|
||||||
|
this.noteTitles.addAll(songTitles);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NoteViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView titleTextView;
|
||||||
|
|
||||||
|
public NoteViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
titleTextView = itemView.findViewById(R.id.note_title);
|
||||||
|
|
||||||
|
titleTextView.setOnClickListener(v -> {
|
||||||
|
int position = getAdapterPosition();
|
||||||
|
if(position != RecyclerView.NO_POSITION) {
|
||||||
|
MusicNote song = noteTitles.get(position);
|
||||||
|
|
||||||
|
Intent intent = new Intent(itemView.getContext(), FullScreenImageActivity.class);
|
||||||
|
intent.putExtra("imageUri", song.getFilePath());
|
||||||
|
itemView.getContext().startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
package core.notevault.ui.metadatadialog;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.OpenableColumns;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import core.notevault.R;
|
||||||
|
|
||||||
|
public class MetaDataDialog extends DialogFragment {
|
||||||
|
private Uri fileUri;
|
||||||
|
|
||||||
|
public interface OnMetadataListener {
|
||||||
|
void onMetadataEntered(String title, String composer, int year, String genre);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnMetadataListener listener;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||||
|
LayoutInflater inflater = requireActivity().getLayoutInflater();
|
||||||
|
View dialogView = inflater.inflate(R.layout.fragment_metadata_dialog, null); // Ersetze 'your_dialog_layout' durch deinen Dateinamen
|
||||||
|
|
||||||
|
EditText title_input = dialogView.findViewById(R.id.title_input);
|
||||||
|
title_input.setText(this.extraxtTitleFromFilePath());
|
||||||
|
EditText composer_input = dialogView.findViewById(R.id.composer_input);
|
||||||
|
EditText year_input = dialogView.findViewById(R.id.year_input);
|
||||||
|
EditText genre_input = dialogView.findViewById(R.id.genre_input);
|
||||||
|
|
||||||
|
return new AlertDialog.Builder(requireContext())
|
||||||
|
.setView(dialogView)
|
||||||
|
.setPositiveButton("Speichern", (dialog, which) -> {
|
||||||
|
String title = title_input.getText().toString();
|
||||||
|
String composer = composer_input.getText().toString();
|
||||||
|
|
||||||
|
String year_string = year_input.getText().toString();
|
||||||
|
int year = 0;
|
||||||
|
if(!year_string.isEmpty()) {
|
||||||
|
year = Integer.parseInt(year_input.getText().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
String genre = genre_input.getText().toString();
|
||||||
|
|
||||||
|
listener.onMetadataEntered(title, composer, year, genre);
|
||||||
|
} )
|
||||||
|
.setNegativeButton("Abbrechen", (dialog, which) -> {} )
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(@NonNull Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
if (context instanceof OnMetadataListener) {
|
||||||
|
listener = (OnMetadataListener) context;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException(context.toString()
|
||||||
|
+ " must implement OnMetadataListener");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uri getFileUri() {
|
||||||
|
return fileUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileUri(Uri fileUri) {
|
||||||
|
this.fileUri = fileUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extraxtTitleFromFilePath() {
|
||||||
|
String fileName = "";
|
||||||
|
|
||||||
|
// Überprüfen, ob die Uri ein Content-Uri ist
|
||||||
|
if (this.fileUri.getScheme().equals("content")) {
|
||||||
|
// ContentResolver verwenden, um die Datei zu finden
|
||||||
|
Cursor cursor = requireContext().getContentResolver().query(this.fileUri, null, null, null, null);
|
||||||
|
if (cursor != null) {
|
||||||
|
int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
||||||
|
if (cursor.moveToFirst()) {
|
||||||
|
// Den Dateinamen aus dem Cursor abfragen
|
||||||
|
fileName = cursor.getString(nameIndex);
|
||||||
|
}
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
} else if (this.fileUri.getScheme().equals("file")) {
|
||||||
|
// Bei einer Datei-Uri einfach den letzten Pfadsegment verwenden
|
||||||
|
fileName = this.fileUri.getLastPathSegment();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fileName.contains(".")) {
|
||||||
|
fileName = fileName.substring(0, fileName.lastIndexOf("."));
|
||||||
|
fileName = fileName.replace("_", " ");
|
||||||
|
fileName = fileName.replace("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String TAG = "MetaDataDialog";
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package core.notevault.ui.slideshow;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import core.notevault.databinding.FragmentSlideshowBinding;
|
||||||
|
|
||||||
|
public class SlideshowFragment extends Fragment {
|
||||||
|
|
||||||
|
private FragmentSlideshowBinding binding;
|
||||||
|
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
|
ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
SlideshowViewModel slideshowViewModel =
|
||||||
|
new ViewModelProvider(this).get(SlideshowViewModel.class);
|
||||||
|
|
||||||
|
binding = FragmentSlideshowBinding.inflate(inflater, container, false);
|
||||||
|
View root = binding.getRoot();
|
||||||
|
|
||||||
|
final TextView textView = binding.textSlideshow;
|
||||||
|
slideshowViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package core.notevault.ui.slideshow;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
|
public class SlideshowViewModel extends ViewModel {
|
||||||
|
|
||||||
|
private final MutableLiveData<String> mText;
|
||||||
|
|
||||||
|
public SlideshowViewModel() {
|
||||||
|
mText = new MutableLiveData<>();
|
||||||
|
mText.setValue("This is slideshow fragment");
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<String> getText() {
|
||||||
|
return mText;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960">
|
||||||
|
<path
|
||||||
|
android:pathData="M440,520L200,520v-80h240v-240h80v240h240v80L520,520v240h-80v-240Z"
|
||||||
|
android:fillColor="#e8eaed"/>
|
||||||
|
</vector>
|
12
app/src/main/res/drawable/ic_menu_camera.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M9,2L7.17,4H4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2H9zm3,15c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/ic_menu_gallery.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M22,16V4c0,-1.1 -0.9,-2 -2,-2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zm-11,-4l2.03,2.71L16,11l4,5H8l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2H4V6H2z"/>
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/ic_menu_slideshow.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6zm16,-4H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zm-8,12.5v-9l6,4.5 -6,4.5z"/>
|
||||||
|
</vector>
|
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z"/></svg>
|
After Width: | Height: | Size: 182 B |
9
app/src/main/res/drawable/side_nav_bar.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<gradient
|
||||||
|
android:angle="135"
|
||||||
|
android:centerColor="#009688"
|
||||||
|
android:endColor="#00695C"
|
||||||
|
android:startColor="#4DB6AC"
|
||||||
|
android:type="linear"/>
|
||||||
|
</shape>
|
12
app/src/main/res/layout/activity_full_screen_image.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/fullscreen_image_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:scaleType="fitCenter" /> <!-- Optional: fitCenter, centerCrop, etc. -->
|
||||||
|
|
||||||
|
</RelativeLayout>
|
26
app/src/main/res/layout/activity_main.xml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.drawerlayout.widget.DrawerLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/drawer_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
tools:openDrawer="start">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/app_bar_main"
|
||||||
|
layout="@layout/app_bar_main"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
|
||||||
|
<com.google.android.material.navigation.NavigationView
|
||||||
|
android:id="@+id/nav_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="start"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
app:headerLayout="@layout/nav_header_main"
|
||||||
|
app:menu="@menu/activity_main_drawer"/>
|
||||||
|
</androidx.drawerlayout.widget.DrawerLayout>
|
26
app/src/main/res/layout/app_bar_main.xml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:theme="@style/Theme.NoteVault.AppBarOverlay">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
app:popupTheme="@style/Theme.NoteVault.PopupOverlay"
|
||||||
|
android:layout_height="?attr/actionBarSize"/>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<include layout="@layout/content_main"/>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
22
app/src/main/res/layout/content_main.xml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
tools:showIn="@layout/app_bar_main">
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/nav_host_fragment_content_main"
|
||||||
|
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:defaultNavHost="true"
|
||||||
|
app:navGraph="@navigation/mobile_navigation"
|
||||||
|
/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
23
app/src/main/res/layout/fragment_gallery.xml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ui.gallery.GalleryFragment">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_gallery"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="20sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
28
app/src/main/res/layout/fragment_home.xml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ui.home.HomeFragment">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/note_recycler_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_above="@+id/importMusicNotesBtn"/>
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:src="@drawable/add_24dp_e8eaed_fill0_wght400_grad0_opsz24"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="true"
|
||||||
|
android:id="@+id/importMusicNotesBtn"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
app:backgroundTint="@color/teal_200"
|
||||||
|
android:contentDescription="Add Music Notes"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
126
app/src/main/res/layout/fragment_metadata_dialog.xml
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:id="@+id/metadata_dialog">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:text="Import-Einstellungen"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/dialog_title"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="18sp"/>
|
||||||
|
|
||||||
|
<TableLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:text="Titel: "
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/title_label"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:inputType="text"
|
||||||
|
android:ems="10"
|
||||||
|
android:id="@+id/title_input"
|
||||||
|
android:hint="Titel eingeben"
|
||||||
|
android:foregroundTint="#000000"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:minWidth="48dp"/>
|
||||||
|
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:text="Komponisten: "
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/composer_label"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="text"
|
||||||
|
android:ems="10"
|
||||||
|
android:id="@+id/composer_input"
|
||||||
|
android:hint="Komponisten eingeben"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:minWidth="48dp"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:padding="16dp"/>
|
||||||
|
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:text="Jahr: "
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/year_label"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="numberSigned"
|
||||||
|
android:ems="10"
|
||||||
|
android:id="@+id/year_input"
|
||||||
|
android:hint="Erscheinungsjahr eingeben"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:minWidth="48dp"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:text="Genre: "
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/genre_label"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="text"
|
||||||
|
android:ems="10"
|
||||||
|
android:id="@+id/genre_input"
|
||||||
|
android:hint="Genre eingeben"
|
||||||
|
android:minWidth="48dp"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
</TableRow>
|
||||||
|
</TableLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
23
app/src/main/res/layout/fragment_slideshow.xml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ui.slideshow.SlideshowFragment">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_slideshow"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="20sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
13
app/src/main/res/layout/item_song.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/note_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
</LinearLayout>
|
36
app/src/main/res/layout/nav_header_main.xml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/nav_header_height"
|
||||||
|
android:background="@drawable/side_nav_bar"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
android:theme="@style/ThemeOverlay.AppCompat.Dark"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="bottom">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||||
|
app:srcCompat="@mipmap/ic_launcher_round"
|
||||||
|
android:contentDescription="@string/nav_header_desc"
|
||||||
|
android:id="@+id/imageView"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||||
|
android:text="@string/nav_header_title"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/nav_header_subtitle"
|
||||||
|
android:id="@+id/textView"/>
|
||||||
|
</LinearLayout>
|
20
app/src/main/res/menu/activity_main_drawer.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:showIn="navigation_view">
|
||||||
|
|
||||||
|
<group android:checkableBehavior="single">
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_home"
|
||||||
|
android:icon="@drawable/ic_menu_camera"
|
||||||
|
android:title="@string/menu_home"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_gallery"
|
||||||
|
android:icon="@drawable/ic_menu_gallery"
|
||||||
|
android:title="@string/menu_gallery"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_slideshow"
|
||||||
|
android:icon="@drawable/ic_menu_slideshow"
|
||||||
|
android:title="@string/menu_slideshow"/>
|
||||||
|
</group>
|
||||||
|
</menu>
|
8
app/src/main/res/menu/main.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<item android:id="@+id/action_settings"
|
||||||
|
android:title="@string/action_settings"
|
||||||
|
android:orderInCategory="101"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
</menu>
|
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@mipmap/ic_launcher_background"/>
|
|
||||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
|
||||||
</adaptive-icon>
|
|
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@mipmap/ic_launcher_background"/>
|
|
||||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
|
||||||
</adaptive-icon>
|
|
6
app/src/main/res/mipmap-anydpi/ic_launcher.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
6
app/src/main/res/mipmap-anydpi/ic_launcher_round.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 44 B |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 982 B |
Before Width: | Height: | Size: 44 B |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 46 B |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 52 B |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 52 B |
Before Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 7.6 KiB |
25
app/src/main/res/navigation/mobile_navigation.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/mobile_navigation"
|
||||||
|
app:startDestination="@+id/nav_home">
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/nav_home"
|
||||||
|
android:name="core.notevault.ui.home.HomeFragment"
|
||||||
|
android:label="@string/menu_home"
|
||||||
|
tools:layout="@layout/fragment_home"/>
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/nav_gallery"
|
||||||
|
android:name="core.notevault.ui.gallery.GalleryFragment"
|
||||||
|
android:label="@string/menu_gallery"
|
||||||
|
tools:layout="@layout/fragment_gallery"/>
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/nav_slideshow"
|
||||||
|
android:name="core.notevault.ui.slideshow.SlideshowFragment"
|
||||||
|
android:label="@string/menu_slideshow"
|
||||||
|
tools:layout="@layout/fragment_slideshow"/>
|
||||||
|
</navigation>
|
3
app/src/main/res/values-land/dimens.xml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<resources>
|
||||||
|
<dimen name="fab_margin">48dp</dimen>
|
||||||
|
</resources>
|
16
app/src/main/res/values-night/themes.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="Theme.NoteVault" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
|
<!-- Primary brand color. -->
|
||||||
|
<item name="colorPrimary">@color/purple_200</item>
|
||||||
|
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||||
|
<item name="colorOnPrimary">@color/black</item>
|
||||||
|
<!-- Secondary brand color. -->
|
||||||
|
<item name="colorSecondary">@color/teal_200</item>
|
||||||
|
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||||
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
|
<!-- Status bar color. -->
|
||||||
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
</style>
|
||||||
|
</resources>
|
3
app/src/main/res/values-w1240dp/dimens.xml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<resources>
|
||||||
|
<dimen name="fab_margin">200dp</dimen>
|
||||||
|
</resources>
|
3
app/src/main/res/values-w600dp/dimens.xml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<resources>
|
||||||
|
<dimen name="fab_margin">48dp</dimen>
|
||||||
|
</resources>
|
8
app/src/main/res/values/dimens.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<resources>
|
||||||
|
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||||
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
|
<dimen name="nav_header_vertical_spacing">8dp</dimen>
|
||||||
|
<dimen name="nav_header_height">176dp</dimen>
|
||||||
|
<dimen name="fab_margin">16dp</dimen>
|
||||||
|
</resources>
|