Author: Adam <git@apiote.xyz>
initial functionality
%!v(PANIC=String method: strings: negative Repeat count)
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c4d8075fc753a1485b178b2e26220224e44e4b63 --- /dev/null +++ b/.gitignore @@ -0,0 +1,218 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/android,androidstudio +# Edit at https://www.toptal.com/developers/gitignore?templates=android,androidstudio + +### Android ### +# Built application files +*.apk +*.aar +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ +# Uncomment the following line in case you need and you don't have the release build type files in your app +# release/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/assetWizardSettings.xml +.idea/dictionaries +.idea/libraries +.idea/jarRepositories.xml +# Android Studio 3 in .gitignore file. +.idea/caches +.idea/modules.xml +# Comment next line if keeping position of elements in Navigation Editor is relevant for you +.idea/navEditor.xml + +# Keystore files +# Uncomment the following lines if you do not want to check your keystore files in. +#*.jks +#*.keystore + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.cxx/ + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md + +# Version control +vcs.xml + +# lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ +# lint/reports/ + +# Android Profiling +*.hprof + +### Android Patch ### +gen-external-apklibs +output.json + +# Replacement of .externalNativeBuild directories introduced +# with Android Studio 3.5. + +### AndroidStudio ### +# Covers files to be ignored for android development using Android Studio. + +# Built application files + +# Files for the ART/Dalvik VM + +# Java class files + +# Generated files + +# Gradle files +.gradle + +# Signing files +.signing/ + +# Local configuration file (sdk path, etc) + +# Proguard folder generated by Eclipse + +# Log Files + +# Android Studio +/*/build/ +/*/local.properties +/*/out +/*/*/build +/*/*/production +*.ipr +*~ +*.swp + +# Keystore files +*.jks +*.keystore + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Android Patch + +# External native build folder generated in Android Studio 2.2 and later + +# NDK +obj/ + +# IntelliJ IDEA +*.iws +/out/ + +# User-specific configurations +.idea/caches/ +.idea/libraries/ +.idea/shelf/ +.idea/.name +.idea/compiler.xml +.idea/copyright/profiles_settings.xml +.idea/encodings.xml +.idea/misc.xml +.idea/scopes/scope_settings.xml +.idea/vcs.xml +.idea/jsLibraryMappings.xml +.idea/datasources.xml +.idea/dataSources.ids +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml + +# OS-specific files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Legacy Eclipse project files +.classpath +.project +.cproject +.settings/ + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.war +*.ear + +# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) +hs_err_pid* + +## Plugin-specific files: + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Mongo Explorer plugin +.idea/mongoSettings.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### AndroidStudio Patch ### + +!/gradle/wrapper/gradle-wrapper.jar + +# End of https://www.toptal.com/developers/gitignore/api/android,androidstudio diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..26d33521af10bcc7fd8cea344038eaaeb78d0ef5 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/render.experimental.xml b/.idea/render.experimental.xml new file mode 100644 index 0000000000000000000000000000000000000000..8ec256a5d290bffdb16a99dd3db0d613792739d5 --- /dev/null +++ b/.idea/render.experimental.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="RenderSettings"> + <option name="showDecorations" value="true" /> + </component> +</project> \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..42afabfd2abebf31384ca7797186a27a4b7dbee8 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..7db0ff536ba05e60aa2bb01e5a01086113058c36 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,49 @@ +plugins { + id 'com.android.application' + id 'kotlin-android' +} + +android { + compileSdk 30 + + defaultConfig { + applicationId "xyz.apiote.stuff" + minSdk 21 + targetSdk 30 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } + buildFeatures { + viewBinding true + } +} + +dependencies { + + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.1' + implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5' + implementation 'androidx.navigation:navigation-ui-ktx:2.3.5' + implementation project(path: ':bare') + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000000000000000000000000000000000000..481bb434814107eb79d7a30b676d344b0df2f8ce --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/xyz/apiote/stuff/ExampleInstrumentedTest.kt b/app/src/androidTest/java/xyz/apiote/stuff/ExampleInstrumentedTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..d783385e4792de4dfb941953a6580fffbb08dfa1 --- /dev/null +++ b/app/src/androidTest/java/xyz/apiote/stuff/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package xyz.apiote.stuff + +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("xyz.apiote.stuff", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..35222f971e2873268c78e7d1c16e85dfcf4e5978 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="xyz.apiote.stuff"> + + <application + android:allowBackup="true" + android:icon="@mipmap/ic_launcher" + android:label="@string/app_name" + android:roundIcon="@mipmap/ic_launcher_round" + android:supportsRtl="true" + android:theme="@style/Theme.Stuff"> + <activity + android:name=".ImportExportActivity" + android:exported="true" /> + <activity + android:name=".EditActivity" + android:exported="true" /> + <activity + android:name=".ContainerActivity" + android:exported="true" + android:label="@string/app_name" + android:theme="@style/Theme.Stuff.NoActionBar"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest> \ No newline at end of file diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..58b2796d54dc6b321a19899a13cd187affe1bb07 Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ diff --git a/app/src/main/java/xyz/apiote/stuff/ContainerActivity.kt b/app/src/main/java/xyz/apiote/stuff/ContainerActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..e6aa8f755b11801aa60a95337bf1f223a821a206 --- /dev/null +++ b/app/src/main/java/xyz/apiote/stuff/ContainerActivity.kt @@ -0,0 +1,303 @@ +package xyz.apiote.stuff + +import android.annotation.SuppressLint +import android.content.Intent +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import xyz.apiote.stuff.databinding.ActivityContainerBinding +import android.content.Context +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.LinearLayoutManager +import android.app.Activity +import android.graphics.Rect +import android.view.* +import androidx.constraintlayout.widget.ConstraintLayout +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.snackbar.Snackbar +import android.view.MotionEvent + +// todo consts + +class ContainerActivity : AppCompatActivity(), StuffAdapter.ItemClickListener { + + private lateinit var binding: ActivityContainerBinding + private lateinit var stuff: Stuff + private var mode: String = "" + private lateinit var db: DB + private lateinit var adapter: StuffAdapter + private lateinit var containedStuff: ArrayList<Stuff> + + enum class REQUEST(val value: Int) { + EDIT(0), + PICK(1) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + db = DB(this) + db.migrate() + + binding = ActivityContainerBinding.inflate(layoutInflater) + setContentView(binding.root) + + mode = intent.extras?.get("mode") as String? ?: "view" + stuff = db.loadStuff(intent.extras?.get("ID") as Long? ?: 0) + + setSupportActionBar(binding.toolbar) + supportActionBar!!.title = stuff.name + + if (mode == "pick") { + setResult(RESULT_CANCELED) + binding.fab.visibility = View.GONE + } else { + binding.fab.setOnClickListener { + val editIntent = Intent(this, EditActivity::class.java) + editIntent.putExtra("container", stuff.id) + startActivityForResult(editIntent, REQUEST.EDIT.value) + } + } + + binding.stuffRecycler.layoutManager = LinearLayoutManager(this) + adapter = StuffAdapter(this, emptyList()) + adapter.setClickListener(this) + binding.stuffRecycler.adapter = adapter + } + + override fun onResume() { + super.onResume() + updateStuffList() + swapListVisibility() + hideBottom() + } + + @SuppressLint("NotifyDataSetChanged") + private fun updateStuffList(notify: Boolean = true) { + containedStuff = db.loadContainer(stuff.id!!) + adapter.setData(containedStuff) + if (notify) { + // todo calculate changes (probably only inserts, we cannot delete if we’re not there) + adapter.notifyDataSetChanged() + } + } + + private fun swapListVisibility() { + if (containedStuff.isEmpty()) { + binding.emptyState.root.visibility = View.VISIBLE + binding.stuffRecycler.visibility = View.GONE + } else { + binding.emptyState.root.visibility = View.GONE + binding.stuffRecycler.visibility = View.VISIBLE + } + } + + override fun onItemClick(view: View?, position: Int) { + val selectedStuff = adapter.getItem(position) + val selectedContents = db.loadContainer(selectedStuff.id!!) + when { + mode == "pick" -> { + val pickIntent = Intent(this, ContainerActivity::class.java) + pickIntent.putExtra("mode", "pick") + pickIntent.putExtra("ID", selectedStuff.id) + startActivityForResult(pickIntent, REQUEST.PICK.value) + } + selectedContents.isNotEmpty() -> { + val viewIntent = Intent(this, ContainerActivity::class.java) + viewIntent.putExtra("ID", selectedStuff.id) + startActivity(viewIntent) + } + else -> { + showBottomInfo(selectedStuff) + } + } + } + + private fun hideBottom() { + val bottomSheet = findViewById<ConstraintLayout>(R.id.standard_bottom_sheet) + val bottomSheetBehavior: BottomSheetBehavior<*> = BottomSheetBehavior.from(bottomSheet) + bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN + } + + private fun showBottomInfo(selectedStuff: Stuff) { + val bottomSheetBehavior = BottomSheetBehavior.from(binding.standardBottomSheet) + bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED + binding.bottomStuffName.text = selectedStuff.name + binding.bottomStuffDescription.text = selectedStuff.description + binding.bottomEdit.setOnClickListener { + hideBottom() + val editIntent = Intent(this, EditActivity::class.java) + editIntent.putExtra("ID", selectedStuff.id) + startActivityForResult(editIntent, REQUEST.EDIT.value) + } + + if (selectedStuff.id == 0L) { + binding.bottomDelete.visibility = View.GONE + binding.bottomEdit.visibility = View.GONE + } else { + binding.bottomDelete.visibility = View.VISIBLE + binding.bottomEdit.visibility = View.VISIBLE + binding.bottomDelete.setOnClickListener { + if (db.loadContainer(selectedStuff.id!!).isNotEmpty()) { + Snackbar.make( + binding.root, + getString(R.string.stuff_not_empty, selectedStuff.name), + Snackbar.LENGTH_SHORT + ) + .show() + } else { + db.deleteStuff(selectedStuff.id) + val position = adapter.getPosition(selectedStuff.id) + containedStuff = db.loadContainer(stuff.id!!) + adapter.setData(containedStuff) + adapter.notifyItemRemoved(position) + hideBottom() + swapListVisibility() + } + } + } + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + if (mode == "view") { + if (stuff.id != 0L) { + menuInflater.inflate(R.menu.menu_container_view, menu) + } else { + menuInflater.inflate(R.menu.menu_container_view_ie, menu) + } + } else if (mode == "pick") { + menuInflater.inflate(R.menu.menu_container_pick, menu) + } + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.action_info -> { + showBottomInfo(stuff) + true + } + R.id.action_import_export -> { + val intent = Intent(this, ImportExportActivity::class.java) + startActivity(intent) + true + } + R.id.action_pick -> { + val returnIntent = Intent() + returnIntent.putExtra("stuffID", stuff.id) + setResult(RESULT_OK, returnIntent) + finish() + true + } + else -> super.onOptionsItemSelected(item) + } + } + + override fun dispatchTouchEvent(event: MotionEvent?): Boolean { + val bottomSheetBehavior = BottomSheetBehavior.from(binding.standardBottomSheet) + if (event?.action == MotionEvent.ACTION_DOWN) { + val outRect = Rect() + binding.standardBottomSheet.getGlobalVisibleRect(outRect) + if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) { + bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN + } + } + + return super.dispatchTouchEvent(event) + } + + // fixme https://proandroiddev.com/is-onactivityresult-deprecated-in-activity-results-api-lets-deep-dive-into-it-302d5cf6edd?gi=75b767b0d7ea + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == REQUEST.PICK.value && resultCode == Activity.RESULT_OK) { + val stuffID = data!!.getLongExtra("stuffID", -1L) + val returnIntent = Intent() + returnIntent.putExtra("stuffID", stuffID) + setResult(RESULT_OK, returnIntent) + finish() + } + if (requestCode == REQUEST.EDIT.value && resultCode == Activity.RESULT_OK) { + val newStuffID = data!!.getLongExtra("stuffID", -1L) + val isInserted = data.getBooleanExtra("inserted", false) + val newContainer = data.getLongExtra("newContainer", -1L) + if (isInserted && newContainer == stuff.container) { + updateStuffList(false) + swapListVisibility() + val position = adapter.getPosition(newStuffID) + adapter.notifyItemInserted(position) + } + if (!isInserted) { + if (!adapter.contains(newStuffID)) { + // fixme if newContainer != -1 -> up is incorrect + supportActionBar!!.title = db.loadStuff(newStuffID).name + } else { + val position = adapter.getPosition(newStuffID) + updateStuffList(false) + if (newContainer == -1L) { + adapter.notifyItemChanged(position) + } else { + adapter.notifyItemRemoved(position) + swapListVisibility() + } + } + } + } + } +} + +class StuffAdapter internal constructor(context: Context?, private var data: List<Stuff>) : + RecyclerView.Adapter<StuffAdapter.ViewHolder>() { + private val inflater = LayoutInflater.from(context) + private var clickListener: ItemClickListener? = null + + inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView), + View.OnClickListener { + var stuffNameTextView = itemView.findViewById<TextView>(R.id.rowStuffName)!! + override fun onClick(view: View) { + clickListener?.onItemClick(view, adapterPosition) + } + + init { + itemView.setOnClickListener(this) + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val view: View = inflater.inflate(R.layout.stuff_row, parent, false) + return ViewHolder(view) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.stuffNameTextView.text = data[position].name + } + + override fun getItemCount(): Int { + return data.size + } + + fun setData(newData: List<Stuff>) { + data = newData + } + + fun getItem(position: Int): Stuff { + return data[position] + } + + fun getPosition(id: Long): Int { + return data.indexOfFirst { + it.id == id + } + } + + fun contains(id: Long): Boolean { + return getPosition(id) != -1 + } + + fun setClickListener(itemClickListener: ItemClickListener?) { + clickListener = itemClickListener + } + + interface ItemClickListener { + fun onItemClick(view: View?, position: Int) + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/apiote/stuff/EditActivity.kt b/app/src/main/java/xyz/apiote/stuff/EditActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..64e26121ed572f17e4033c8038432dc6297f285a --- /dev/null +++ b/app/src/main/java/xyz/apiote/stuff/EditActivity.kt @@ -0,0 +1,119 @@ +package xyz.apiote.stuff + +import android.app.Activity +import android.content.Intent +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import com.google.android.material.snackbar.Snackbar +import xyz.apiote.stuff.databinding.ActivityEditBinding + +// todo consts + +class EditActivity : AppCompatActivity() { + private lateinit var binding: ActivityEditBinding + private var id: Long? = null + private var stuff = Stuff(null, "", "", -1) + private var originalStuff = Stuff(null, "", "", -1) + private lateinit var db: DB + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = ActivityEditBinding.inflate(layoutInflater) + setContentView(binding.root) + + val receivedContainer = intent.extras?.get("container") as Long? + stuff.container = receivedContainer ?: -1 + + binding.chooseContainer.setOnClickListener { + val chooseIntent = Intent(this, ContainerActivity::class.java) + chooseIntent.putExtra("ID", 0L) + chooseIntent.putExtra("mode", "pick") + startActivityForResult(chooseIntent, ContainerActivity.REQUEST.PICK.value) + } + + db = DB(this) + + id = intent.extras?.get("ID") as Long? + title = if (id != null) { + stuff = db.loadStuff(id!!) + binding.editName.setText(stuff.name) + binding.editDescription.setText(stuff.description) + binding.nameContainer.text = db.loadStuff(stuff.container).name + getString(R.string.edit_stuff, stuff.name) + } else { + getString(R.string.add_stuff) + } + + if (stuff.container != -1L) { + binding.nameContainer.text = db.loadStuff(stuff.container).name + } else { + binding.nameContainer.text = getString(R.string.no_container) + } + + originalStuff = stuff + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.menu_edit, menu) + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.action_save -> { + stuff.name = binding.editName.text.toString() + stuff.description = binding.editDescription.text.toString() + if (stuff.container == -1L) { + Snackbar.make( + binding.root, + getString(R.string.container_must_not_be_empty), + Snackbar.LENGTH_SHORT + ) + .show() + return true + } + if (stuff.name == "") { + Snackbar.make( + binding.root, + getString(R.string.name_must_not_be_empty), + Snackbar.LENGTH_SHORT + ) + .show() + return true + } + val (id, inserted) = db.saveStuff(stuff) + val returnIntent = Intent() + returnIntent.putExtra("stuffID", id as Long) + returnIntent.putExtra("inserted", inserted as Boolean) + if (stuff.container != originalStuff.container) { + returnIntent.putExtra("newContainer", stuff.container) + } + setResult(RESULT_OK, returnIntent) + finish() + true + } + else -> super.onOptionsItemSelected(item) + } + } + + override fun onBackPressed() { + setResult(RESULT_CANCELED) + super.onBackPressed() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == ContainerActivity.REQUEST.PICK.value) { + if (resultCode == Activity.RESULT_OK) { + val stuffID = data!!.getLongExtra("stuffID", -1L) + if (stuffID != -1L) { + stuff.container = stuffID + binding.nameContainer.text = db.loadStuff(stuff.container).name + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/apiote/stuff/db.kt b/app/src/main/java/xyz/apiote/stuff/db.kt new file mode 100644 index 0000000000000000000000000000000000000000..ba613150a90c5cfa16f542c39b401b1d45c61994 --- /dev/null +++ b/app/src/main/java/xyz/apiote/stuff/db.kt @@ -0,0 +1,80 @@ +package xyz.apiote.stuff + +import android.content.ContentValues +import android.content.Context +import android.content.ContextWrapper +import android.database.sqlite.SQLiteConstraintException +import android.database.sqlite.SQLiteDatabase + +// todo consts + +data class Stuff(val id: Long?, var name: String, var description: String, var container: Long) + +class DB(context: ContextWrapper) { + private var db: SQLiteDatabase = context.openOrCreateDatabase( + "stuff", + Context.MODE_PRIVATE, null + ) + + fun migrate() { + db.execSQL("create table if not exists stuff(id integer primary key, name string, description string, container int, foreign key(container) references stuff(id));") + try { + db.execSQL( + "insert into stuff values(?, ?, ?, ?)", + arrayOf(0, "Stuff", "", -1) + ) + } catch (e: SQLiteConstraintException) { + } + } + + fun saveStuff(stuff: Stuff): Array<Any> { + db.rawQuery("select * from stuff where id = ?", arrayOf(stuff.id.toString())).use { + return if (it.moveToNext()) { + db.execSQL( + "update stuff set name = ?, description = ?, container = ? where id = ?", + arrayOf(stuff.name, stuff.description, stuff.container, stuff.id) + ) + arrayOf(stuff.id!!, false) + } else { + val values = ContentValues() + values.put("name", stuff.name) + values.put("description", stuff.description) + values.put("container", stuff.container) + arrayOf(db.insert("stuff", null, values), true) + } + } + } + + fun loadStuff(id: Long): Stuff { + return db.rawQuery("select * from stuff where id = ?", arrayOf(id.toString())).use { + val hasValue = it.moveToNext() + assert(hasValue) + val name = it.getString(1) + val description = it.getString(2) + val container = it.getLong(3) + + Stuff(id, name, description, container) + } + } + + fun loadContainer(containerID: Long): ArrayList<Stuff> { + val stuff = ArrayList<Stuff>() + db.rawQuery( + "select * from stuff where container = ? order by name", + arrayOf(containerID.toString()) + ).use { + while (it.moveToNext()) { + val id = it.getLong(0) + val name = it.getString(1) + val description = it.getString(2) + val container = it.getLong(3) + stuff.add(Stuff(id, name, description, container)) + } + } + return stuff + } + + fun deleteStuff(id: Long) { + db.execSQL("delete from stuff where id = ?", arrayOf(id.toString())) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/add.xml b/app/src/main/res/drawable/add.xml new file mode 100644 index 0000000000000000000000000000000000000000..eb232541d873c666e1063cb1ef41aa3e66b1cf27 --- /dev/null +++ b/app/src/main/res/drawable/add.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/> +</vector> diff --git a/app/src/main/res/drawable/delete.xml b/app/src/main/res/drawable/delete.xml new file mode 100644 index 0000000000000000000000000000000000000000..3c4030b03e52082973dddcfff97def1ed81fe5ba --- /dev/null +++ b/app/src/main/res/drawable/delete.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/> +</vector> diff --git a/app/src/main/res/drawable/done.xml b/app/src/main/res/drawable/done.xml new file mode 100644 index 0000000000000000000000000000000000000000..899cbb684033bb9727d8c7c29619510541999a28 --- /dev/null +++ b/app/src/main/res/drawable/done.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/> +</vector> diff --git a/app/src/main/res/drawable/edit.xml b/app/src/main/res/drawable/edit.xml new file mode 100644 index 0000000000000000000000000000000000000000..2844bafebe8a5b0ae7431437d83e4cdbbac2b432 --- /dev/null +++ b/app/src/main/res/drawable/edit.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/> +</vector> diff --git a/app/src/main/res/drawable/empty_box.xml b/app/src/main/res/drawable/empty_box.xml new file mode 100644 index 0000000000000000000000000000000000000000..dabd6871e4eeabc71a5bcdf81abcfe44493ca502 --- /dev/null +++ b/app/src/main/res/drawable/empty_box.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M20.55,5.22l-1.39,-1.68C18.88,3.21 18.47,3 18,3H6C5.53,3 5.12,3.21 4.85,3.55L3.46,5.22C3.17,5.57 3,6.01 3,6.5V19c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V6.5C21,6.01 20.83,5.57 20.55,5.22zM12,9.5l5.5,5.5H14v2h-4v-2H6.5L12,9.5zM5.12,5l0.82,-1h12l0.93,1H5.12z"/> +</vector> diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000000000000000000000000000000000000..16a2b1dad121afc69de9214ac731ffa433bdfe3b --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,14 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="108" + android:viewportHeight="108"> + <group android:scaleX="1.98" + android:scaleY="1.98" + android:translateX="30.24" + android:translateY="30.24"> + <path + android:pathData="M20,2L4,2c-1,0 -2,0.9 -2,2v3.01c0,0.72 0.43,1.34 1,1.69L3,20c0,1.1 1.1,2 2,2h14c0.9,0 2,-0.9 2,-2L21,8.7c0.57,-0.35 1,-0.97 1,-1.69L22,4c0,-1.1 -1,-2 -2,-2zM15,14L9,14v-2h6v2zM20,7L4,7L4,4l16,-0.02L20,7z" + android:fillColor="#000000"/> + </group> +</vector> diff --git a/app/src/main/res/drawable/import_export.xml b/app/src/main/res/drawable/import_export.xml new file mode 100644 index 0000000000000000000000000000000000000000..bc5c0ad68df5e5b9999b424fbd3395458d3102e9 --- /dev/null +++ b/app/src/main/res/drawable/import_export.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M9,3L5,6.99h3L8,14h2L10,6.99h3L9,3zM16,17.01L16,10h-2v7.01h-3L15,21l4,-3.99h-3z"/> +</vector> diff --git a/app/src/main/res/drawable/info.xml b/app/src/main/res/drawable/info.xml new file mode 100644 index 0000000000000000000000000000000000000000..17255b7ae340198e106092df31e60084a54f8865 --- /dev/null +++ b/app/src/main/res/drawable/info.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/> +</vector> diff --git a/app/src/main/res/layout/activity_container.xml b/app/src/main/res/layout/activity_container.xml new file mode 100644 index 0000000000000000000000000000000000000000..b468e63b037c877f508ee907169a26eb1eaa83ce --- /dev/null +++ b/app/src/main/res/layout/activity_container.xml @@ -0,0 +1,107 @@ +<?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=".ContainerActivity"> + + <com.google.android.material.appbar.AppBarLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:theme="@style/Theme.Stuff.AppBarOverlay"> + + <androidx.appcompat.widget.Toolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="?attr/actionBarSize" + android:background="?attr/colorPrimary" + app:popupTheme="@style/Theme.Stuff.PopupOverlay" /> + + </com.google.android.material.appbar.AppBarLayout> + + <!-- todo maybe path --> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/stuffRecycler" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> + + <include + android:id="@+id/empty_state" + layout="@layout/empty_state" /> + + <androidx.constraintlayout.widget.ConstraintLayout + android:id="@+id/standard_bottom_sheet" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:theme="@style/Theme.Stuff.BottomSheetDialog" + app:behavior_fitToContents="true" + app:behavior_hideable="true" + app:behavior_skipCollapsed="true" + app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"> + + <TextView + android:id="@+id/bottom_stuff_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" + android:text="" + android:textAppearance="@style/TextAppearance.AppCompat.Display1" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <TextView + android:id="@+id/bottom_stuff_description" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="32dp" + android:layout_marginBottom="16dp" + android:text="" + android:textAppearance="@style/TextAppearance.AppCompat.Body1" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/bottom_stuff_name" /> + + <!-- todo touch tint --> + <ImageView + android:id="@+id/bottom_delete" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" + android:contentDescription="TODO" + android:src="@drawable/delete" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <!-- todo touch tint --> + <ImageView + android:id="@+id/bottom_edit" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" + android:contentDescription="TODO" + android:src="@drawable/edit" + app:layout_constraintEnd_toStartOf="@id/bottom_delete" + app:layout_constraintTop_toTopOf="parent" /> + + </androidx.constraintlayout.widget.ConstraintLayout> + + <!-- todo hide on scroll --> + <com.google.android.material.floatingactionbutton.FloatingActionButton + android:id="@+id/fab" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|end" + android:layout_marginEnd="@dimen/fab_margin" + android:layout_marginBottom="16dp" + android:contentDescription="TODO" + app:srcCompat="@drawable/add" /> + + +</androidx.coordinatorlayout.widget.CoordinatorLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_edit.xml b/app/src/main/res/layout/activity_edit.xml new file mode 100644 index 0000000000000000000000000000000000000000..04c27a3e2cc57fae5abf97bdc51f87754ec33cb2 --- /dev/null +++ b/app/src/main/res/layout/activity_edit.xml @@ -0,0 +1,81 @@ +<?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=".EditActivity"> + + <EditText + android:id="@+id/editName" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" + android:hint="@string/edit_name" + android:importantForAutofill="no" + android:inputType="textShortMessage|textAutoCorrect|text" + android:minHeight="48dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <EditText + android:id="@+id/editDescription" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" + android:hint="@string/edit_description" + android:importantForAutofill="no" + android:inputType="textMultiLine|text" + android:minHeight="48dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/editName" /> + + <Button + android:id="@+id/chooseContainer" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="24dp" + android:text="@string/edit_choose_container" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/divider" /> + + <TextView + android:id="@+id/nameContainer" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="24dp" + android:text="" + app:layout_constraintBottom_toBottomOf="@+id/chooseContainer" + app:layout_constraintStart_toEndOf="@+id/chooseContainer" + app:layout_constraintTop_toTopOf="@+id/chooseContainer" /> + + <View + android:id="@+id/divider" + android:layout_width="0dp" + android:layout_height="1dp" + android:layout_marginStart="8dp" + android:background="?android:attr/listDivider" + app:layout_constraintBottom_toBottomOf="@+id/textDividerContainer" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/textDividerContainer" + app:layout_constraintTop_toTopOf="@+id/textDividerContainer" /> + + <TextView + android:id="@+id/textDividerContainer" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginTop="24dp" + android:background="?android:attr/colorBackground" + android:text="@string/divider_container" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/editDescription" /> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_import_export.xml b/app/src/main/res/layout/activity_import_export.xml new file mode 100644 index 0000000000000000000000000000000000000000..1fd3f50e5efefb4e91cf7b0ea260813d883aae95 --- /dev/null +++ b/app/src/main/res/layout/activity_import_export.xml @@ -0,0 +1,47 @@ +<?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=".ImportExportActivity"> + + <Button + android:id="@+id/ie_select_file_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="64dp" + android:text="select file" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <Button + android:id="@+id/ie_import_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" + android:text="import" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/ie_select_file_button" /> + + <Button + android:id="@+id/ie_export_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="16dp" + android:text="export" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="@+id/ie_import_button" /> + + <TextView + android:id="@+id/textView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:text="" + app:layout_constraintBottom_toBottomOf="@+id/ie_select_file_button" + app:layout_constraintStart_toEndOf="@+id/ie_select_file_button" + app:layout_constraintTop_toTopOf="@+id/ie_select_file_button" /> +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/empty_state.xml b/app/src/main/res/layout/empty_state.xml new file mode 100644 index 0000000000000000000000000000000000000000..9683a5044ff1d7a67d008cfa4729d1a5d85357b8 --- /dev/null +++ b/app/src/main/res/layout/empty_state.xml @@ -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" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ImageView + android:id="@+id/imageView" + android:layout_width="64dp" + android:layout_height="64dp" + android:alpha="0.5" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/empty_box" /> + + <TextView + android:id="@+id/textView2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:alpha="0.5" + android:text="No stuff yet" + app:layout_constraintEnd_toEndOf="@+id/imageView" + app:layout_constraintStart_toStartOf="@+id/imageView" + app:layout_constraintTop_toBottomOf="@+id/imageView" /> +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/stuff_row.xml b/app/src/main/res/layout/stuff_row.xml new file mode 100644 index 0000000000000000000000000000000000000000..f6f542d5ff5f388e899993a670e32cff8ae6046c --- /dev/null +++ b/app/src/main/res/layout/stuff_row.xml @@ -0,0 +1,29 @@ +<?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="wrap_content"> + + <TextView + android:id="@+id/rowStuffName" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:text="" + app:layout_constraintBottom_toBottomOf="@+id/checkBox" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="@+id/checkBox" /> + + <CheckBox + android:id="@+id/checkBox" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" + android:layout_marginBottom="16dp" + android:text="" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" /> +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/menu/menu_container_pick.xml b/app/src/main/res/menu/menu_container_pick.xml new file mode 100644 index 0000000000000000000000000000000000000000..356bba90f73636eee617ed214d9312608317c069 --- /dev/null +++ b/app/src/main/res/menu/menu_container_pick.xml @@ -0,0 +1,10 @@ +<menu 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" + tools:context="xyz.apiote.stuff.ContainerActivity"> + <item + android:id="@+id/action_pick" + android:orderInCategory="100" + app:showAsAction="always" + android:title="@string/container_pick_here" /> +</menu> \ No newline at end of file diff --git a/app/src/main/res/menu/menu_container_view.xml b/app/src/main/res/menu/menu_container_view.xml new file mode 100644 index 0000000000000000000000000000000000000000..112810d9f4d5e7dfb6291dc13be2d59e6ab5e920 --- /dev/null +++ b/app/src/main/res/menu/menu_container_view.xml @@ -0,0 +1,11 @@ +<menu 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" + tools:context="xyz.apiote.stuff.ContainerActivity"> + <item + android:id="@+id/action_info" + android:icon="@drawable/info" + android:orderInCategory="100" + android:title="@string/container_view_info" + app:showAsAction="ifRoom" /> +</menu> \ No newline at end of file diff --git a/app/src/main/res/menu/menu_container_view_ie.xml b/app/src/main/res/menu/menu_container_view_ie.xml new file mode 100644 index 0000000000000000000000000000000000000000..99ca213f4b810c047a78561f1fcf87fb3b2f5950 --- /dev/null +++ b/app/src/main/res/menu/menu_container_view_ie.xml @@ -0,0 +1,11 @@ +<menu 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" + tools:context="xyz.apiote.stuff.ContainerActivity"> + <item + android:id="@+id/action_import_export" + android:icon="@drawable/import_export" + android:orderInCategory="200" + android:title="@string/import_export" + app:showAsAction="ifRoom" /> +</menu> \ No newline at end of file diff --git a/app/src/main/res/menu/menu_edit.xml b/app/src/main/res/menu/menu_edit.xml new file mode 100644 index 0000000000000000000000000000000000000000..087730b6f02ecfee21515f44fa35e88d0d5b3480 --- /dev/null +++ b/app/src/main/res/menu/menu_edit.xml @@ -0,0 +1,10 @@ +<?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_save" + android:title="@string/editor_save" + android:icon="@drawable/done" + app:showAsAction="always" /> +</menu> \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000000000000000000000000000000000..7353dbd1fd82487df2d06121f85f7994728f1070 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_background"/> + <foreground android:drawable="@drawable/ic_launcher_foreground"/> +</adaptive-icon> \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000000000000000000000000000000000..7353dbd1fd82487df2d06121f85f7994728f1070 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_background"/> + <foreground android:drawable="@drawable/ic_launcher_foreground"/> +</adaptive-icon> \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..e8e3bcdd3c16765260943f70f7c903042a08decd Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..3d314dd6e6ba0267a866a782fd94fbf949cd9675 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..bf26b03507e14cfd29ca283c4c25f693aa004a46 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..11c5f3dc38ef73c46eaa210a3607fb0c3e46ef0e Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..58b7a3f59ec51076596197a6f874bacd144d0f0f Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..56fe33b76d2362d71ee2a1cd033ceb7acc0a6222 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..64c6a822821f5a26db6cd819fe8e971e0107f84e Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..f4960932f4ae9359de9639647abbdc34b7222737 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..00a02732c126287316f67d77a35b11acebf5c5df Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..1ae389ad605641056d72d48ed664f3f8f5832720 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000000000000000000000000000000000000..05ba2da03bb4a8ce4d183fbef70fbfbab552d918 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="primary">#364045</color> + <color name="primary_dark">#101a1e</color> + <color name="secondary">#db9d3b</color> + <color name="secondary_dark">#a56f00</color> + <color name="black">#FF000000</color> + <color name="white">#FFFFFFFF</color> + <color name="grey">#333333</color> +</resources> \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000000000000000000000000000000000000..b089334799c0704ac23d7197a9ceaef4b8210d44 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,3 @@ +<resources> + <dimen name="fab_margin">16dp</dimen> +</resources> \ No newline at end of file diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..38f01833386165f9c5862ef5c5869caac9592ae3 --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="ic_launcher_background">#DB9D3B</color> +</resources> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..a52f96c79b2fae6e394d7fb96a4767ed045d4d21 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,17 @@ +<resources> + <string name="app_name">Stuff</string> + <string name="container_pick_here">HERE</string> + <string name="container_view_info">info</string> + <string name="editor_save">save</string> + <string name="stuff_not_empty">Stuff ‘%s’ is not empty</string> + <string name="container_must_not_be_empty">Container must not be empty</string> + <string name="name_must_not_be_empty">Name must not be empty</string> + <string name="divider_container">Container</string> + <string name="edit_choose_container">Choose</string> + <string name="edit_description">Description</string> + <string name="edit_name">Name</string> + <string name="no_container">no container</string> + <string name="add_stuff">Add stuff</string> + <string name="edit_stuff">Edit ‘%s’</string> + <string name="import_export">import/export</string> +</resources> \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000000000000000000000000000000000000..ebbf2144d45b02e0b2cc1992d9731bda3b415f33 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,29 @@ +<resources xmlns:tools="http://schemas.android.com/tools"> + <!-- Base application theme. --> + <style name="Theme.Stuff" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> + <!-- Primary brand color. --> + <item name="colorPrimary">@color/primary</item> + <item name="colorPrimaryVariant">@color/primary_dark</item> + <item name="colorOnPrimary">@color/white</item> + <!-- Secondary brand color. --> + <item name="colorSecondary">@color/secondary</item> + <item name="colorSecondaryVariant">@color/secondary_dark</item> + <item name="colorOnSecondary">@color/black</item> + <!-- Status bar color. --> + <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> + <!-- Customize your theme here. --> + </style> + + <style name="Theme.Stuff.BottomSheetDialog" parent="Theme.MaterialComponents.BottomSheetDialog"> + <item name="android:background">@color/grey</item> + </style> + + <style name="Theme.Stuff.NoActionBar"> + <item name="windowActionBar">false</item> + <item name="windowNoTitle">true</item> + </style> + + <style name="Theme.Stuff.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> + + <style name="Theme.Stuff.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> +</resources> \ No newline at end of file diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml new file mode 100644 index 0000000000000000000000000000000000000000..8c42a7637f1b6adf5a169de044b1f8858e8a514d --- /dev/null +++ b/app/src/main/res/values-land/dimens.xml @@ -0,0 +1,3 @@ +<resources> + <dimen name="fab_margin">48dp</dimen> +</resources> \ No newline at end of file diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000000000000000000000000000000000000..d73661be0a70af4be1008a935fbac3c7366d1774 --- /dev/null +++ b/app/src/main/res/values-night/themes.xml @@ -0,0 +1,19 @@ +<resources xmlns:tools="http://schemas.android.com/tools"> + <!-- Base application theme. --> + <style name="Theme.Stuff" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> + <!-- Primary brand color. --> + <item name="colorPrimary">@color/primary</item> + <item name="colorPrimaryVariant">@color/primary_dark</item> + <item name="colorOnPrimary">@color/white</item> + <!-- Secondary brand color. --> + <item name="colorSecondary">@color/secondary</item> + <item name="colorSecondaryVariant">@color/secondary_dark</item> + <item name="colorOnSecondary">@color/black</item> + <!-- Status bar color. --> + <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> + <!-- Customize your theme here. --> + </style> + <style name="Theme.Stuff.BottomSheetDialog" parent="Theme.MaterialComponents.BottomSheetDialog"> + <item name="android:background">@color/grey</item> + </style> +</resources> \ No newline at end of file diff --git a/app/src/main/res/values-w1240dp/dimens.xml b/app/src/main/res/values-w1240dp/dimens.xml new file mode 100644 index 0000000000000000000000000000000000000000..3ee9dabb2e6fce26ca9f30806f341a28ca4c8184 --- /dev/null +++ b/app/src/main/res/values-w1240dp/dimens.xml @@ -0,0 +1,3 @@ +<resources> + <dimen name="fab_margin">200dp</dimen> +</resources> \ No newline at end of file diff --git a/app/src/main/res/values-w600dp/dimens.xml b/app/src/main/res/values-w600dp/dimens.xml new file mode 100644 index 0000000000000000000000000000000000000000..8c42a7637f1b6adf5a169de044b1f8858e8a514d --- /dev/null +++ b/app/src/main/res/values-w600dp/dimens.xml @@ -0,0 +1,3 @@ +<resources> + <dimen name="fab_margin">48dp</dimen> +</resources> \ No newline at end of file diff --git a/app/src/test/java/xyz/apiote/stuff/ExampleUnitTest.kt b/app/src/test/java/xyz/apiote/stuff/ExampleUnitTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..feacd06411d95f953a8ea72826e7882491a0b784 --- /dev/null +++ b/app/src/test/java/xyz/apiote/stuff/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package xyz.apiote.stuff + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..abdee4cac40f87a6782608735007ee65188ef594 --- /dev/null +++ b/build.gradle @@ -0,0 +1,18 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + repositories { + google() + mavenCentral() + } + dependencies { + classpath "com.android.tools.build:gradle:7.0.0" + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..1be44757cac72e37438d0c7bafc483d36acf6231 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Aug 28 10:06:53 GMT 2021 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000000000000000000000000000000000000..98bed167dc90ffee72b7affb37a659966b1bd114 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,21 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official \ No newline at end of file diff --git a/gradlew b/gradlew new file mode 100755 index 0000000000000000000000000000000000000000..4f906e0c811fc9e230eb44819f509cd0627f2600 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000000000000000000000000000000000000..107acd32c4e687021ef32db511e8a206129b88ec --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000000000000000000000000000000000000..7137c5f9e7d6acba81f1825f02b506ec4799aa5f --- /dev/null +++ b/settings.gradle @@ -0,0 +1,11 @@ +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + jcenter() // Warning: this repository is going to shut down soon + } +} +rootProject.name = "Stuff" +include ':app' +include ':bare'