From 3c8a8522d8d0a1f6aaf28fae0ef590fdf0719d8d Mon Sep 17 00:00:00 2001 From: dadada Date: Sat, 7 Nov 2020 20:39:23 +0100 Subject: [PATCH] Initial commit --- .gitignore | 16 ++ .idea/.gitignore | 3 + .idea/codeStyles/Project.xml | 139 +++++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/compiler.xml | 6 + .idea/gradle.xml | 23 +++ .idea/jarRepositories.xml | 25 +++ .idea/misc.xml | 9 + .idea/vcs.xml | 6 + LICENSE | 192 ++++++++++++++++++ app/.gitignore | 1 + app/build.gradle | 60 ++++++ app/proguard-rules.pro | 21 ++ .../dadada/uuidgen/ExampleInstrumentedTest.kt | 24 +++ app/src/main/AndroidManifest.xml | 25 +++ app/src/main/ic_launcher-playstore.png | Bin 0 -> 13360 bytes .../main/java/li/dadada/uuidgen/UuidGen.kt | 19 ++ .../li/dadada/uuidgen/model/AppDatabase.kt | 9 + .../main/java/li/dadada/uuidgen/model/Uuid.kt | 32 +++ .../java/li/dadada/uuidgen/model/UuidDao.kt | 19 ++ .../java/li/dadada/uuidgen/ui/MainActivity.kt | 37 ++++ .../li/dadada/uuidgen/ui/UuidGenFragment.kt | 52 +++++ .../li/dadada/uuidgen/ui/UuidListFragment.kt | 58 ++++++ .../dadada/uuidgen/viewmodel/ClipBoardUtil.kt | 16 ++ .../uuidgen/viewmodel/OnUuidClickListener.kt | 8 + .../dadada/uuidgen/viewmodel/UuidAdapter.kt | 56 +++++ .../dadada/uuidgen/viewmodel/UuidViewModel.kt | 45 ++++ .../drawable-v24/ic_launcher_foreground.xml | 31 +++ .../res/drawable/ic_baseline_history_24.xml | 10 + .../res/drawable/ic_launcher_background.xml | 170 ++++++++++++++++ .../res/drawable/ic_launcher_foreground.xml | 31 +++ app/src/main/res/drawable/uuid_selector.xml | 7 + app/src/main/res/drawable/uuidgen.xml | 16 ++ app/src/main/res/layout/activity_main.xml | 25 +++ app/src/main/res/layout/content_main.xml | 19 ++ app/src/main/res/layout/uuid_gen_fragment.xml | 25 +++ app/src/main/res/layout/uuid_item.xml | 36 ++++ .../main/res/layout/uuid_list_fragment.xml | 25 +++ app/src/main/res/menu/menu_main.xml | 11 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1530 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 3438 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1120 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2224 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2294 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 5071 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3290 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 7768 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 4708 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 11130 bytes app/src/main/res/navigation/nav_graph.xml | 22 ++ app/src/main/res/values-night/themes.xml | 16 ++ app/src/main/res/values/colors.xml | 10 + app/src/main/res/values/dimens.xml | 3 + .../res/values/ic_launcher_background.xml | 4 + app/src/main/res/values/strings.xml | 8 + app/src/main/res/values/themes.xml | 25 +++ .../java/li/dadada/uuidgen/ExampleUnitTest.kt | 17 ++ build.gradle | 28 +++ gradle.properties | 21 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 ++++++++++++++++ gradlew.bat | 84 ++++++++ settings.gradle | 2 + uuidgen_logo.svg | 84 ++++++++ 67 files changed, 1824 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/compiler.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml create mode 100644 LICENSE create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/li/dadada/uuidgen/ExampleInstrumentedTest.kt create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/ic_launcher-playstore.png create mode 100644 app/src/main/java/li/dadada/uuidgen/UuidGen.kt create mode 100644 app/src/main/java/li/dadada/uuidgen/model/AppDatabase.kt create mode 100644 app/src/main/java/li/dadada/uuidgen/model/Uuid.kt create mode 100644 app/src/main/java/li/dadada/uuidgen/model/UuidDao.kt create mode 100644 app/src/main/java/li/dadada/uuidgen/ui/MainActivity.kt create mode 100644 app/src/main/java/li/dadada/uuidgen/ui/UuidGenFragment.kt create mode 100644 app/src/main/java/li/dadada/uuidgen/ui/UuidListFragment.kt create mode 100644 app/src/main/java/li/dadada/uuidgen/viewmodel/ClipBoardUtil.kt create mode 100644 app/src/main/java/li/dadada/uuidgen/viewmodel/OnUuidClickListener.kt create mode 100644 app/src/main/java/li/dadada/uuidgen/viewmodel/UuidAdapter.kt create mode 100644 app/src/main/java/li/dadada/uuidgen/viewmodel/UuidViewModel.kt create mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/ic_baseline_history_24.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/uuid_selector.xml create mode 100644 app/src/main/res/drawable/uuidgen.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/layout/content_main.xml create mode 100644 app/src/main/res/layout/uuid_gen_fragment.xml create mode 100644 app/src/main/res/layout/uuid_item.xml create mode 100644 app/src/main/res/layout/uuid_list_fragment.xml create mode 100644 app/src/main/res/menu/menu_main.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/navigation/nav_graph.xml create mode 100644 app/src/main/res/values-night/themes.xml create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/ic_launcher_background.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/themes.xml create mode 100644 app/src/test/java/li/dadada/uuidgen/ExampleUnitTest.kt create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle create mode 100644 uuidgen_logo.svg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..01684f2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +app/release diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..3c7772a --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,139 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..61a9130 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..b617266 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..a5f05cd --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d5d35ec --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ba253e3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,192 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2013-2018 Docker, Inc. + + 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. + diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /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 0000000..fe03a25 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,60 @@ +plugins { + id 'com.android.application' + id 'kotlin-android' + id 'kotlin-kapt' +} + +android { + compileSdkVersion 30 + + defaultConfig { + applicationId "li.dadada.uuidgen" + minSdkVersion 22 + targetSdkVersion 30 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled true + shrinkResources true + debuggable false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + debug { + applicationIdSuffix ".debug" + debuggable true + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } + + buildFeatures { + dataBinding = true + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'androidx.core:core-ktx:1.3.2' + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.2.1' + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1' + implementation 'androidx.navigation:navigation-ui-ktx:2.3.1' + implementation "androidx.room:room-runtime:$room_version" + kapt "androidx.room:room-compiler:$room_version" + implementation "androidx.room:room-ktx:$room_version" + testImplementation "androidx.room:room-testing:$room_version" + testImplementation 'junit:junit:4.13.1' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /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/li/dadada/uuidgen/ExampleInstrumentedTest.kt b/app/src/androidTest/java/li/dadada/uuidgen/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..174f890 --- /dev/null +++ b/app/src/androidTest/java/li/dadada/uuidgen/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package li.dadada.uuidgen + +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("li.dadada.uuidgen", 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 0000000..4e5913c --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + \ 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..716988676c74a314551be1cac298649d29779c61 GIT binary patch literal 13360 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 literal 0 HcmV?d00001 diff --git a/app/src/main/java/li/dadada/uuidgen/UuidGen.kt b/app/src/main/java/li/dadada/uuidgen/UuidGen.kt new file mode 100644 index 0000000..e855cc0 --- /dev/null +++ b/app/src/main/java/li/dadada/uuidgen/UuidGen.kt @@ -0,0 +1,19 @@ +package li.dadada.uuidgen + +import android.app.Application +import androidx.room.Room +import li.dadada.uuidgen.model.AppDatabase +import li.dadada.uuidgen.model.UuidDao + +class UuidGen : Application() { + internal val uuidDao : UuidDao by lazy { + db.uuidDao() + } + + private val db: AppDatabase by lazy { + Room.databaseBuilder( + applicationContext, + AppDatabase::class.java, "uuids" + ).build() + } +} \ No newline at end of file diff --git a/app/src/main/java/li/dadada/uuidgen/model/AppDatabase.kt b/app/src/main/java/li/dadada/uuidgen/model/AppDatabase.kt new file mode 100644 index 0000000..719ec2d --- /dev/null +++ b/app/src/main/java/li/dadada/uuidgen/model/AppDatabase.kt @@ -0,0 +1,9 @@ +package li.dadada.uuidgen.model + +import androidx.room.Database +import androidx.room.RoomDatabase + +@Database(entities = [Uuid::class], version = 1) +abstract class AppDatabase : RoomDatabase() { + abstract fun uuidDao(): UuidDao +} diff --git a/app/src/main/java/li/dadada/uuidgen/model/Uuid.kt b/app/src/main/java/li/dadada/uuidgen/model/Uuid.kt new file mode 100644 index 0000000..397531f --- /dev/null +++ b/app/src/main/java/li/dadada/uuidgen/model/Uuid.kt @@ -0,0 +1,32 @@ +package li.dadada.uuidgen.model + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import java.util.* + +@Entity +data class Uuid( + @PrimaryKey val uuid: String = UUID.randomUUID().toString(), + @ColumnInfo(name = "created") val created: Long = Date().time +) { + override fun toString(): String { + return uuid + } + + override fun equals(other: Any?): Boolean { + return if (other !is Uuid) { + false + } else { + uuid == other.uuid + } + } + + override fun hashCode(): Int { + var result = uuid.hashCode() + result = 31 * result + created.hashCode() + return result + } +} + + diff --git a/app/src/main/java/li/dadada/uuidgen/model/UuidDao.kt b/app/src/main/java/li/dadada/uuidgen/model/UuidDao.kt new file mode 100644 index 0000000..0304333 --- /dev/null +++ b/app/src/main/java/li/dadada/uuidgen/model/UuidDao.kt @@ -0,0 +1,19 @@ +package li.dadada.uuidgen.model + +import androidx.lifecycle.LiveData +import androidx.room.* + +@Dao +interface UuidDao { + @Query("SELECT * FROM `uuid` ORDER BY `created` ASC") + fun getAll(): LiveData> + + @Query("SELECT * FROM `uuid` WHERE `uuid` IS :uuid") + fun get(uuid: String) : List + + @Insert(onConflict = OnConflictStrategy.ABORT) + fun insertAll(vararg uuid: Uuid) + + @Delete + fun delete(user: Uuid) +} diff --git a/app/src/main/java/li/dadada/uuidgen/ui/MainActivity.kt b/app/src/main/java/li/dadada/uuidgen/ui/MainActivity.kt new file mode 100644 index 0000000..ad0154c --- /dev/null +++ b/app/src/main/java/li/dadada/uuidgen/ui/MainActivity.kt @@ -0,0 +1,37 @@ +package li.dadada.uuidgen.ui + +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import androidx.appcompat.app.AppCompatActivity +import androidx.navigation.findNavController +import kotlinx.coroutines.* +import li.dadada.uuidgen.* + + +class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContentView(R.layout.activity_main) + setSupportActionBar(findViewById(R.id.toolbar)) + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + // Inflate the menu; this adds items to the action bar if it is present. + menuInflater.inflate(R.menu.menu_main, menu) + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.action_history -> { + findNavController(R.id.nav_host_fragment) + .navigate(R.id.action_uuid_gen_fragment_to_uuid_list_fragment) + true + } + else -> super.onOptionsItemSelected(item) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/li/dadada/uuidgen/ui/UuidGenFragment.kt b/app/src/main/java/li/dadada/uuidgen/ui/UuidGenFragment.kt new file mode 100644 index 0000000..948fae4 --- /dev/null +++ b/app/src/main/java/li/dadada/uuidgen/ui/UuidGenFragment.kt @@ -0,0 +1,52 @@ +package li.dadada.uuidgen.ui + +import android.content.ClipboardManager +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.databinding.DataBindingUtil +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelProvider +import com.google.android.material.snackbar.Snackbar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.launch +import li.dadada.uuidgen.R +import li.dadada.uuidgen.databinding.UuidGenFragmentBinding +import li.dadada.uuidgen.viewmodel.ClipBoardUtil +import li.dadada.uuidgen.viewmodel.UuidViewModel + + +class UuidGenFragment : Fragment(), CoroutineScope by MainScope() { + + private val viewModel: UuidViewModel by lazy { + ViewModelProvider(this).get(UuidViewModel::class.java) + } + + private lateinit var clipboardManager: ClipboardManager + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + val binding: UuidGenFragmentBinding = + DataBindingUtil.inflate(inflater, R.layout.uuid_gen_fragment, container, false) + clipboardManager = inflater.context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + binding.buttonGen.setOnClickListener { view -> + launch { genUuid(view) } + } + return binding.root + } + + private suspend fun genUuid(view: View) { + val uuid = viewModel.genUuid() + if (uuid != null) { + ClipBoardUtil.copyUuid(uuid, view, clipboardManager) + } else { + Snackbar.make(view, R.string.warn_duplicate_uuid, Snackbar.LENGTH_SHORT) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/li/dadada/uuidgen/ui/UuidListFragment.kt b/app/src/main/java/li/dadada/uuidgen/ui/UuidListFragment.kt new file mode 100644 index 0000000..c23e45d --- /dev/null +++ b/app/src/main/java/li/dadada/uuidgen/ui/UuidListFragment.kt @@ -0,0 +1,58 @@ +package li.dadada.uuidgen.ui + +import android.content.ClipboardManager +import android.content.Context.CLIPBOARD_SERVICE +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.databinding.DataBindingUtil +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import li.dadada.uuidgen.R +import li.dadada.uuidgen.model.Uuid +import li.dadada.uuidgen.viewmodel.UuidAdapter +import li.dadada.uuidgen.viewmodel.UuidViewModel +import li.dadada.uuidgen.databinding.UuidListFragmentBinding +import li.dadada.uuidgen.viewmodel.ClipBoardUtil +import li.dadada.uuidgen.viewmodel.OnUuidClickListener + + +/** + * A simple [Fragment] subclass as the default destination in the navigation. + */ +class UuidListFragment : Fragment() { + private val uuidAdapter = UuidAdapter(object : OnUuidClickListener { + override fun onUuidClicked(view: View, uuid: Uuid): Boolean { + ClipBoardUtil.copyUuid( + uuid, + view, + activity?.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager) + return true + } + }) + + private lateinit var binding : UuidListFragmentBinding + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + binding = DataBindingUtil.inflate(inflater, R.layout.uuid_list_fragment, container, false) + binding.listUuids.apply { + adapter = uuidAdapter + layoutManager = LinearLayoutManager(this@UuidListFragment.context) + } + + return binding.root; + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val viewModel = ViewModelProvider(this).get(UuidViewModel::class.java) + viewModel.uuidList.observe(viewLifecycleOwner, + Observer> { list -> uuidAdapter.submitList(list) }) + } +} \ No newline at end of file diff --git a/app/src/main/java/li/dadada/uuidgen/viewmodel/ClipBoardUtil.kt b/app/src/main/java/li/dadada/uuidgen/viewmodel/ClipBoardUtil.kt new file mode 100644 index 0000000..adb0bef --- /dev/null +++ b/app/src/main/java/li/dadada/uuidgen/viewmodel/ClipBoardUtil.kt @@ -0,0 +1,16 @@ +package li.dadada.uuidgen.viewmodel + +import android.content.ClipData +import android.content.ClipboardManager +import android.view.View +import com.google.android.material.snackbar.BaseTransientBottomBar +import com.google.android.material.snackbar.Snackbar +import li.dadada.uuidgen.model.Uuid + +object ClipBoardUtil { + fun copyUuid(uuid: Uuid, view: View, clipboardManager: ClipboardManager) { + clipboardManager.setPrimaryClip(ClipData.newPlainText("uuid", uuid.uuid)) + Snackbar.make(view, "Copied $uuid to clipboard", BaseTransientBottomBar.LENGTH_SHORT) + .show() + } +} \ No newline at end of file diff --git a/app/src/main/java/li/dadada/uuidgen/viewmodel/OnUuidClickListener.kt b/app/src/main/java/li/dadada/uuidgen/viewmodel/OnUuidClickListener.kt new file mode 100644 index 0000000..e174164 --- /dev/null +++ b/app/src/main/java/li/dadada/uuidgen/viewmodel/OnUuidClickListener.kt @@ -0,0 +1,8 @@ +package li.dadada.uuidgen.viewmodel + +import android.view.View +import li.dadada.uuidgen.model.Uuid + +interface OnUuidClickListener { + fun onUuidClicked(view: View, uuid: Uuid) : Boolean +} \ No newline at end of file diff --git a/app/src/main/java/li/dadada/uuidgen/viewmodel/UuidAdapter.kt b/app/src/main/java/li/dadada/uuidgen/viewmodel/UuidAdapter.kt new file mode 100644 index 0000000..0232a7f --- /dev/null +++ b/app/src/main/java/li/dadada/uuidgen/viewmodel/UuidAdapter.kt @@ -0,0 +1,56 @@ +package li.dadada.uuidgen.viewmodel + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.databinding.DataBindingUtil +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import li.dadada.uuidgen.R +import li.dadada.uuidgen.databinding.UuidItemBinding +import li.dadada.uuidgen.model.Uuid + + +class UuidAdapter(private val controller: OnUuidClickListener) : ListAdapter(UuidDiffCallback()) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UuidViewHolder { + return from(parent, controller) + } + + override fun onBindViewHolder(holder: UuidViewHolder, position: Int) { + val item = getItem(position) + holder.bind(item) + } + + class UuidViewHolder( + private val binding: UuidItemBinding, + private val listener: OnUuidClickListener + ) : RecyclerView.ViewHolder(binding.root) { + fun bind(item: Uuid) { + binding.uuid = item + binding.listener = listener + binding.executePendingBindings() + } + } + + companion object { + fun from(parent: ViewGroup, listener: OnUuidClickListener) : UuidViewHolder { + val binding : UuidItemBinding = DataBindingUtil.inflate( + LayoutInflater.from(parent.context), + R.layout.uuid_item, + parent, false + ) + return UuidViewHolder(binding, listener) + } + } +} + +class UuidDiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: Uuid, newItem: Uuid): Boolean { + return oldItem == newItem + } + + override fun areContentsTheSame(oldItem: Uuid, newItem: Uuid): Boolean { + return oldItem == newItem + } +} \ No newline at end of file diff --git a/app/src/main/java/li/dadada/uuidgen/viewmodel/UuidViewModel.kt b/app/src/main/java/li/dadada/uuidgen/viewmodel/UuidViewModel.kt new file mode 100644 index 0000000..a9b71f4 --- /dev/null +++ b/app/src/main/java/li/dadada/uuidgen/viewmodel/UuidViewModel.kt @@ -0,0 +1,45 @@ +package li.dadada.uuidgen.viewmodel + +import android.app.Application +import android.content.ClipData +import android.content.ClipboardManager +import android.view.View +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.SavedStateHandle +import com.google.android.material.snackbar.BaseTransientBottomBar +import com.google.android.material.snackbar.Snackbar +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import li.dadada.uuidgen.UuidGen +import li.dadada.uuidgen.model.Uuid +import li.dadada.uuidgen.model.UuidDao + + +internal class UuidViewModel(application: Application, + savedStateHandle: SavedStateHandle +) : AndroidViewModel(application) { + + private val uuidDao : UuidDao by lazy { + (application as UuidGen).uuidDao + } + + val uuidList = uuidDao.getAll() + + suspend fun genUuid() : Uuid? { + return genUuid(uuidDao) + } + + companion object { + private suspend fun genUuid(uuidDao: UuidDao) : Uuid? = withContext(Dispatchers.IO) { + val uuid = Uuid() + with(uuidDao) { + if (get(uuid.uuid).isEmpty()) { + insertAll(uuid) + uuid + } else { + null + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1d1edde --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_baseline_history_24.xml b/app/src/main/res/drawable/ic_baseline_history_24.xml new file mode 100644 index 0000000..9bc1fc3 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_history_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 0000000..f815f44 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/uuid_selector.xml b/app/src/main/res/drawable/uuid_selector.xml new file mode 100644 index 0000000..feb9be5 --- /dev/null +++ b/app/src/main/res/drawable/uuid_selector.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/src/main/res/drawable/uuidgen.xml b/app/src/main/res/drawable/uuidgen.xml new file mode 100644 index 0000000..f3ae47c --- /dev/null +++ b/app/src/main/res/drawable/uuidgen.xml @@ -0,0 +1,16 @@ + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..342aa5c --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml new file mode 100644 index 0000000..5474c02 --- /dev/null +++ b/app/src/main/res/layout/content_main.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/uuid_gen_fragment.xml b/app/src/main/res/layout/uuid_gen_fragment.xml new file mode 100644 index 0000000..79a2704 --- /dev/null +++ b/app/src/main/res/layout/uuid_gen_fragment.xml @@ -0,0 +1,25 @@ + + + + + + + + + +