diff --git a/.gitignore b/.gitignore index 14ed79fa..480485ba 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ build/ # Local configuration local.properties -gradle.properties # IntelliJ *.iml diff --git a/README.md b/README.md index fd767ee9..227b2e01 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,19 @@ -# Badge Magic + -Magically Create Symbols and Text on LED Name Badges using Bluetooth +# Badge Magic [![Build Status](https://travis-ci.org/fossasia/badge-magic-android.svg?branch=development)](https://travis-ci.org/fossasia/badge-magic-android) [![Join the chat at https://gitter.im/fossasia/badge-magic](https://badges.gitter.im/fossasia/badge-magic.svg)](https://gitter.im/fossasia/badge-magic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Build Status](https://travis-ci.org/fossasia/badge-magic-android.svg?branch=development)](https://travis-ci.org/fossasia/badge-magic-android) -[![Join the chat at https://gitter.im/fossasia/badge-magic](https://badges.gitter.im/fossasia/badge-magic.svg)](https://gitter.im/fossasia/badge-magic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +**Magically Create Symbols and Text on LED Name Badges using Bluetooth** The Badge Magic Android app lets you create scrolling symbols and text on LED name badges through Bluetooth. The app provides options to portray names, clipart and simple animations on LED badges. For the data transfer from the smartphone to the LED badge we use Bluetooth. The project is based on the work of [Nilhcem](https://github.com/Nilhcem). - + + + + + + Get it on F-Droid + +
## Download diff --git a/app/build.gradle b/app/build.gradle index 4901386e..0120192a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { applicationId 'org.fossasia.badgemagic' minSdkVersion versions.minSdk targetSdkVersion versions.targetSdk - versionCode 2 - versionName '1.0.1' + versionCode 3 + versionName '1.1.0' vectorDrawables.useSupportLibrary = true } @@ -35,6 +35,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + dataBinding.enabled= true } spotless { @@ -47,6 +48,8 @@ spotless { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin_version}" + kapt "androidx.databinding:compiler:3.2.0-alpha11" + //Moshi implementation "com.squareup.moshi:moshi-kotlin:${versions.moshi_version}" kapt "com.squareup.moshi:moshi-kotlin-codegen:${versions.moshi_version}" @@ -55,16 +58,16 @@ dependencies { implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.16' //Android X Libraries - implementation 'androidx.appcompat:appcompat:1.1.0-alpha05' - implementation 'androidx.recyclerview:recyclerview:1.1.0-alpha05' + implementation 'androidx.appcompat:appcompat:1.1.0-beta01' + implementation 'androidx.recyclerview:recyclerview:1.1.0-alpha06' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - //First Party Lifecycle Library - implementation "androidx.lifecycle:lifecycle-extensions:${versions.lifecycle}" - kapt "androidx.lifecycle:lifecycle-compiler:${versions.lifecycle}" + + // Koin AndroidX + implementation "org.koin:koin-androidx-viewmodel:${versions.koin_version}" //Material Design - implementation 'com.google.android.material:material:1.1.0-alpha06' + implementation 'com.google.android.material:material:1.1.0-alpha07' //Timber implementation 'com.jakewharton.timber:timber:4.7.1' @@ -74,7 +77,7 @@ dependencies { implementation 'androidx.legacy:legacy-support-v4:1.0.0' testImplementation 'junit:junit:4.12' testImplementation 'com.nhaarman:mockito-kotlin-kt1.1:1.5.0' - testImplementation 'org.amshove.kluent:kluent:1.49' + testImplementation 'org.amshove.kluent:kluent:1.50' // Leak Canary debugImplementation "com.squareup.leakcanary:leakcanary-android:${versions.leak_canary}" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d022d970..8da73161 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ + @@ -15,15 +16,17 @@ + + @@ -45,6 +48,7 @@ android:name="android.app.shortcuts" android:resource="@xml/shortcuts" /> + { - card.background = resourceHelper.getDrawable(R.color.colorAccent) - title.setTextColor(resourceHelper.getColor(android.R.color.white) - ?: Color.parseColor("#000000")) - image.setColorFilter(resourceHelper.getColor(android.R.color.white) - ?: Color.parseColor("#000000")) + card.background = itemView.context.resources.getDrawable(R.color.colorAccent) + title.setTextColor(itemView.context.resources.getColor(android.R.color.white)) + image.setColorFilter(itemView.context.resources.getColor(android.R.color.white)) } false -> { - card.background = resourceHelper.getDrawable(android.R.color.transparent) - title.setTextColor(resourceHelper.getColor(android.R.color.black) - ?: Color.parseColor("#00000000")) - image.setColorFilter(resourceHelper.getColor(android.R.color.black) - ?: Color.parseColor("#00000000")) + card.background = itemView.context.resources.getDrawable(android.R.color.transparent) + title.setTextColor(itemView.context.resources.getColor(android.R.color.black)) + image.setColorFilter(itemView.context.resources.getColor(android.R.color.black)) } } diff --git a/app/src/main/java/org/fossasia/badgemagic/bindings/DrawViewBindings.kt b/app/src/main/java/org/fossasia/badgemagic/bindings/DrawViewBindings.kt new file mode 100644 index 00000000..22311ddd --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/bindings/DrawViewBindings.kt @@ -0,0 +1,29 @@ +package org.fossasia.badgemagic.bindings + +import android.widget.ImageView +import androidx.databinding.BindingAdapter +import androidx.databinding.ObservableBoolean +import androidx.databinding.ObservableField +import org.fossasia.badgemagic.R +import org.fossasia.badgemagic.data.draw_layout.DrawMode +import org.fossasia.badgemagic.ui.custom.DrawBadgeLayout + +@BindingAdapter("drawState") +fun setBadgeDrawState(badge: DrawBadgeLayout, drawModeState: ObservableField) { + drawModeState.get()?.let { badge.changeDrawState(it) } +} + +@BindingAdapter("resetState") +fun resetDrawBadge(badge: DrawBadgeLayout, isEnabled: ObservableBoolean) { + badge.resetCheckList() +} + +@BindingAdapter("changeColor") +fun changeColorState(imageView: ImageView, isEnabled: ObservableBoolean) { + imageView.setColorFilter( + if (isEnabled.get()) + imageView.context.resources.getColor(R.color.colorAccent) + else + imageView.context.resources.getColor(android.R.color.black) + ) +} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/bindings/SettingsViewBindings.kt b/app/src/main/java/org/fossasia/badgemagic/bindings/SettingsViewBindings.kt new file mode 100644 index 00000000..4a06dea9 --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/bindings/SettingsViewBindings.kt @@ -0,0 +1,23 @@ +package org.fossasia.badgemagic.bindings + +import android.view.View +import android.widget.AdapterView +import android.widget.ArrayAdapter +import androidx.appcompat.widget.AppCompatSpinner +import androidx.databinding.BindingAdapter +import org.fossasia.badgemagic.viewmodels.SettingsViewModel + +@BindingAdapter("createAdapterFrom") +fun setSpinnerAdapter(spinner: AppCompatSpinner, viewModel: SettingsViewModel) { + val list: MutableList = viewModel.languageList.get() ?: mutableListOf() + spinner.adapter = ArrayAdapter(spinner.context, android.R.layout.simple_spinner_dropdown_item, list) + spinner.setSelection(viewModel.getSelectedSpinnerLanguage(), false) + spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onNothingSelected(parent: AdapterView<*>?) { + } + + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + viewModel.setSelectedSpinnerLangauge(position) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/data/Language.kt b/app/src/main/java/org/fossasia/badgemagic/data/Language.kt new file mode 100644 index 00000000..5a8548a5 --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/data/Language.kt @@ -0,0 +1,8 @@ +package org.fossasia.badgemagic.data + +import java.util.Locale + +enum class Language(val locale: Locale) { + ENGLISH(Locale.ENGLISH), + CHINESE(Locale.CHINA), +} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/data/clipart/ClipArtContainer.kt b/app/src/main/java/org/fossasia/badgemagic/data/clipart/ClipArtContainer.kt deleted file mode 100644 index 07d59c5d..00000000 --- a/app/src/main/java/org/fossasia/badgemagic/data/clipart/ClipArtContainer.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.fossasia.badgemagic.data.clipart - -class ClipArtContainer private constructor() { - - var clipArts = ClipArtDAO() - private set - - companion object { - @Volatile - private var instance: ClipArtContainer? = null - - fun getInstance() = - instance ?: synchronized(this) { - instance - ?: ClipArtContainer().also { instance = it } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/data/clipart/ClipArtRepository.kt b/app/src/main/java/org/fossasia/badgemagic/data/clipart/ClipArtRepository.kt deleted file mode 100644 index a0d7fc2f..00000000 --- a/app/src/main/java/org/fossasia/badgemagic/data/clipart/ClipArtRepository.kt +++ /dev/null @@ -1,17 +0,0 @@ -package org.fossasia.badgemagic.data.clipart - -class ClipArtRepository private constructor(private val clipArts: ClipArtDAO) { - - fun getClipArts() = clipArts.getClipArts() - - companion object { - @Volatile - private var instance: ClipArtRepository? = null - - fun getInstance(filesData: ClipArtDAO) = - instance ?: synchronized(this) { - instance - ?: ClipArtRepository(filesData).also { instance = it } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/data/device/bluetooth/GattClient.kt b/app/src/main/java/org/fossasia/badgemagic/data/device/bluetooth/GattClient.kt index 62240ef5..b5701bc0 100644 --- a/app/src/main/java/org/fossasia/badgemagic/data/device/bluetooth/GattClient.kt +++ b/app/src/main/java/org/fossasia/badgemagic/data/device/bluetooth/GattClient.kt @@ -68,7 +68,8 @@ class GattClient { val characteristic = bluetoothGatt?.getService(SERVICE_UUID)?.getCharacteristic(CHARACTERISTIC_UUID) characteristic?.value = data - bluetoothGatt?.writeCharacteristic(characteristic) + if (characteristic != null) + bluetoothGatt?.writeCharacteristic(characteristic) } } diff --git a/app/src/main/java/org/fossasia/badgemagic/data/draw_layout/DrawMode.kt b/app/src/main/java/org/fossasia/badgemagic/data/draw_layout/DrawMode.kt new file mode 100644 index 00000000..ffac418c --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/data/draw_layout/DrawMode.kt @@ -0,0 +1,7 @@ +package org.fossasia.badgemagic.data.draw_layout + +enum class DrawMode(val mode: Int) { + NOTHING(0), + DRAW(1), + ERASE(2) +} diff --git a/app/src/main/java/org/fossasia/badgemagic/data/saved_files/FilesContainer.kt b/app/src/main/java/org/fossasia/badgemagic/data/saved_files/FilesContainer.kt deleted file mode 100644 index 86b8a4ed..00000000 --- a/app/src/main/java/org/fossasia/badgemagic/data/saved_files/FilesContainer.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.fossasia.badgemagic.data.saved_files - -class FilesContainer private constructor() { - - var filesData = FilesDAO() - private set - - companion object { - @Volatile - private var instance: FilesContainer? = null - - fun getInstance() = - instance ?: synchronized(this) { - instance - ?: FilesContainer().also { instance = it } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/data/saved_files/FilesRepository.kt b/app/src/main/java/org/fossasia/badgemagic/data/saved_files/FilesRepository.kt deleted file mode 100644 index 7d545af8..00000000 --- a/app/src/main/java/org/fossasia/badgemagic/data/saved_files/FilesRepository.kt +++ /dev/null @@ -1,27 +0,0 @@ -package org.fossasia.badgemagic.data.saved_files - -class FilesRepository private constructor(private val filesData: FilesDAO) { - - fun deleteFile(fileName: String) = filesData.deleteFile(fileName) - - fun getFiles() = filesData.getFiles() - - fun update() = filesData.update() - - fun saveFile(filename: String, json: String) = filesData.saveFile(filename, json) - - fun checkIfFilePresent(fileName: String): Boolean = filesData.checkIfFilePresent(fileName) - - fun getAbsPath(fileName: String): String? = filesData.getAbsPath(fileName) - - companion object { - @Volatile - private var instance: FilesRepository? = null - - fun getInstance(filesData: FilesDAO) = - instance ?: synchronized(this) { - instance - ?: FilesRepository(filesData).also { instance = it } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/data/clipart/ClipArtDAO.kt b/app/src/main/java/org/fossasia/badgemagic/database/ClipArtService.kt similarity index 89% rename from app/src/main/java/org/fossasia/badgemagic/data/clipart/ClipArtDAO.kt rename to app/src/main/java/org/fossasia/badgemagic/database/ClipArtService.kt index 636cd317..69d4f7d7 100644 --- a/app/src/main/java/org/fossasia/badgemagic/data/clipart/ClipArtDAO.kt +++ b/app/src/main/java/org/fossasia/badgemagic/database/ClipArtService.kt @@ -1,4 +1,4 @@ -package org.fossasia.badgemagic.data.clipart +package org.fossasia.badgemagic.database import android.graphics.drawable.Drawable import android.util.SparseArray @@ -6,10 +6,12 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import org.fossasia.badgemagic.R import org.fossasia.badgemagic.util.Resource +import org.koin.core.KoinComponent +import org.koin.core.inject -class ClipArtDAO { +class ClipArtService : KoinComponent { private val clipArts = MutableLiveData>() - private val resourceHelper = Resource() + private val resourceHelper: Resource by inject() init { val tempSparseArray = SparseArray() diff --git a/app/src/main/java/org/fossasia/badgemagic/data/saved_files/FilesDAO.kt b/app/src/main/java/org/fossasia/badgemagic/database/StorageFilesService.kt similarity index 92% rename from app/src/main/java/org/fossasia/badgemagic/data/saved_files/FilesDAO.kt rename to app/src/main/java/org/fossasia/badgemagic/database/StorageFilesService.kt index 6f373f8e..18b9841b 100644 --- a/app/src/main/java/org/fossasia/badgemagic/data/saved_files/FilesDAO.kt +++ b/app/src/main/java/org/fossasia/badgemagic/database/StorageFilesService.kt @@ -1,11 +1,11 @@ -package org.fossasia.badgemagic.data.saved_files +package org.fossasia.badgemagic.database import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import org.fossasia.badgemagic.data.fragments.ConfigInfo import org.fossasia.badgemagic.util.StorageUtils -class FilesDAO { +class StorageFilesService { private val files = MutableLiveData>() init { diff --git a/app/src/main/java/org/fossasia/badgemagic/di/Modules.kt b/app/src/main/java/org/fossasia/badgemagic/di/Modules.kt new file mode 100644 index 00000000..5f9d200e --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/di/Modules.kt @@ -0,0 +1,30 @@ +package org.fossasia.badgemagic.di + +import org.fossasia.badgemagic.database.ClipArtService +import org.fossasia.badgemagic.database.StorageFilesService +import org.fossasia.badgemagic.util.PreferenceUtils +import org.fossasia.badgemagic.util.Resource +import org.fossasia.badgemagic.viewmodels.FilesViewModel +import org.fossasia.badgemagic.viewmodels.TextArtViewModel +import org.fossasia.badgemagic.viewmodels.SettingsViewModel +import org.fossasia.badgemagic.viewmodels.DrawViewModel +import org.koin.android.ext.koin.androidContext +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.dsl.module + +val viewModelModules = module { + viewModel { TextArtViewModel(get(), get()) } + viewModel { FilesViewModel(get()) } + viewModel { SettingsViewModel(get()) } + viewModel { DrawViewModel() } +} + +val singletonModules = module { + single { ClipArtService() } + single { StorageFilesService() } +} + +val utilModules = module { + single { PreferenceUtils(androidContext()) } + single { Resource(androidContext()) } +} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/App.kt b/app/src/main/java/org/fossasia/badgemagic/ui/App.kt deleted file mode 100644 index e3c15882..00000000 --- a/app/src/main/java/org/fossasia/badgemagic/ui/App.kt +++ /dev/null @@ -1,27 +0,0 @@ -package org.fossasia.badgemagic.ui - -import android.app.Application -import android.content.Context -import org.fossasia.badgemagic.BuildConfig -import timber.log.Timber - -class App : Application() { - - companion object { - @JvmStatic - var appContext: Context? = null - private set - } - - override fun onCreate() { - super.onCreate() - appContext = applicationContext - initLogger() - } - - private fun initLogger() { - if (BuildConfig.DEBUG) { - Timber.plant(Timber.DebugTree()) - } - } -} diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/AppViewModel.kt b/app/src/main/java/org/fossasia/badgemagic/ui/AppViewModel.kt deleted file mode 100644 index 58283b3a..00000000 --- a/app/src/main/java/org/fossasia/badgemagic/ui/AppViewModel.kt +++ /dev/null @@ -1,16 +0,0 @@ -package org.fossasia.badgemagic.ui - -import androidx.lifecycle.ViewModel -import org.fossasia.badgemagic.data.saved_files.FilesRepository - -class AppViewModel(private val configRepo: FilesRepository) : - ViewModel() { - - fun getFiles() = configRepo.getFiles() - - fun deleteFile(fileName: String) = configRepo.deleteFile(fileName) - - fun updateList() = configRepo.update() - - fun getAbsPath(fileName: String): String? = configRepo.getAbsPath(fileName) -} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/AppViewModelProviderFactory.kt b/app/src/main/java/org/fossasia/badgemagic/ui/AppViewModelProviderFactory.kt deleted file mode 100644 index feeea5d8..00000000 --- a/app/src/main/java/org/fossasia/badgemagic/ui/AppViewModelProviderFactory.kt +++ /dev/null @@ -1,13 +0,0 @@ -package org.fossasia.badgemagic.ui - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import org.fossasia.badgemagic.data.saved_files.FilesRepository - -class AppViewModelProviderFactory(private val configRepository: FilesRepository) : - ViewModelProvider.NewInstanceFactory() { - - override fun create(modelClass: Class): T { - return AppViewModel(configRepository) as T - } -} diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/DrawActivity.kt b/app/src/main/java/org/fossasia/badgemagic/ui/DrawActivity.kt new file mode 100644 index 00000000..2cc5bd16 --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/ui/DrawActivity.kt @@ -0,0 +1,20 @@ +package org.fossasia.badgemagic.ui + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.databinding.DataBindingUtil +import org.fossasia.badgemagic.R +import org.fossasia.badgemagic.databinding.ActivityDrawBinding +import org.fossasia.badgemagic.viewmodels.DrawViewModel +import org.koin.androidx.viewmodel.ext.android.viewModel + +class DrawActivity : AppCompatActivity() { + + private val viewModel by viewModel() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val activityDrawBinding = DataBindingUtil.setContentView(this, R.layout.activity_draw) + activityDrawBinding.viewModel = viewModel + } +} diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/drawer/DrawerActivity.kt b/app/src/main/java/org/fossasia/badgemagic/ui/DrawerActivity.kt similarity index 72% rename from app/src/main/java/org/fossasia/badgemagic/ui/drawer/DrawerActivity.kt rename to app/src/main/java/org/fossasia/badgemagic/ui/DrawerActivity.kt index 9b63fd71..8962a3c5 100644 --- a/app/src/main/java/org/fossasia/badgemagic/ui/drawer/DrawerActivity.kt +++ b/app/src/main/java/org/fossasia/badgemagic/ui/DrawerActivity.kt @@ -1,9 +1,8 @@ -package org.fossasia.badgemagic.ui.drawer +package org.fossasia.badgemagic.ui import android.Manifest import android.app.Activity import android.app.AlertDialog -import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothManager import android.content.Context import android.content.DialogInterface @@ -17,27 +16,27 @@ import androidx.appcompat.app.ActionBarDrawerToggle import android.view.MenuItem import androidx.drawerlayout.widget.DrawerLayout import com.google.android.material.navigation.NavigationView -import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.widget.Toolbar import android.view.Menu import android.view.View import android.widget.Toast import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat -import androidx.lifecycle.ViewModelProviders +import kotlinx.android.synthetic.main.activity_drawer.* +import kotlinx.android.synthetic.main.app_bar_drawer.* import org.fossasia.badgemagic.R import org.fossasia.badgemagic.core.android.log.Timber -import org.fossasia.badgemagic.ui.fragments.base.BaseFragment -import org.fossasia.badgemagic.ui.AppViewModel +import org.fossasia.badgemagic.ui.base.BaseFragment +import org.fossasia.badgemagic.viewmodels.FilesViewModel import org.fossasia.badgemagic.ui.fragments.AboutFragment -import org.fossasia.badgemagic.ui.fragments.main_saved.MainSavedFragment -import org.fossasia.badgemagic.ui.fragments.main_textart.MainTextArtFragment -import org.fossasia.badgemagic.util.InjectorUtils +import org.fossasia.badgemagic.ui.fragments.SavedBadgesFragment +import org.fossasia.badgemagic.ui.fragments.SettingsFragment +import org.fossasia.badgemagic.ui.fragments.TextArtFragment +import org.fossasia.badgemagic.ui.base.BaseActivity import org.fossasia.badgemagic.util.SendingUtils import org.fossasia.badgemagic.util.StorageUtils +import org.koin.androidx.viewmodel.ext.android.viewModel -@Suppress("DEPRECATION") -class DrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener { +class DrawerActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener { companion object { private const val PICK_FILE_RESULT_CODE = 2 @@ -48,18 +47,11 @@ class DrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelec private var showMenu: Menu? = null private var drawerCheckedID = R.id.create - private var viewModel: AppViewModel? = null - - private fun inject() { - viewModel = ViewModelProviders.of(this, InjectorUtils.provideFilesViewModelFactory()) - .get(AppViewModel::class.java) - } + private val viewModel by viewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - inject() - setContentView(R.layout.activity_drawer) if (intent.action == Intent.ACTION_VIEW) @@ -71,17 +63,14 @@ class DrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelec } private fun setupDrawerAndToolbar() { - val toolbar: Toolbar = findViewById(R.id.toolbar) setSupportActionBar(toolbar) - val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout) - val navView: NavigationView = findViewById(R.id.nav_view) val toggle = ActionBarDrawerToggle( - this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) - drawerLayout.addDrawerListener(toggle) + this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) + drawer_layout.addDrawerListener(toggle) toggle.syncState() - drawerLayout.addDrawerListener(object : DrawerLayout.DrawerListener { + drawer_layout.addDrawerListener(object : DrawerLayout.DrawerListener { override fun onDrawerStateChanged(newState: Int) { } @@ -91,13 +80,17 @@ class DrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelec override fun onDrawerClosed(drawerView: View) { when (drawerCheckedID) { R.id.create -> { - switchFragment(MainTextArtFragment.newInstance()) + switchFragment(TextArtFragment.newInstance()) showMenu?.setGroupVisible(R.id.saved_group, false) } R.id.saved -> { - switchFragment(MainSavedFragment.newInstance()) + switchFragment(SavedBadgesFragment.newInstance()) showMenu?.setGroupVisible(R.id.saved_group, true) } + R.id.settings -> { + switchFragment(SettingsFragment.newInstance()) + showMenu?.setGroupVisible(R.id.saved_group, false) + } R.id.feedback -> { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/fossasia/badge-magic-android/issues"))) } @@ -115,17 +108,17 @@ class DrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelec } }) - navView.setNavigationItemSelectedListener(this) + nav_view.setNavigationItemSelectedListener(this) when (intent.action) { Intent.ACTION_MAIN, "org.fossasia.badgemagic.createBadge.shortcut" -> { - switchFragment(MainTextArtFragment.newInstance()) + switchFragment(TextArtFragment.newInstance()) showMenu?.setGroupVisible(R.id.saved_group, false) - navView.setCheckedItem(R.id.create) + nav_view.setCheckedItem(R.id.create) } "org.fossasia.badgemagic.savedBadges.shortcut" -> { - switchFragment(MainSavedFragment.newInstance()) + switchFragment(SavedBadgesFragment.newInstance()) showMenu?.setGroupVisible(R.id.saved_group, true) - navView.setCheckedItem(R.id.saved) + nav_view.setCheckedItem(R.id.saved) } } } @@ -174,10 +167,7 @@ class DrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelec } REQUEST_ENABLE_BT -> { this.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED - if (resultCode == Activity.RESULT_CANCELED) { - showAlertDialog(true) - return - } else if (resultCode == Activity.RESULT_OK) { + if (resultCode == Activity.RESULT_OK) { prepareForScan() return } @@ -186,21 +176,6 @@ class DrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelec super.onActivityResult(requestCode, resultCode, data) } - private fun showAlertDialog(bluetoothDialog: Boolean) { - val dialogMessage = if (bluetoothDialog) getString(R.string.enable_bluetooth) else getString(R.string.grant_required_permission) - val builder = AlertDialog.Builder(this) - builder.setIcon(resources.getDrawable(R.drawable.ic_caution)) - builder.setTitle(getString(R.string.permission_required)) - builder.setMessage(dialogMessage) - builder.setPositiveButton("OK") { _, _ -> - prepareForScan() - } - builder.setNegativeButton("CANCEL") { _, _ -> - Toast.makeText(this, R.string.enable_bluetooth, Toast.LENGTH_SHORT).show() - } - builder.create().show() - } - private fun switchFragment(fragment: BaseFragment) { supportFragmentManager.beginTransaction() .replace(R.id.frag_container, fragment) @@ -210,7 +185,6 @@ class DrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelec private fun checkManifestPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { - ensureBluetoothEnabled() Timber.i { "Coarse permission granted" } } else { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_PERMISSION_CODE) @@ -222,9 +196,6 @@ class DrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelec REQUEST_PERMISSION_CODE -> { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { Timber.d { "Required Permission Accepted" } - ensureBluetoothEnabled() - } else { - showAlertDialog(false) } } else -> super.onRequestPermissionsResult(requestCode, permissions, grantResults) @@ -235,17 +206,6 @@ class DrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelec return packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) } - private fun ensureBluetoothEnabled() { - // Ensures Bluetooth is enabled on the device - val btManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager - val btAdapter = btManager.adapter - if (!btAdapter.isEnabled) { - val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) - this.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED - startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT) - } - } - private fun disableBluetooth() { val btManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager val btAdapter = btManager.adapter @@ -257,7 +217,7 @@ class DrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelec private fun saveImportFile(uri: Uri?) { if (StorageUtils.copyFileToDirectory(this, uri)) { Toast.makeText(this, R.string.success_import_json, Toast.LENGTH_SHORT).show() - viewModel?.updateList() + viewModel.updateList() } else Toast.makeText(this, R.string.invalid_import_json, Toast.LENGTH_SHORT).show() } diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/base/BaseActivity.kt b/app/src/main/java/org/fossasia/badgemagic/ui/base/BaseActivity.kt new file mode 100644 index 00000000..5d4ab957 --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/ui/base/BaseActivity.kt @@ -0,0 +1,11 @@ +package org.fossasia.badgemagic.ui.base + +import android.content.Context +import androidx.appcompat.app.AppCompatActivity +import org.fossasia.badgemagic.util.LocaleManager + +abstract class BaseActivity : AppCompatActivity() { + override fun attachBaseContext(base: Context?) { + super.attachBaseContext(LocaleManager.setLocale(base)) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/base/BaseFragment.kt b/app/src/main/java/org/fossasia/badgemagic/ui/base/BaseFragment.kt similarity index 79% rename from app/src/main/java/org/fossasia/badgemagic/ui/fragments/base/BaseFragment.kt rename to app/src/main/java/org/fossasia/badgemagic/ui/base/BaseFragment.kt index baa9b712..6f2a33fb 100644 --- a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/base/BaseFragment.kt +++ b/app/src/main/java/org/fossasia/badgemagic/ui/base/BaseFragment.kt @@ -1,12 +1,9 @@ -package org.fossasia.badgemagic.ui.fragments.base +package org.fossasia.badgemagic.ui.base import androidx.fragment.app.Fragment import org.fossasia.badgemagic.data.device.model.DataToSend open class BaseFragment : Fragment(), BaseFragmentInterface { - override fun inject() { - } - override fun initializePreview() { } @@ -18,5 +15,4 @@ open class BaseFragment : Fragment(), BaseFragmentInterface { interface BaseFragmentInterface { fun getSendData(): DataToSend fun initializePreview() - fun inject() } \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/custom/DrawBadgeLayout.kt b/app/src/main/java/org/fossasia/badgemagic/ui/custom/DrawBadgeLayout.kt new file mode 100644 index 00000000..08d1c642 --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/ui/custom/DrawBadgeLayout.kt @@ -0,0 +1,154 @@ +package org.fossasia.badgemagic.ui.custom + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Rect +import android.graphics.RectF +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Color +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.View +import org.fossasia.badgemagic.R +import org.fossasia.badgemagic.data.badge_preview.Cell +import org.fossasia.badgemagic.data.badge_preview.CheckList +import org.fossasia.badgemagic.data.draw_layout.DrawMode + +class DrawBadgeLayout(context: Context?, attrs: AttributeSet?) : View(context, attrs) { + + private var ledDisabled: Drawable? = context?.getDrawable(R.drawable.ic_led) + private var ledEnabled: Drawable? = context?.getDrawable(R.drawable.ic_led_lit) + + private lateinit var bgBounds: RectF + + private var badgeHeight = 11 + private var badgeWidth = 40 + + private var cells = mutableListOf() + + private var checkList = ArrayList() + + private var drawMode = DrawMode.NOTHING + + init { + resetCheckList() + } + + fun changeDrawState(mode: DrawMode) { + drawMode = mode + } + + fun resetCheckList() { + checkList = ArrayList() + for (i in 0 until badgeHeight) { + checkList.add(CheckList()) + } + for (i in 0 until badgeHeight) { + for (j in 0 until badgeWidth) { + checkList[i].list.add(false) + } + } + invalidate() + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + + val ratioHeight = 1 + val ratioWidth = 3 + + val originalWidth = MeasureSpec.getSize(widthMeasureSpec) + val calculatedHeight = originalWidth * ratioHeight / ratioWidth + + setMeasuredDimension( + MeasureSpec.makeMeasureSpec(originalWidth, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(calculatedHeight, MeasureSpec.EXACTLY)) + } + + @SuppressLint("DrawAllocation") + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + super.onLayout(changed, left, top, right, bottom) + + val offset = 30 + + val singleCell = (right - left - (offset * 3)) / badgeWidth + + val offsetXToAdd: Int = ((((right - offset).toFloat() - (left + offset).toFloat()) - (singleCell * badgeWidth)) / 2).toInt() + 1 + + cells = mutableListOf() + for (i in 0 until badgeHeight) { + cells.add(Cell()) + for (j in 0 until badgeWidth) { + cells[i].list.add(Rect( + (offsetXToAdd * 2) + j * singleCell, + (offsetXToAdd * 2) + i * singleCell, + (offsetXToAdd * 2) + j * singleCell + singleCell, + (offsetXToAdd * 2) + i * singleCell + singleCell + )) + } + } + + bgBounds = RectF((offsetXToAdd).toFloat(), (offsetXToAdd).toFloat(), ((singleCell * badgeWidth) + (offsetXToAdd * 3)).toFloat(), ((singleCell * badgeHeight) + (offsetXToAdd * 3)).toFloat()) + } + + private fun drawLED(condition: Boolean, canvas: Canvas, xValue: Int, yValue: Int) { + if (condition) { + ledEnabled?.bounds = cells[xValue].list[yValue] + ledEnabled?.draw(canvas) + } else { + ledDisabled?.bounds = cells[xValue].list[yValue] + ledDisabled?.draw(canvas) + } + } + + @SuppressLint("DrawAllocation") + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + // Paint Configuration + val bgPaint = Paint() + bgPaint.isAntiAlias = true + bgPaint.color = Color.parseColor("#000000") + + // Draw Background + canvas.drawRoundRect(bgBounds, 25f, 25f, bgPaint) + for (i in 0 until badgeHeight) { + for (j in 0 until badgeWidth) { + drawLED( + checkList[i].list[j], + canvas, + i, j + ) + } + } + } + + @SuppressLint("ClickableViewAccessibility") + override fun onTouchEvent(event: MotionEvent?): Boolean { + changeCheckList(event?.x, event?.y) + return true + } + + private fun changeCheckList(x: Float?, y: Float?) { + if (x != null && y != null && drawMode != DrawMode.NOTHING) { + if (liesWithinX(x) || liesWithinY(y)) + return + + val singleCellSize = cells[0].list[0].right - cells[0].list[0].left + val newX = x - cells[0].list[0].left + val newY = y - cells[0].list[0].top + + checkList[(newY / singleCellSize).toInt()].list[(newX / singleCellSize).toInt()] = when (drawMode) { + DrawMode.DRAW -> true + DrawMode.ERASE -> false + else -> false + } + + invalidate() + } + } + + private fun liesWithinX(x: Float) = x < cells[0].list[0].left || x > cells[0].list[badgeWidth - 1].right + private fun liesWithinY(y: Float) = y < cells[0].list[0].top || y > cells[badgeHeight - 1].list[0].bottom +} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/custom/PreviewBadge.kt b/app/src/main/java/org/fossasia/badgemagic/ui/custom/PreviewBadge.kt index 38d2d717..d2533b6f 100644 --- a/app/src/main/java/org/fossasia/badgemagic/ui/custom/PreviewBadge.kt +++ b/app/src/main/java/org/fossasia/badgemagic/ui/custom/PreviewBadge.kt @@ -91,15 +91,16 @@ class PreviewBadge : View { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) + val ratioHeight = 1 - val ratioWidth = 3 + val ratioWidth = 3.45 val originalWidth = MeasureSpec.getSize(widthMeasureSpec) val calculatedHeight = originalWidth * ratioHeight / ratioWidth setMeasuredDimension( MeasureSpec.makeMeasureSpec(originalWidth, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(calculatedHeight, MeasureSpec.EXACTLY)) + MeasureSpec.makeMeasureSpec(calculatedHeight.toInt(), MeasureSpec.EXACTLY)) } public override fun onSaveInstanceState(): Parcelable? { @@ -145,14 +146,14 @@ class PreviewBadge : View { cells.add(Cell()) for (j in 0 until badgeWidth) { cells[i].list.add(Rect( - left + (offsetXToAdd * 2) + j * singleCell, - top + (offsetXToAdd * 2) + i * singleCell, - left + (offsetXToAdd * 2) + j * singleCell + singleCell, - top + (offsetXToAdd * 2) + i * singleCell + singleCell + (offsetXToAdd * 2) + j * singleCell, + (offsetXToAdd * 2) + i * singleCell, + (offsetXToAdd * 2) + j * singleCell + singleCell, + (offsetXToAdd * 2) + i * singleCell + singleCell )) } } - bgBounds = RectF((left + offset).toFloat(), (top + offset).toFloat(), (right - offset).toFloat(), ((singleCell * badgeHeight) + (offsetXToAdd * 3)).toFloat()) + bgBounds = RectF((offsetXToAdd).toFloat(), (offsetXToAdd).toFloat(), ((singleCell * badgeWidth) + (offsetXToAdd * 3)).toFloat(), ((singleCell * badgeHeight) + (offsetXToAdd * 3)).toFloat()) } private fun drawLED(condition: Boolean, canvas: Canvas, xValue: Int, yValue: Int) { diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/AboutFragment.kt b/app/src/main/java/org/fossasia/badgemagic/ui/fragments/AboutFragment.kt index adc61571..bf73645c 100644 --- a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/AboutFragment.kt +++ b/app/src/main/java/org/fossasia/badgemagic/ui/fragments/AboutFragment.kt @@ -7,7 +7,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import org.fossasia.badgemagic.R -import org.fossasia.badgemagic.ui.fragments.base.BaseFragment +import org.fossasia.badgemagic.ui.base.BaseFragment import de.psdev.licensesdialog.LicensesDialog import de.psdev.licensesdialog.licenses.ApacheSoftwareLicense20 import de.psdev.licensesdialog.licenses.MITLicense diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/main_saved/MainSavedFragment.kt b/app/src/main/java/org/fossasia/badgemagic/ui/fragments/SavedBadgesFragment.kt similarity index 88% rename from app/src/main/java/org/fossasia/badgemagic/ui/fragments/main_saved/MainSavedFragment.kt rename to app/src/main/java/org/fossasia/badgemagic/ui/fragments/SavedBadgesFragment.kt index 100307c5..68a3498e 100644 --- a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/main_saved/MainSavedFragment.kt +++ b/app/src/main/java/org/fossasia/badgemagic/ui/fragments/SavedBadgesFragment.kt @@ -1,4 +1,4 @@ -package org.fossasia.badgemagic.ui.fragments.main_saved +package org.fossasia.badgemagic.ui.fragments import android.bluetooth.BluetoothAdapter import android.content.Intent @@ -10,7 +10,6 @@ import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.core.content.FileProvider import androidx.lifecycle.Observer -import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.synthetic.main.fragment_main_save.* @@ -19,38 +18,26 @@ import org.fossasia.badgemagic.data.fragments.ConfigInfo import org.fossasia.badgemagic.data.device.model.DataToSend import org.fossasia.badgemagic.data.device.model.Mode import org.fossasia.badgemagic.data.device.model.Speed -import org.fossasia.badgemagic.ui.AppViewModel -import org.fossasia.badgemagic.ui.fragments.base.BaseFragment +import org.fossasia.badgemagic.viewmodels.FilesViewModel +import org.fossasia.badgemagic.ui.base.BaseFragment import org.fossasia.badgemagic.util.Converters -import org.fossasia.badgemagic.util.InjectorUtils import org.fossasia.badgemagic.util.SendingUtils import org.fossasia.badgemagic.adapter.OnSavedItemSelected import org.fossasia.badgemagic.adapter.SaveAdapter +import org.koin.androidx.viewmodel.ext.android.sharedViewModel import java.io.File -class MainSavedFragment : BaseFragment() { +class SavedBadgesFragment : BaseFragment() { companion object { @JvmStatic fun newInstance() = - MainSavedFragment() + SavedBadgesFragment() } private var recyclerAdapter: SaveAdapter? = null - private lateinit var viewModel: AppViewModel - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - inject() - } - - override fun inject() { - val currentActivity = activity - if (currentActivity != null) - viewModel = ViewModelProviders - .of(currentActivity, InjectorUtils.provideFilesViewModelFactory()) - .get(AppViewModel::class.java) - } + private val viewModel by sharedViewModel() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_main_save, container, false) diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/SettingsFragment.kt b/app/src/main/java/org/fossasia/badgemagic/ui/fragments/SettingsFragment.kt new file mode 100644 index 00000000..5fdf978f --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/ui/fragments/SettingsFragment.kt @@ -0,0 +1,46 @@ +package org.fossasia.badgemagic.ui.fragments + +import androidx.databinding.DataBindingUtil +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.lifecycle.Observer +import com.google.android.material.snackbar.Snackbar +import org.fossasia.badgemagic.R +import org.fossasia.badgemagic.databinding.FragmentSettingsBinding +import org.fossasia.badgemagic.ui.base.BaseFragment +import org.fossasia.badgemagic.viewmodels.SettingsViewModel +import org.koin.androidx.viewmodel.ext.android.viewModel + +class SettingsFragment : BaseFragment() { + + companion object { + @JvmStatic + fun newInstance() = + SettingsFragment() + } + + private val viewModel by viewModel() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val binding = DataBindingUtil.inflate(inflater, R.layout.fragment_settings, container, false) + binding.viewModel = viewModel + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + viewModel.changedLanguage.observe(viewLifecycleOwner, Observer { + + Snackbar + .make(view, requireContext().getString(R.string.change_language), Snackbar.LENGTH_INDEFINITE) + .setAction("RESTART") { + requireActivity().finishAffinity() + startActivity(requireActivity().intent) + } + .show() + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/main_textart/MainTextArtFragment.kt b/app/src/main/java/org/fossasia/badgemagic/ui/fragments/TextArtFragment.kt similarity index 83% rename from app/src/main/java/org/fossasia/badgemagic/ui/fragments/main_textart/MainTextArtFragment.kt rename to app/src/main/java/org/fossasia/badgemagic/ui/fragments/TextArtFragment.kt index 42640778..044b77b9 100644 --- a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/main_textart/MainTextArtFragment.kt +++ b/app/src/main/java/org/fossasia/badgemagic/ui/fragments/TextArtFragment.kt @@ -1,8 +1,10 @@ -package org.fossasia.badgemagic.ui.fragments.main_textart +package org.fossasia.badgemagic.ui.fragments import android.annotation.SuppressLint import android.app.AlertDialog import android.bluetooth.BluetoothAdapter +import android.bluetooth.BluetoothManager +import android.content.Context import android.content.DialogInterface import android.content.res.Configuration import android.graphics.Color @@ -21,7 +23,6 @@ import android.widget.TextView import android.widget.LinearLayout import android.widget.Toast import androidx.lifecycle.Observer -import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.GridLayoutManager import com.google.android.material.tabs.TabLayout import kotlinx.android.synthetic.main.effects_layout.* @@ -31,7 +32,7 @@ import org.fossasia.badgemagic.data.DrawableInfo import org.fossasia.badgemagic.data.ModeInfo import org.fossasia.badgemagic.data.device.model.Mode import org.fossasia.badgemagic.ui.custom.knob.Croller -import org.fossasia.badgemagic.ui.fragments.base.BaseFragment +import org.fossasia.badgemagic.ui.base.BaseFragment import kotlinx.android.synthetic.main.fragment_main_textart.* import kotlinx.android.synthetic.main.sections_tab.* import org.fossasia.badgemagic.adapter.DrawableAdapter @@ -44,12 +45,13 @@ import org.fossasia.badgemagic.data.device.model.DataToSend import org.fossasia.badgemagic.data.device.model.Message import org.fossasia.badgemagic.data.device.model.Speed import org.fossasia.badgemagic.text.CenteredImageSpan -import org.fossasia.badgemagic.util.InjectorUtils import org.fossasia.badgemagic.util.SendingUtils import org.fossasia.badgemagic.util.Converters import org.fossasia.badgemagic.util.ImageUtils import org.fossasia.badgemagic.util.DRAWABLE_END import org.fossasia.badgemagic.util.DRAWABLE_START +import org.fossasia.badgemagic.viewmodels.TextArtViewModel +import org.koin.androidx.viewmodel.ext.android.viewModel import pl.droidsonroids.gif.GifImageView import java.text.SimpleDateFormat import java.util.Timer @@ -57,30 +59,18 @@ import java.util.Calendar import java.util.Locale import java.util.TimerTask -class MainTextArtFragment : BaseFragment() { +class TextArtFragment : BaseFragment() { companion object { private const val SCAN_TIMEOUT_MS = 9500L @JvmStatic fun newInstance() = - MainTextArtFragment() + TextArtFragment() } private val drawableRecyclerAdapter = DrawableAdapter() private val modeAdapter = ModeAdapter() - private lateinit var viewModel: MainTextArtViewModel - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - inject() - } - - override fun inject() { - val currentActivity = activity - if (currentActivity != null) - viewModel = ViewModelProviders - .of(currentActivity, InjectorUtils.provideMainTextDrawableViewModelFactory()) - .get(MainTextArtViewModel::class.java) - } + private val viewModel by viewModel() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -122,27 +112,53 @@ class MainTextArtFragment : BaseFragment() { } transfer_button.setOnClickListener { - if (BluetoothAdapter.getDefaultAdapter().isEnabled) { - // Easter egg - Toast.makeText(requireContext(), getString(R.string.sending_data), Toast.LENGTH_LONG).show() - - transfer_button.visibility = View.GONE - send_progress.visibility = View.VISIBLE - - val buttonTimer = Timer() - buttonTimer.schedule(object : TimerTask() { - override fun run() { - activity?.runOnUiThread { - transfer_button.visibility = View.VISIBLE - send_progress.visibility = View.GONE + if (textViewMainText.text.trim().toString() != "") { + if (BluetoothAdapter.getDefaultAdapter().isEnabled) { + // Easter egg + Toast.makeText(requireContext(), getString(R.string.sending_data), Toast.LENGTH_LONG).show() + + transfer_button.visibility = View.GONE + send_progress.visibility = View.VISIBLE + + val buttonTimer = Timer() + buttonTimer.schedule(object : TimerTask() { + override fun run() { + activity?.runOnUiThread { + transfer_button.visibility = View.VISIBLE + send_progress.visibility = View.GONE + } } - } - }, SCAN_TIMEOUT_MS) + }, SCAN_TIMEOUT_MS) - SendingUtils.sendMessage(requireContext(), getSendData()) - } else { - Toast.makeText(requireContext(), getString(R.string.enable_bluetooth), Toast.LENGTH_LONG).show() - } + SendingUtils.sendMessage(requireContext(), getSendData()) + } else + showAlertDialog() + } else + Toast.makeText(requireContext(), getString(R.string.empty_text_to_send), Toast.LENGTH_LONG).show() + } + } + + private fun showAlertDialog() { + val dialogMessage = getString(R.string.enable_bluetooth) + val builder = AlertDialog.Builder(requireContext()) + builder.setIcon(resources.getDrawable(R.drawable.ic_caution)) + builder.setTitle(getString(R.string.permission_required)) + builder.setMessage(dialogMessage) + builder.setPositiveButton("OK") { _, _ -> + turnOnBluetooth() + Toast.makeText(context, R.string.bluetooth_enabled, Toast.LENGTH_SHORT).show() + } + builder.setNegativeButton("CANCEL") { _, _ -> + Toast.makeText(context, R.string.enable_bluetooth, Toast.LENGTH_SHORT).show() + } + builder.create().show() + } + + private fun turnOnBluetooth() { + val btManager = requireContext().getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager + val btAdapter = btManager.adapter + if (btAdapter.disable()) { + btAdapter.enable() } } @@ -167,6 +183,25 @@ class MainTextArtFragment : BaseFragment() { textViewMainText.showKeyboard() textViewMainText.setText(viewModel.text) + + clipart_handler_layout.setOnClickListener { + viewModel.showClipart = !viewModel.showClipart + toggleEmojiSection() + } + toggleEmojiSection() + } + + private fun toggleEmojiSection() { + viewModel.showClipart.let { + clipart_layout.visibility = if (it) View.VISIBLE else View.GONE + clipart_handler.setImageResource( + if (it) + R.drawable.ic_clipart_switcher_enabled + else + R.drawable.ic_clipart_switcher_disabled + ) + if (it) textViewMainText.hideKeyboard() else textViewMainText.showKeyboard() + } } private val tabSelectedListener = object : TabLayout.OnTabSelectedListener { @@ -286,7 +321,7 @@ class MainTextArtFragment : BaseFragment() { onDrawableSelected = drawableListener } - viewModel.getClipArts().observe(this, Observer { + viewModel.getClipArts().observe(viewLifecycleOwner, Observer { val listOfDrawable = mutableListOf() for (i in 0 until it.size()) { val key = it.keyAt(i) @@ -446,7 +481,7 @@ class MainTextArtFragment : BaseFragment() { viewModel.let { StoreAsync(fileName, jsonString, it).execute() } } - class StoreAsync(private val filename: String, private val json: String, private val viewModel: MainTextArtViewModel) : AsyncTask() { + class StoreAsync(private val filename: String, private val json: String, private val viewModel: TextArtViewModel) : AsyncTask() { override fun doInBackground(vararg params: Void?): Void? { viewModel.saveFile(filename, json) return null diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/main_textart/MainTextArtViewModel.kt b/app/src/main/java/org/fossasia/badgemagic/ui/fragments/main_textart/MainTextArtViewModel.kt deleted file mode 100644 index c16b29c1..00000000 --- a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/main_textart/MainTextArtViewModel.kt +++ /dev/null @@ -1,23 +0,0 @@ -package org.fossasia.badgemagic.ui.fragments.main_textart - -import androidx.lifecycle.ViewModel -import org.fossasia.badgemagic.data.clipart.ClipArtRepository -import org.fossasia.badgemagic.data.saved_files.FilesRepository - -class MainTextArtViewModel(private val configRepo: FilesRepository, private val clipArtRepo: ClipArtRepository) : ViewModel() { - var speed = 1 - var isFlash = false - var isMarquee = false - var isInverted = false - var animationPosition = -1 - var currentTab = 1 - var text = "" - - fun checkIfFilePresent(fileName: String): Boolean = configRepo.checkIfFilePresent(fileName) - - fun updateList() = configRepo.update() - - fun saveFile(filename: String, json: String) = configRepo.saveFile(filename, json) - - fun getClipArts() = clipArtRepo.getClipArts() -} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/main_textart/MainTextArtViewModelProviderFactory.kt b/app/src/main/java/org/fossasia/badgemagic/ui/fragments/main_textart/MainTextArtViewModelProviderFactory.kt deleted file mode 100644 index f641f874..00000000 --- a/app/src/main/java/org/fossasia/badgemagic/ui/fragments/main_textart/MainTextArtViewModelProviderFactory.kt +++ /dev/null @@ -1,15 +0,0 @@ -package org.fossasia.badgemagic.ui.fragments.main_textart - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import org.fossasia.badgemagic.data.clipart.ClipArtRepository -import org.fossasia.badgemagic.data.saved_files.FilesRepository - -class MainTextArtViewModelProviderFactory(private val configRepository: FilesRepository, private val clipArtRepository: ClipArtRepository) : - ViewModelProvider.NewInstanceFactory() { - - override fun create(modelClass: Class): T { - @Suppress("UNCHECKED_CAST") - return MainTextArtViewModel(configRepository, clipArtRepository) as T - } -} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/util/Converters.kt b/app/src/main/java/org/fossasia/badgemagic/util/Converters.kt index 5b9f1bbb..6f675feb 100644 --- a/app/src/main/java/org/fossasia/badgemagic/util/Converters.kt +++ b/app/src/main/java/org/fossasia/badgemagic/util/Converters.kt @@ -1,8 +1,6 @@ package org.fossasia.badgemagic.util -import android.content.Context import android.graphics.drawable.BitmapDrawable -import androidx.annotation.DrawableRes import android.graphics.drawable.Drawable import android.util.SparseArray import org.fossasia.badgemagic.data.device.DataToByteArrayConverter @@ -12,12 +10,7 @@ const val DRAWABLE_START = '«' const val DRAWABLE_END = '»' object Converters { - fun convertImageToLEDHex(context: Context, @DrawableRes dId: Int, invertLED: Boolean): List { - val myIcon = context.resources.getDrawable(dId) - return convertDrawableToLEDHex(myIcon, invertLED) - } - - fun convertDrawableToLEDHex(drawableIcon: Drawable, invertLED: Boolean): List { + private fun convertDrawableToLEDHex(drawableIcon: Drawable?, invertLED: Boolean): List { val bm = (drawableIcon as BitmapDrawable).bitmap val height = bm.height diff --git a/app/src/main/java/org/fossasia/badgemagic/util/InjectorUtils.kt b/app/src/main/java/org/fossasia/badgemagic/util/InjectorUtils.kt deleted file mode 100644 index b1c18fcc..00000000 --- a/app/src/main/java/org/fossasia/badgemagic/util/InjectorUtils.kt +++ /dev/null @@ -1,22 +0,0 @@ -package org.fossasia.badgemagic.util - -import org.fossasia.badgemagic.data.clipart.ClipArtContainer -import org.fossasia.badgemagic.data.clipart.ClipArtRepository -import org.fossasia.badgemagic.data.saved_files.FilesContainer -import org.fossasia.badgemagic.data.saved_files.FilesRepository -import org.fossasia.badgemagic.ui.AppViewModelProviderFactory -import org.fossasia.badgemagic.ui.fragments.main_textart.MainTextArtViewModelProviderFactory - -object InjectorUtils { - - private val filesRepo = FilesRepository.getInstance(FilesContainer.getInstance().filesData) - private val clipArtRepo = ClipArtRepository.getInstance(ClipArtContainer.getInstance().clipArts) - - fun provideFilesViewModelFactory(): AppViewModelProviderFactory { - return AppViewModelProviderFactory(filesRepo) - } - - fun provideMainTextDrawableViewModelFactory(): MainTextArtViewModelProviderFactory { - return MainTextArtViewModelProviderFactory(filesRepo, clipArtRepo) - } -} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/util/LocaleManager.kt b/app/src/main/java/org/fossasia/badgemagic/util/LocaleManager.kt new file mode 100644 index 00000000..aa1f8820 --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/util/LocaleManager.kt @@ -0,0 +1,30 @@ +package org.fossasia.badgemagic.util + +import android.content.Context +import android.content.res.Configuration +import org.fossasia.badgemagic.data.Language +import java.util.Locale + +object LocaleManager { + + fun setLocale(context: Context?): Context { + return updateResources(context as Context, + Language.values()[PreferenceUtils(context).selectedLanguage].locale + ) + } + + fun updateResources(context: Context, language: Locale): Context { + + val contextFun: Context + + Locale.setDefault(language) + + val resources = context.resources + val configuration = Configuration(resources.configuration) + + configuration.setLocale(language) + contextFun = context.createConfigurationContext(configuration) + + return contextFun + } +} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/util/PreferenceUtils.kt b/app/src/main/java/org/fossasia/badgemagic/util/PreferenceUtils.kt new file mode 100644 index 00000000..2c004703 --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/util/PreferenceUtils.kt @@ -0,0 +1,18 @@ +package org.fossasia.badgemagic.util + +import android.content.Context +import android.content.Context.MODE_PRIVATE + +const val PREFS_FILENAME = "org.fossasia.badgemagic.prefs" +const val SELECTED_LANGUAGE = "selected_language" + +class PreferenceUtils(val context: Context) { + + private fun getPrefs() = context.getSharedPreferences(PREFS_FILENAME, MODE_PRIVATE) + + var selectedLanguage: Int + get() = getPrefs()?.getInt(SELECTED_LANGUAGE, 0) ?: 0 + set(value) { + getPrefs()?.edit()?.putInt(SELECTED_LANGUAGE, value)?.apply() + } +} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/util/Resource.kt b/app/src/main/java/org/fossasia/badgemagic/util/Resource.kt index 6971d03c..cc6775cc 100644 --- a/app/src/main/java/org/fossasia/badgemagic/util/Resource.kt +++ b/app/src/main/java/org/fossasia/badgemagic/util/Resource.kt @@ -1,17 +1,13 @@ package org.fossasia.badgemagic.util +import android.content.Context import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.annotation.StringRes -import org.fossasia.badgemagic.ui.App -class Resource { - private val context by lazy { - App.appContext - } - - fun getResources() = context?.resources - fun getDrawable(@DrawableRes resId: Int) = context?.resources?.getDrawable(resId) - fun getString(@StringRes resId: Int) = context?.getString(resId) - fun getColor(@ColorRes resId: Int) = context?.resources?.getColor(resId) +class Resource(val context: Context) { + fun getResources() = context.resources + fun getDrawable(@DrawableRes resId: Int) = context.getDrawable(resId) + fun getString(@StringRes resId: Int) = context.getString(resId) + fun getColor(@ColorRes resId: Int) = context.resources?.getColor(resId) } \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/viewmodels/DrawViewModel.kt b/app/src/main/java/org/fossasia/badgemagic/viewmodels/DrawViewModel.kt new file mode 100644 index 00000000..8a6839bd --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/viewmodels/DrawViewModel.kt @@ -0,0 +1,28 @@ +package org.fossasia.badgemagic.viewmodels + +import androidx.databinding.ObservableBoolean +import androidx.databinding.ObservableField +import androidx.lifecycle.ViewModel +import org.fossasia.badgemagic.data.draw_layout.DrawMode + +class DrawViewModel : ViewModel() { + var drawModeState: ObservableField = ObservableField(DrawMode.NOTHING) + + var drawState: ObservableBoolean = ObservableBoolean(false) + var eraseState: ObservableBoolean = ObservableBoolean(false) + var resetState: ObservableBoolean = ObservableBoolean(false) + + fun changeDrawState() { + drawState.set(!drawState.get()) + drawModeState.set(if (drawState.get()) DrawMode.DRAW else DrawMode.NOTHING) + } + + fun changeEraseState() { + eraseState.set(!eraseState.get()) + drawModeState.set(if (eraseState.get()) DrawMode.ERASE else DrawMode.NOTHING) + } + + fun changeResetState() { + resetState.set(!resetState.get()) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/viewmodels/FilesViewModel.kt b/app/src/main/java/org/fossasia/badgemagic/viewmodels/FilesViewModel.kt new file mode 100644 index 00000000..f7893dd6 --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/viewmodels/FilesViewModel.kt @@ -0,0 +1,17 @@ +package org.fossasia.badgemagic.viewmodels + +import androidx.lifecycle.ViewModel +import org.fossasia.badgemagic.database.StorageFilesService + +class FilesViewModel( + private val storageFilesService: StorageFilesService +) : ViewModel() { + + fun getFiles() = storageFilesService.getFiles() + + fun deleteFile(fileName: String) = storageFilesService.deleteFile(fileName) + + fun updateList() = storageFilesService.update() + + fun getAbsPath(fileName: String): String? = storageFilesService.getAbsPath(fileName) +} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/viewmodels/SettingsViewModel.kt b/app/src/main/java/org/fossasia/badgemagic/viewmodels/SettingsViewModel.kt new file mode 100644 index 00000000..79e46cce --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/viewmodels/SettingsViewModel.kt @@ -0,0 +1,27 @@ +package org.fossasia.badgemagic.viewmodels + +import androidx.databinding.ObservableField +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import org.fossasia.badgemagic.data.Language +import org.fossasia.badgemagic.util.PreferenceUtils + +class SettingsViewModel( + private val preferenceUtils: PreferenceUtils +) : ViewModel() { + var languageList: ObservableField> = ObservableField() + var changedLanguage: MutableLiveData = MutableLiveData() + + init { + val mutableList = mutableListOf() + mutableList.addAll(Language.values().map { it.toString() }) + languageList.set(mutableList) + } + + fun getSelectedSpinnerLanguage() = preferenceUtils.selectedLanguage + + fun setSelectedSpinnerLangauge(position: Int) { + preferenceUtils.selectedLanguage = position + changedLanguage.value = true + } +} \ No newline at end of file diff --git a/app/src/main/java/org/fossasia/badgemagic/viewmodels/TextArtViewModel.kt b/app/src/main/java/org/fossasia/badgemagic/viewmodels/TextArtViewModel.kt new file mode 100644 index 00000000..9ecb1371 --- /dev/null +++ b/app/src/main/java/org/fossasia/badgemagic/viewmodels/TextArtViewModel.kt @@ -0,0 +1,27 @@ +package org.fossasia.badgemagic.viewmodels + +import androidx.lifecycle.ViewModel +import org.fossasia.badgemagic.database.ClipArtService +import org.fossasia.badgemagic.database.StorageFilesService + +class TextArtViewModel( + private val clipArtService: ClipArtService, + private val storageFilesService: StorageFilesService +) : ViewModel() { + var speed = 1 + var isFlash = false + var isMarquee = false + var isInverted = false + var animationPosition = -1 + var currentTab = 1 + var text = "" + var showClipart = false + + fun checkIfFilePresent(fileName: String): Boolean = storageFilesService.checkIfFilePresent(fileName) + + fun updateList() = storageFilesService.update() + + fun saveFile(filename: String, json: String) = storageFilesService.saveFile(filename, json) + + fun getClipArts() = clipArtService.getClipArts() +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_clipart_switcher_disabled.xml b/app/src/main/res/drawable/ic_clipart_switcher_disabled.xml new file mode 100644 index 00000000..a36c723f --- /dev/null +++ b/app/src/main/res/drawable/ic_clipart_switcher_disabled.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_clipart_switcher_enabled.xml b/app/src/main/res/drawable/ic_clipart_switcher_enabled.xml new file mode 100644 index 00000000..6af759fc --- /dev/null +++ b/app/src/main/res/drawable/ic_clipart_switcher_enabled.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_draw_erase.xml b/app/src/main/res/drawable/ic_draw_erase.xml new file mode 100644 index 00000000..49355f36 --- /dev/null +++ b/app/src/main/res/drawable/ic_draw_erase.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_draw_pencil.xml b/app/src/main/res/drawable/ic_draw_pencil.xml new file mode 100644 index 00000000..76c2cfa3 --- /dev/null +++ b/app/src/main/res/drawable/ic_draw_pencil.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_draw_reset.xml b/app/src/main/res/drawable/ic_draw_reset.xml new file mode 100644 index 00000000..a7408278 --- /dev/null +++ b/app/src/main/res/drawable/ic_draw_reset.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_emoji.xml b/app/src/main/res/drawable/ic_emoji.xml index feec568e..742f0ac5 100644 --- a/app/src/main/res/drawable/ic_emoji.xml +++ b/app/src/main/res/drawable/ic_emoji.xml @@ -1,8 +1,24 @@ - - - - - - + + + + + + + diff --git a/app/src/main/res/drawable/ic_menu_settings.xml b/app/src/main/res/drawable/ic_menu_settings.xml new file mode 100644 index 00000000..e2560dc1 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_settings.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land/fragment_main_save.xml b/app/src/main/res/layout-land/fragment_main_save.xml index 95608700..3d01e4a4 100644 --- a/app/src/main/res/layout-land/fragment_main_save.xml +++ b/app/src/main/res/layout-land/fragment_main_save.xml @@ -38,12 +38,9 @@ android:visibility="gone"> diff --git a/app/src/main/res/layout-land/fragment_main_textart.xml b/app/src/main/res/layout-land/fragment_main_textart.xml index b59eccc6..929af436 100644 --- a/app/src/main/res/layout-land/fragment_main_textart.xml +++ b/app/src/main/res/layout-land/fragment_main_textart.xml @@ -33,35 +33,50 @@ android:orientation="vertical" android:paddingEnd="@dimen/spacing_normal"> - + android:orientation="horizontal"> + + + + + - - - + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_small" + android:background="@drawable/round_corner_bg"> - - + diff --git a/app/src/main/res/layout/activity_draw.xml b/app/src/main/res/layout/activity_draw.xml new file mode 100644 index 00000000..3fa37e78 --- /dev/null +++ b/app/src/main/res/layout/activity_draw.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/app_bar_drawer.xml b/app/src/main/res/layout/app_bar_drawer.xml index fb1fa72d..3b951983 100644 --- a/app/src/main/res/layout/app_bar_drawer.xml +++ b/app/src/main/res/layout/app_bar_drawer.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.drawer.DrawerActivity"> + tools:context=".ui.DrawerActivity"> + android:orientation="vertical" + android:visibility="gone"> diff --git a/app/src/main/res/layout/fragment_main_textart.xml b/app/src/main/res/layout/fragment_main_textart.xml index 7e556557..0f9eae2a 100644 --- a/app/src/main/res/layout/fragment_main_textart.xml +++ b/app/src/main/res/layout/fragment_main_textart.xml @@ -11,8 +11,7 @@ + android:layout_height="match_parent"> - + android:orientation="horizontal"> + + + + + - - - + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_small" + android:background="@drawable/round_corner_bg"> - - + @@ -63,8 +76,7 @@ android:id="@+id/buttonsLayout" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_marginBottom="@dimen/bottom_bar_margin" + android:layout_marginTop="@dimen/spacing_large" android:baselineAligned="false" android:gravity="center" android:orientation="horizontal"> @@ -79,7 +91,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" - android:layout_marginTop="@dimen/spacing_small" android:paddingLeft="@dimen/button_padding_left_right" android:paddingRight="@dimen/button_padding_left_right" android:text="@string/save_button" @@ -103,7 +114,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" - android:layout_marginTop="@dimen/spacing_small" android:paddingLeft="@dimen/button_padding_left_right" android:paddingRight="@dimen/button_padding_left_right" android:text="@string/transfer_button" diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml new file mode 100644 index 00000000..bea27999 --- /dev/null +++ b/app/src/main/res/layout/fragment_settings.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/sections_tab.xml b/app/src/main/res/layout/sections_tab.xml index 87d58f9b..42a4b6d0 100644 --- a/app/src/main/res/layout/sections_tab.xml +++ b/app/src/main/res/layout/sections_tab.xml @@ -9,37 +9,25 @@ android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/spacing_normal" android:layout_marginBottom="@dimen/spacing_normal" app:tabTextAppearance="@style/TabTextAppearance"> - - - - + + + + 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 00000000..f02f8bc4 --- /dev/null +++ b/app/src/main/res/values-land/dimens.xml @@ -0,0 +1,4 @@ + + + 100dp + \ No newline at end of file diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml deleted file mode 100644 index 779fe8c6..00000000 --- a/app/src/main/res/values-v21/styles.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 00000000..5759ef4d --- /dev/null +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,85 @@ + + 徽章魔术 + + 您必须打开蓝牙才能使用发送功能 + 您必须授予所需的权限 + + + 华盖 + 速度 + 动画 + 剩下 + + 向上 + + 固定 + 雪花 + 图片 + 动画 + 激光 + 需要许可 + 找不到设备。请再试一次。 + 反转LED + 输入文字 + 位图图像 + 保存 + 文件名 + 继续之前输入文件名 + 保存徽章 + 保存的徽章 + 执行操作 + 删除 + 分享 + 已保存的徽章已删除。 + + 进口 + 选择有效徽章魔术配置 + 文件已存在 + 要覆盖更改吗? + 导入文件 + 你想导入吗? + 发送数据。 + 传递 + 效果 + + 打开导航抽屉 + 关闭导航抽屉 + 导航标题 + + 其他 + 反馈/错误报告 + 买徽章 + 关于我们 + 保存的徽章 + 创建徽章 + 导入成功 + Badge Magic是一款用于控制LED名称徽章的Android应用程序。目标是提供在LED徽章上描绘名称,图形和简单动画的选项。对于从智能手机到LED徽章的数据传输,我们使用蓝牙。该项目以Nilhcem的工作为基础。 + 联系我们 + GitHub上 + 分拆回购并推送更改或提交新问题。 + 执照 + 检查Badge Magic上使用的Apache License 2.0术语 + 图书馆许可证 + 检查Badge Magic上使用的第三方库。 + 莫希 + 版权所有2015 Square,Inc。 + Android的GIF抽拉 + 版权所有2013年 - 至今KarolWrótniak,Droids on Roids LLC + 木材 + 版权所有2013 Jake Wharton + Android BLE Scanner Compat库 + 版权所有2015,Nordic Semiconductor + 许可证对话框 + 版权所有2013 Philip Schiffer + 看起来还没有保存的徽章 + 没有保存的徽章! + 创建徽章 + 保存的徽章 + 您的设备不支持应用程序快捷方式。 + 请输入要发送的内容 + 蓝牙已打开。 + + 语言 + 设置 + 为了更改语言,我们需要重新启动应用程序。 + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 41ee382c..96a67d64 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -18,7 +18,7 @@ 20dp 40dp 20dp - 150dp + 180dp 10dp 1dp 5dp @@ -37,4 +37,5 @@ 22sp 16sp + 50dp \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 99e359fe..d61fe607 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,5 +1,14 @@ + Developed by FOSSASIA + contributors. + + https://github.com/square/moshi + https://github.com/JakeWharton/timber + https://github.com/NordicSemiconductor/Android-Scanner-Compat-Library + https://github.com/PSDev/LicensesDialog + https://github.com/koral––/android–gif–drawable + Badge Magic You must turn Bluetooth on to use send feature @@ -54,9 +63,6 @@ Saved Badges Create Badges Import Successful - Developed by FOSSASIA - contributors. - Badge Magic is an Android app to control LED name badges. The goal is to provide options to portray names, graphics and simple animations on LED badges. For the data transfer from the smartphone to the LED badge we use Bluetooth. The project is based on the work of Nilhcem. Connect With Us GitHub @@ -66,24 +72,28 @@ Library Licenses Check third-party libs used on Badge Magic. Moshi - https://github.com/square/moshi Copyright 2015 Square, Inc. android-gif-drawable - https://github.com/koral––/android–gif–drawable Copyright 2013 - present Karol Wrótniak, Droids on Roids LLC Timber - https://github.com/JakeWharton/timber Copyright 2013 Jake Wharton Android BLE Scanner Compat library - https://github.com/NordicSemiconductor/Android-Scanner-Compat-Library Copyright 2015, Nordic Semiconductor Licences Dialog - https://github.com/PSDev/LicensesDialog Copyright 2013 Philip Schiffer Looks like there are no saved badges yet No Saved Badges ! Create Badge Saved Badges App shortcuts are not supported on your device. + Please Enter Something to Send + Bluetooth has been turned on. + + Language + Settings + In order to change the language we need to restart the app. + Reset + Draw + Erase diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 339f25dc..0fda332d 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -18,11 +18,6 @@ false - - @@ -32,4 +27,10 @@ + + diff --git a/app/src/main/res/xml/shortcuts.xml b/app/src/main/res/xml-v25/shortcuts.xml similarity index 73% rename from app/src/main/res/xml/shortcuts.xml rename to app/src/main/res/xml-v25/shortcuts.xml index 5e41d233..4dd62e5f 100644 --- a/app/src/main/res/xml/shortcuts.xml +++ b/app/src/main/res/xml-v25/shortcuts.xml @@ -1,15 +1,17 @@ - + + android:shortcutDisabledMessage="@string/disabled" + tools:targetApi="n_mr1"> + android:targetClass="org.fossasia.badgemagic.ui.DrawerActivity" /> @@ -23,7 +25,7 @@ + android:targetClass="org.fossasia.badgemagic.ui.DrawerActivity" /> \ No newline at end of file diff --git a/build.gradle b/build.gradle index f0c7bf3f..e9a8d9da 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.4.1' + classpath "com.android.tools.build:gradle:3.4.1" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin_version" } } diff --git a/docs/images/app_icon.png b/docs/images/app_icon.png new file mode 100644 index 00000000..8a89cae6 Binary files /dev/null and b/docs/images/app_icon.png differ diff --git a/ic_web.svg b/docs/images/app_icon.svg similarity index 100% rename from ic_web.svg rename to docs/images/app_icon.svg diff --git a/docs/images/fdroid_badge.png b/docs/images/fdroid_badge.png new file mode 100644 index 00000000..7af05870 Binary files /dev/null and b/docs/images/fdroid_badge.png differ diff --git a/docs/images/google_play_badge.png b/docs/images/google_play_badge.png new file mode 100644 index 00000000..7e6d7706 Binary files /dev/null and b/docs/images/google_play_badge.png differ diff --git a/docs/images/screen-1.png b/docs/images/screen-1.png index 5bcb0f9a..f21bdecf 100644 Binary files a/docs/images/screen-1.png and b/docs/images/screen-1.png differ diff --git a/docs/images/screen-2.png b/docs/images/screen-2.png index 36869fd8..d12f5c01 100644 Binary files a/docs/images/screen-2.png and b/docs/images/screen-2.png differ diff --git a/docs/images/screen-3.png b/docs/images/screen-3.png index 97cba1c6..6fb782d1 100644 Binary files a/docs/images/screen-3.png and b/docs/images/screen-3.png differ diff --git a/docs/images/screen-4-hard.png b/docs/images/screen-4-hard.png index 77ebd581..e765ba1d 100644 Binary files a/docs/images/screen-4-hard.png and b/docs/images/screen-4-hard.png differ diff --git a/docs/images/screen-4.png b/docs/images/screen-4.png index 4da0a235..3e7fa5a0 100644 Binary files a/docs/images/screen-4.png and b/docs/images/screen-4.png differ diff --git a/docs/images/screen-5.png b/docs/images/screen-5.png index 27f246bd..804974c2 100644 Binary files a/docs/images/screen-5.png and b/docs/images/screen-5.png differ diff --git a/docs/images/screen-6-hard.png b/docs/images/screen-6-hard.png index 9dbb557c..9ee97299 100644 Binary files a/docs/images/screen-6-hard.png and b/docs/images/screen-6-hard.png differ diff --git a/docs/images/screen-6.png b/docs/images/screen-6.png index e9512f24..83686afb 100644 Binary files a/docs/images/screen-6.png and b/docs/images/screen-6.png differ diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..5465fec0 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +android.enableJetifier=true +android.useAndroidX=true \ No newline at end of file diff --git a/scripts/upload-apk.sh b/scripts/upload-apk.sh index a08291a9..c748876b 100644 --- a/scripts/upload-apk.sh +++ b/scripts/upload-apk.sh @@ -37,7 +37,7 @@ fi if [[ "$TRAVIS_BRANCH" == "$PUBLISH_BRANCH" ]]; then for file in app*; do - cp ${file} badge-magic-master-${file%%} + mv ${file} badge-magic-master-${file%%} done fi diff --git a/versions.gradle b/versions.gradle index 7fea9fb3..c09ae3da 100644 --- a/versions.gradle +++ b/versions.gradle @@ -2,10 +2,11 @@ ext.versions = [:] versions.compileSdk = 28 versions.buildTools = '28.0.3' -versions.minSdk = 18 +versions.minSdk = 21 versions.targetSdk = 28 versions.kotlin_version = '1.3.31' + +versions.koin_version = '2.0.1' versions.moshi_version = '1.8.0' -versions.lifecycle = '2.2.0-alpha01' versions.leak_canary = '2.0-alpha-2' \ No newline at end of file