diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..1691862 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/copyright/ui.xml b/.idea/copyright/ui.xml new file mode 100644 index 0000000..330f52a --- /dev/null +++ b/.idea/copyright/ui.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 093845d..c12ee43 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -1,8 +1,11 @@ + - + diff --git a/README.md b/README.md index 0ce9eae..9a932d6 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,20 @@ -# Android Promise Commons -- [v1.0.0] -The base promise library +# Android Promise UI [![](https://jitpack.io/v/android-promise/ui.svg)](https://jitpack.io/#android-promise/ui) -# Setup -- -#### build.gradle +Adapters, notifications, loading layout, Chain processors + + +### Table of Contents +**[Setup](##Setup)**
+**[Initialization](##Initialization)**
+**[Adapters](##Adapters)**
+**[Loading Layout](##LoadingLayout)**
+**[Chain Processors](##Transactions)**
+**[Next Steps, Credits, Feedback, License](#next-steps)**
+ +## Setup +##### build.gradle ``` + allprojects { repositories { ... @@ -14,6 +23,7 @@ allprojects { } android { + ... compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -21,37 +31,291 @@ android { } dependencies { - implementation 'com.github.dev4vin:android-promise:1.0.8' - implementation 'io.reactivex.rxjava2:rxjava:2.2.7' + ... + implementation 'com.github.android-promise:ui:TAG' + implementation 'com.github.android-promise:commons:1.1-alpha03' } ``` -# Initialization +### Initialization Initialize Promise in your main application file, entry point -#### App.java +##### App.java ```java +public class App extends Application { @Override public void onCreate() { super.onCreate(); - Promise.init(this).threads(100); + // 10 is the number of threads allowed to run in the background + AndroidPromise.init(this, 10, BuildConfig.DEBUG); + } + + @Override + public void onTerminate() { + super.onTerminate(); + AndroidPromise.instance().terminate(); + } +} +``` + +## Adapters +In this example, a simple use of the promise adapter, the adapter renders a list of viewable pojo + +```kotlin +lateinit var adapter: PromiseAdapter +``` +The adapter can optionally a click listner to fire when an viewable pojo is clicked +In this scenario, the adapter also takes a map of object class to viewholder class. + +```kotlin +adapter = PromiseAdapter(ArrayMap, KClass>().apply { + put(ViewablePoJo::class.java, ViewablePoJoViewable::class) + }, this, true) + +``` +To pass the right object to the viewholder, to properly a viewholder to object type, one of the following three ways apply +#### Mapping with ViewHolder class +The viewholder class is as, it must implement Viewable and have one constructor accepting the object instance to be displayed +```kotlin + +class ViewablePoJoViewable(private val viewablePoJo: ViewablePoJo) : Viewable { + + lateinit var imageView: ImageView + lateinit var textView: TextView + lateinit var shimmerFrameLayout: ShimmerFrameLayout + + override fun layout(): Int = R.layout.pojo_layout + + override fun init(view: View) { + shimmerFrameLayout = view.findViewById(R.id.shimmers) + textView = view.findViewById(R.id.pojo_text) + imageView = view.findViewById(R.id.action_image) + } + + override fun bind(view: View?, args: Any?) { + if (args is Boolean) { + shimmerFrameLayout.startShimmer() + return + } + shimmerFrameLayout.stopShimmer() + shimmerFrameLayout.setShimmer(null) + textView.text = viewablePoJo.text + } +} +``` +#### Using ViewableEntity annotation +The object class should have a viewable entity annotation as follows +```kotlin +// this viewholder must have a constructor accepting an instance of viewable pojo +class ViewablePoJoViewHolder(private val viewablePoJo: ViewablePoJo) : ViewHolder { + + override fun init(view: View) { + textView = view.findViewById(R.id.pojo_text) + } + + override fun bind(view: View, args: Any?) { + textView.text = viewablePoJo.text + } + + lateinit var textView: TextView +} + +//this entity tells the adapter to use ViewablePoJoViewHolder when rendering items of type ViewablePoJo +@ViewableEntity(layoutResource = R.layout.pojo_layout, viewHolderClass = ViewablePoJoViewHolder::class) +class ViewablePoJo(val text: String): Searchable { + @SuppressLint("DefaultLocale") + override fun onSearch(query: String): Boolean = text.toLowerCase().contains(query.toLowerCase()) +} +``` +#### Or the entity should be Viewable +```kotlin +class ImplementingViewable(): Viewable { + // returns the layout for this instance + override fun layout(): Int { + return R.layout.pojo_layout + } + + override fun init(view: View?) { + // initialize the views + } + + override fun bind(view: View?, args: Any?) { + //bind data to the views + } +} +``` + +### Adapter click events +The PromiseAdapter.Listener delivers click events for all public views in the viewholder, +```kotlin +class MainActivity : AppCompatActivity(), PromiseAdapter.Listener { + + override fun onClick(t: ViewablePoJo, id: Int) { + Toast.makeText(this, "Clicked ${t.text}", Toast.LENGTH_LONG).show() + LogUtil.e("_MainActivity", "clicked the pojo", t, " id ", id) } + ... + ``` +When a view is declared as public, a click listener is injected to it by the adapter +```kotlin + +class ViewablePoJoViewable(private val viewablePoJo: ViewablePoJo) : Viewable { + // this views are public + lateinit var imageView: ImageView + lateinit var textView: TextView + lateinit var shimmerFrameLayout: ShimmerFrameLayout + ... +} +``` +> declaring a view as private, a click listener won't be injectet into it +The id of the clicked view and the object instance are both delivered in the listener onClick handler + +```kotlin +class MainActivity : AppCompatActivity(), PromiseAdapter.Listener { + // fired when item is clicked + override fun onClick(t: ViewablePoJo, id: Int) { + Toast.makeText(this, "Clicked ${t.text}", Toast.LENGTH_LONG).show() + LogUtil.e("_MainActivity", "clicked the pojo", t, " id ", id) + } + ... +} ``` -#### Stay Updated +The full illusration below... +```kotlin +class MainActivity : AppCompatActivity(), PromiseAdapter.Listener { + + override fun onClick(t: ViewablePoJo, id: Int) { + Toast.makeText(this, "Clicked ${t.text}", Toast.LENGTH_LONG).show() + LogUtil.e("_MainActivity", "clicked the pojo", t, " id ", id) + } + + lateinit var adapter: PromiseAdapter + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + searchEditText.addTextChangedListener(object: TextWatcher { + override fun afterTextChanged(s: Editable) { + this.onTextChanged(s.toString(), 0, 0, 0) + } -# Wiki! -I strongly recommend to read the **[Wiki](https://github.com/dev4vin/android-promise/wiki) pages**, where you can find a comprehensive Tutorial.
+ override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { -### Pull requests / Issues / Improvement requests + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + adapter.search(s.toString()){ + if(!it) loading_view.showEmpty(R.drawable.ic_launcher_background, + "Searched list is empty", + "No item found with the query provided") + else loading_view.showContent() + } + } + }) + + adapter = PromiseAdapter(ArrayMap, KClass>().apply { + put(ViewablePoJo::class.java, ViewablePoJoViewable::class) + }, this, true) + + recycler_view.layoutManager = LinearLayoutManager(this) + + recycler_view.adapter = adapter + + loading_view.showContent() + adapter.add(List.generate(10) { + ViewablePoJo("test $it") + }) + + AndroidPromise.instance().executeOnUi({ + adapter.args = null + + adapter setList List.generate(50) { + ViewablePoJo("test $it") + } + }, 5000) + } +} +``` + +## LoadingLayout + +This is useful when you have to display another view when loading items from a repository + +```xml +... + + + +... +``` +> The loading layout only takes one sigle child in the xml tree + +#### Using it in the source code +When requesting data from repository, initialize loading as follows +```kotlin + + // using default loader progress bar + loading_view.showLoading(null) + + // can also pass an object that is viewable + class LoadingViewable(private val message: String): Viewable { + override fun layout(): Int { + return R.layout.loading_viewable + } + + override fun init(view: View?) { + // init loading layout views + } + + override fun bind(view: View?, args: Any?) { + // bind message to the views + } + } + + loading_view.showLoading(LoadingViewable("Loading items, please wait")) + +``` + +After receiving data +```kotlin + loading_view.showContent() +``` +More apis +```kotlin + ... + loading_view.showEmpty(...) + loading_view.showError(...) + ... +``` + +## New features on the way +watch this repo to stay updated + +# Developed By +* Peter Vincent - +# Donations +If you'd like to support this library development, you could buy me coffee here: +* [![Become a Patreon]("https://c6.patreon.com/becomePatronButton.bundle.js")](https://www.patreon.com/bePatron?u=31932751) + +Thank you very much in advance! + +#### Pull requests / Issues / Improvement requests Feel free to contribute and ask!
# License -#### Android Promise - Copyright 2018 Peter Vincent - Licensed under the Apache License, Version 2.0 (the "License"); + Licensed under the Apache License, Version 2.0 Android Promise; you may not use this file except in compliance with the License. You may obtain a copy of the License at diff --git a/build.gradle b/build.gradle index 47095cc..c41950d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,20 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.61' + ext.kotlin_version = '1.3.70' ext.supportLibVersion = "28.0.0" repositories { diff --git a/gradle.properties b/gradle.properties index d546dea..423f5fe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,16 @@ +# +# Copyright 2017, Peter Vincent +# Licensed under the Apache License, Version 2.0, Android Promise. +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://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. +# + # Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index eda838b..c671377 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,3 +1,16 @@ +# +# Copyright 2017, Peter Vincent +# Licensed under the Apache License, Version 2.0, Android Promise. +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://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. +# + #Tue Aug 27 22:34:34 EAT 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists diff --git a/promiseui/build.gradle b/promiseui/build.gradle index d77e3e9..c0cd545 100644 --- a/promiseui/build.gradle +++ b/promiseui/build.gradle @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + apply plugin: 'com.android.library' apply plugin: 'kotlin-android' @@ -7,7 +20,7 @@ android { buildToolsVersion '29.0.2' defaultConfig { - minSdkVersion 15 + minSdkVersion 16 targetSdkVersion 29 versionCode 1 versionName "1.0" @@ -31,19 +44,19 @@ dependencies { implementation 'androidx.exifinterface:exifinterface:1.1.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'com.github.android-promise:commons:1.0' - implementation 'io.reactivex.rxjava2:rxjava:2.2.12' + implementation 'com.github.android-promise:commons:1.1-alpha03' + implementation 'io.reactivex.rxjava2:rxjava:2.2.17' implementation 'com.github.tbruyelle:rxpermissions:0.10.2' implementation 'androidx.recyclerview:recyclerview:1.1.0' // For control over item selection of both touch and mouse driven selection - implementation "androidx.recyclerview:recyclerview-selection:1.1.0-beta01" + implementation "androidx.recyclerview:recyclerview-selection:1.1.0-rc01" implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'eu.davidea:flexible-adapter:5.1.0' implementation 'eu.davidea:flexible-adapter-ui:1.0.0' implementation 'eu.davidea:flexible-adapter-livedata:1.0.0-b3' // From 1.0.0-b3, library is compiled with data binding v2 implementation 'eu.davidea:flexible-adapter-databinding:1.0.0' - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13' androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } diff --git a/promiseui/src/androidTest/java/promise/ui/ExampleInstrumentedTest.java b/promiseui/src/androidTest/java/promise/ui/ExampleInstrumentedTest.java index a2064b4..54d16b3 100644 --- a/promiseui/src/androidTest/java/promise/ui/ExampleInstrumentedTest.java +++ b/promiseui/src/androidTest/java/promise/ui/ExampleInstrumentedTest.java @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.ui; import android.content.Context; diff --git a/promiseui/src/main/AndroidManifest.xml b/promiseui/src/main/AndroidManifest.xml index d222d45..0c292f0 100644 --- a/promiseui/src/main/AndroidManifest.xml +++ b/promiseui/src/main/AndroidManifest.xml @@ -1,3 +1,16 @@ + + diff --git a/promiseui/src/main/java/promise/ui/DataSource.java b/promiseui/src/main/java/promise/ui/DataSource.java deleted file mode 100644 index a6aafd4..0000000 --- a/promiseui/src/main/java/promise/ui/DataSource.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * - */ - -package promise.ui; - -import promise.commons.model.List; -import promise.commons.model.Result; - -/** - * @param - */ -public interface DataSource { - - /** - * @param response - * @param skip the offset index of data to load - * @param take, the number of items to load - */ - void load(Result, ?> response, int skip, int take); -} diff --git a/promiseui/src/main/java/promise/ui/PaginatedAdapter.java b/promiseui/src/main/java/promise/ui/PaginatedAdapter.java deleted file mode 100644 index 10d00a7..0000000 --- a/promiseui/src/main/java/promise/ui/PaginatedAdapter.java +++ /dev/null @@ -1,14 +0,0 @@ -package promise.ui; - -import promise.commons.model.List; - -public interface PaginatedAdapter { - - void add(List list); - - boolean hasLoader(); - - void addLoadingView(); - - void removeLoader(); -} diff --git a/promiseui/src/main/java/promise/ui/SearchableListDialog.java b/promiseui/src/main/java/promise/ui/SearchableListDialog.java index 9e1e849..dae530e 100644 --- a/promiseui/src/main/java/promise/ui/SearchableListDialog.java +++ b/promiseui/src/main/java/promise/ui/SearchableListDialog.java @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.ui; import android.app.AlertDialog; @@ -13,7 +26,6 @@ import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; -import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.SearchView; @@ -21,7 +33,7 @@ import java.io.Serializable; import java.util.List; -import promise.ui.model.Searchable; +import promise.ui.adapter.Searchable; public class SearchableListDialog extends DialogFragment implements @@ -168,12 +180,9 @@ private void setData(View rootView) { _listViewItems.setTextFilterEnabled(true); - _listViewItems.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - _searchableItem.onSearchableItemClicked(listAdapter.getItem(position), position); - getDialog().dismiss(); - } + _listViewItems.setOnItemClickListener((parent, view, position, id) -> { + _searchableItem.onSearchableItemClicked(listAdapter.getItem(position), position); + getDialog().dismiss(); }); } diff --git a/promiseui/src/main/java/promise/ui/SearchableSpinner.java b/promiseui/src/main/java/promise/ui/SearchableSpinner.java index d5ccd71..c741e03 100644 --- a/promiseui/src/main/java/promise/ui/SearchableSpinner.java +++ b/promiseui/src/main/java/promise/ui/SearchableSpinner.java @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.ui; import android.app.Activity; @@ -97,9 +110,7 @@ public void setAdapter(SpinnerAdapter adapter) { ArrayAdapter arrayAdapter = new ArrayAdapter(_context, android.R.layout .simple_list_item_1, new String[]{_strHintText}); super.setAdapter(arrayAdapter); - } else { - super.setAdapter(adapter); - } + } else super.setAdapter(adapter); } else { _isFromInit = false; diff --git a/promiseui/src/main/java/promise/ui/UIJobScheduler.kt b/promiseui/src/main/java/promise/ui/UIJobScheduler.kt index 46f8bfa..6847605 100644 --- a/promiseui/src/main/java/promise/ui/UIJobScheduler.kt +++ b/promiseui/src/main/java/promise/ui/UIJobScheduler.kt @@ -1,7 +1,22 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.ui +import android.os.Build import android.view.Choreographer -import promise.commons.Promise +import androidx.annotation.RequiresApi +import promise.commons.AndroidPromise import java.util.* object UIJobScheduler { @@ -13,22 +28,20 @@ object UIJobScheduler { fun submitJob(job: () -> Unit) { jobQueue.add(job) - if (jobQueue.size == 1) Promise.instance().executeOnUi { processJobs() } + if (jobQueue.size == 1) AndroidPromise.instance().executeOnUi { processJobs() } } private fun processJobs() { while (!jobQueue.isEmpty() && !isOverMaxTime) { val start = System.nanoTime() - jobQueue.poll().invoke() + with(jobQueue) { + poll().invoke() + } elapsed += System.nanoTime() - start } - if (jobQueue.isEmpty()) { + if (jobQueue.isEmpty()) elapsed = 0 else if (isOverMaxTime) onNextFrame { elapsed = 0 - } else if (isOverMaxTime) { - onNextFrame { - elapsed = 0 - processJobs() - } + processJobs() } } diff --git a/promiseui/src/main/java/promise/ui/Viewable.java b/promiseui/src/main/java/promise/ui/Viewable.java new file mode 100644 index 0000000..358cdb7 --- /dev/null +++ b/promiseui/src/main/java/promise/ui/Viewable.java @@ -0,0 +1,22 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + +package promise.ui; + +import androidx.annotation.LayoutRes; + +import promise.ui.adapter.ViewHolder; + +public interface Viewable extends ViewHolder { + @LayoutRes int layout(); +} \ No newline at end of file diff --git a/promiseui/src/main/java/promise/ui/AdapterDivider.java b/promiseui/src/main/java/promise/ui/adapter/AdapterDivider.java similarity index 97% rename from promiseui/src/main/java/promise/ui/AdapterDivider.java rename to promiseui/src/main/java/promise/ui/adapter/AdapterDivider.java index ee302af..33b7f5f 100644 --- a/promiseui/src/main/java/promise/ui/AdapterDivider.java +++ b/promiseui/src/main/java/promise/ui/adapter/AdapterDivider.java @@ -1,6 +1,6 @@ /* - * Copyright 2017, Solutech RMS - * Licensed under the Apache License, Version 2.0, "Solutech Limited". + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 @@ -11,7 +11,7 @@ * limitations under the License. */ -package promise.ui; +package promise.ui.adapter; import android.content.Context; import android.content.res.TypedArray; diff --git a/promiseui/src/main/java/promise/ui/adapter/DataSource.java b/promiseui/src/main/java/promise/ui/adapter/DataSource.java new file mode 100644 index 0000000..fa2f236 --- /dev/null +++ b/promiseui/src/main/java/promise/ui/adapter/DataSource.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + +package promise.ui.adapter; + +import promise.commons.model.List; +import promise.commons.tx.PromiseResult; + +/** + * @param + */ +public interface DataSource { + + /** + * @param response + * @param skip the offset index of data to load + * @param take, the number of items to load + */ + void load(PromiseResult, ?> response, int skip, int take); +} diff --git a/promiseui/src/main/java/promise/ui/DiffAdapter.kt b/promiseui/src/main/java/promise/ui/adapter/DiffAdapter.kt similarity index 87% rename from promiseui/src/main/java/promise/ui/DiffAdapter.kt rename to promiseui/src/main/java/promise/ui/adapter/DiffAdapter.kt index bda7569..c954aae 100644 --- a/promiseui/src/main/java/promise/ui/DiffAdapter.kt +++ b/promiseui/src/main/java/promise/ui/adapter/DiffAdapter.kt @@ -1,19 +1,17 @@ /* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. */ -package promise.ui +package promise.ui.adapter import android.annotation.SuppressLint import android.content.Context @@ -31,19 +29,17 @@ import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView -import promise.commons.Promise import promise.commons.data.log.LogUtil import promise.commons.model.List -import promise.commons.model.Result +import promise.commons.tx.PromiseResult import promise.commons.util.Conditions -import promise.ui.model.LoadingViewable -import promise.ui.model.Searchable -import promise.ui.model.Viewable -import promise.ui.model.ViewableInstance -import java.util.* +import promise.ui.UIJobScheduler +import promise.ui.Viewable import kotlin.reflect.KClass -open class DiffAdapter(list: List, var listener: Listener?, var args: Any?) : ListAdapter.Holder>(object : DiffUtil.ItemCallback() { +open class DiffAdapter(list: List, + var listener: Listener?, + var args: Any?) : ListAdapter.Holder>(object : DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: T, newItem: T): Boolean = oldItem == oldItem @SuppressLint("DiffUtilEquals") @@ -51,7 +47,7 @@ open class DiffAdapter(list: List, var listener: Listener?, var a oldItem.hashCode() == newItem.hashCode() }), PaginatedAdapter { - private val TAG = LogUtil.makeTag(DiffAdapter::class.java) + private val TAG: String = LogUtil.makeTag(DiffAdapter::class.java) private val AdapterItems = "__adapter_items__" private val indexer: Indexer private var list: List? = null @@ -121,8 +117,8 @@ open class DiffAdapter(list: List, var listener: Listener?, var a indexer.add(Conditions.checkNotNull(t)) } - infix fun unshift(t: T) { - indexer.unshift(Conditions.checkNotNull(t)) + infix fun unShift(t: T) { + indexer.unShift(Conditions.checkNotNull(t)) } override infix fun add(list: List) { @@ -214,10 +210,10 @@ open class DiffAdapter(list: List, var listener: Listener?, var a if (dataSource != null) { recyclerView.addOnScrollListener(PaginationListener(this, - dataSource!!,recyclerView.layoutManager!!, visibleThreshold)) + dataSource!!, recyclerView.layoutManager!!, visibleThreshold)) addLoadingView() - dataSource!!.load(Result, Throwable>() - .withCallBack { + dataSource!!.load(PromiseResult, Throwable>() + .withCallback { clear() this add it }, 0, visibleThreshold) @@ -378,7 +374,7 @@ open class DiffAdapter(list: List, var listener: Listener?, var a } } else { - val fields = List(Arrays.asList(*viewableInstance.viewable().javaClass.declaredFields)) + val fields = List(listOf(*viewableInstance.viewable().javaClass.declaredFields)) for (field in fields) try { val viewable = viewableInstance.viewable() @@ -412,22 +408,22 @@ open class DiffAdapter(list: List, var listener: Listener?, var a val instance = ViewableInstance(t) list!!.add(instance) if (reverse) list!!.reverse() - Promise.instance().executeOnUi { this@DiffAdapter.notifyDataSetChanged() } + UIJobScheduler.submitJob { this@DiffAdapter.notifyDataSetChanged() } } else { val instance = ViewableInstance(t) list!!.add(instance) - Promise.instance().executeOnUi { notifyItemInserted(0) } + UIJobScheduler.submitJob { notifyItemInserted(0) } } } - internal infix fun unshift(t: T) { + internal infix fun unShift(t: T) { if (list == null) list = List() if (!list!!.isEmpty()) { val list1 = List() list1.add(t) list1.addAll(list!!.map { (it as ViewableInstance).t }) setList(list1) - Promise.instance().executeOnUi { this@DiffAdapter.notifyDataSetChanged() } + UIJobScheduler.submitJob { this@DiffAdapter.notifyDataSetChanged() } } else { add(t) } @@ -435,14 +431,14 @@ open class DiffAdapter(list: List, var listener: Listener?, var a internal infix fun setList(list: List) { this@DiffAdapter.list = list.map { ViewableInstance(it) } - Promise.instance().executeOnUi { this@DiffAdapter.notifyDataSetChanged() } + UIJobScheduler.submitJob { this@DiffAdapter.notifyDataSetChanged() } } internal infix fun remove(t: T) { if (list == null) return val instance = list!!.find { i -> (i as ViewableInstance).t === t } list!!.remove(instance) - Promise.instance().executeOnUi { this@DiffAdapter.notifyDataSetChanged() } + UIJobScheduler.submitJob { this@DiffAdapter.notifyDataSetChanged() } } internal infix fun update(viewHolder: T) { @@ -456,7 +452,7 @@ open class DiffAdapter(list: List, var listener: Listener?, var a } internal fun updateAll() { - Promise.instance().executeOnUi { this@DiffAdapter.notifyDataSetChanged() } + UIJobScheduler.submitJob { this@DiffAdapter.notifyDataSetChanged() } } internal infix fun add(list: List) { @@ -466,7 +462,7 @@ open class DiffAdapter(list: List, var listener: Listener?, var a internal fun clear() { if (list == null || list!!.isEmpty()) return list!!.clear() - Promise.instance().executeOnUi { this@DiffAdapter.notifyDataSetChanged() } + UIJobScheduler.submitJob { this@DiffAdapter.notifyDataSetChanged() } } internal fun size(): Int = if (list == null || list!!.isEmpty()) 0 else list!!.size @@ -476,9 +472,7 @@ open class DiffAdapter(list: List, var listener: Listener?, var a } } - inner class WrapContentLinearLayoutManager : LinearLayoutManager { - - constructor(context: Context, orientation: Int, reverseLayout: Boolean) : super(context, orientation, reverseLayout) {} + inner class WrapContentLinearLayoutManager(context: Context, orientation: Int, reverseLayout: Boolean) : LinearLayoutManager(context, orientation, reverseLayout) { override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State) { try { diff --git a/promiseui/src/main/java/promise/ui/adapter/LoadingViewable.java b/promiseui/src/main/java/promise/ui/adapter/LoadingViewable.java new file mode 100644 index 0000000..c85e8ac --- /dev/null +++ b/promiseui/src/main/java/promise/ui/adapter/LoadingViewable.java @@ -0,0 +1,24 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + +package promise.ui.adapter; + +import android.view.View; + +import androidx.annotation.LayoutRes; + +public interface LoadingViewable { + @LayoutRes + int layout(); + void init(View view); +} diff --git a/promiseui/src/main/java/promise/ui/adapter/PaginatedAdapter.java b/promiseui/src/main/java/promise/ui/adapter/PaginatedAdapter.java new file mode 100644 index 0000000..904dca6 --- /dev/null +++ b/promiseui/src/main/java/promise/ui/adapter/PaginatedAdapter.java @@ -0,0 +1,27 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + +package promise.ui.adapter; + +import promise.commons.model.List; + +public interface PaginatedAdapter { + + void add(List list); + + boolean hasLoader(); + + void addLoadingView(); + + void removeLoader(); +} diff --git a/promiseui/src/main/java/promise/ui/PaginationListener.kt b/promiseui/src/main/java/promise/ui/adapter/PaginationListener.kt similarity index 81% rename from promiseui/src/main/java/promise/ui/PaginationListener.kt rename to promiseui/src/main/java/promise/ui/adapter/PaginationListener.kt index 2166c1f..dfcaa45 100644 --- a/promiseui/src/main/java/promise/ui/PaginationListener.kt +++ b/promiseui/src/main/java/promise/ui/adapter/PaginationListener.kt @@ -1,11 +1,24 @@ -package promise.ui +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + +package promise.ui.adapter import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.StaggeredGridLayoutManager import promise.commons.model.List -import promise.commons.model.Result +import promise.commons.tx.PromiseResult class PaginationListener(private val adapter: PaginatedAdapter, private val dataSource: DataSource, @@ -26,13 +39,10 @@ class PaginationListener(private val adapter: PaginatedAdapter, private infix fun getLastVisibleItem(lastVisibleItemPositions: IntArray): Int { var maxSize = 0 - for (i in lastVisibleItemPositions.indices) { - if (i == 0) { - maxSize = lastVisibleItemPositions[i] - } else if (lastVisibleItemPositions[i] > maxSize) { - maxSize = lastVisibleItemPositions[i] - } - } + for (i in lastVisibleItemPositions.indices) + if (i == 0) maxSize = lastVisibleItemPositions[i] + else if (lastVisibleItemPositions[i] > maxSize) + maxSize = lastVisibleItemPositions[i] return maxSize } @@ -76,8 +86,8 @@ class PaginationListener(private val adapter: PaginatedAdapter, view.adapter!!.itemCount > visibleThreshold) { // This condition will useful when recyclerview has less than visibleThreshold items currentPage += visibleThreshold adapter.addLoadingView() - dataSource.load(Result, Throwable>() - .withCallBack { + dataSource.load(PromiseResult, Throwable>() + .withCallback { adapter.add(it) }, currentPage, visibleThreshold) loading = true @@ -94,7 +104,6 @@ class PaginationListener(private val adapter: PaginatedAdapter, init { when (mLayoutManager) { is GridLayoutManager -> this.visibleThreshold *= mLayoutManager.spanCount - is StaggeredGridLayoutManager -> this.visibleThreshold *= mLayoutManager.spanCount } } diff --git a/promiseui/src/main/java/promise/ui/PromiseAdapter.kt b/promiseui/src/main/java/promise/ui/adapter/PromiseAdapter.kt similarity index 88% rename from promiseui/src/main/java/promise/ui/PromiseAdapter.kt rename to promiseui/src/main/java/promise/ui/adapter/PromiseAdapter.kt index e4de6d8..03f1e25 100644 --- a/promiseui/src/main/java/promise/ui/PromiseAdapter.kt +++ b/promiseui/src/main/java/promise/ui/adapter/PromiseAdapter.kt @@ -1,19 +1,17 @@ /* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. */ -package promise.ui +package promise.ui.adapter import android.content.Context import android.view.LayoutInflater @@ -28,24 +26,22 @@ import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import promise.commons.Promise import promise.commons.data.log.LogUtil import promise.commons.model.List -import promise.commons.model.Result +import promise.commons.tx.PromiseResult import promise.commons.util.Conditions -import promise.ui.model.LoadingViewable -import promise.ui.model.Searchable -import promise.ui.model.Viewable -import promise.ui.model.ViewableInstance +import promise.ui.UIJobScheduler +import promise.ui.Viewable import java.util.* import kotlin.reflect.KClass /** * Created by yoctopus on 11/6/17. */ -open class PromiseAdapter(list: List, var listener: Listener?, var args: Any?) : RecyclerView.Adapter.Holder>(), PaginatedAdapter{ +open class PromiseAdapter(list: List, + var listener: Listener?, var args: Any?) : RecyclerView.Adapter.Holder>(), PaginatedAdapter { - private val TAG = LogUtil.makeTag(PromiseAdapter::class.java) + private val TAG: String = LogUtil.makeTag(PromiseAdapter::class.java) private val AdapterItems = "__adapter_items__" private val indexer: Indexer private var list: List? = null @@ -83,9 +79,9 @@ open class PromiseAdapter(list: List, var listener: Listener?, va this.list!!.add(ViewableInstance(it)) } indexer = Indexer() + this.setHasStableIds(true) } - fun swipe(swipeListener: Swipe): PromiseAdapter { this.swipeListener = swipeListener return this @@ -115,7 +111,7 @@ open class PromiseAdapter(list: List, var listener: Listener?, va indexer.add(Conditions.checkNotNull(t)) } - infix fun unshift(t: T) { + infix fun unShift(t: T) { indexer.unshift(Conditions.checkNotNull(t)) } @@ -193,7 +189,7 @@ open class PromiseAdapter(list: List, var listener: Listener?, va if (viewHolder is PromiseAdapter<*>.Holder) { val response: Response = object : Response { override fun call() { - /*update(holder.viewHolder.getT());*/ + update(viewHolder.viewableInstance.t as T) } } when (direction) { @@ -210,8 +206,8 @@ open class PromiseAdapter(list: List, var listener: Listener?, va recyclerView.addOnScrollListener(PaginationListener(this, dataSource!!, recyclerView.layoutManager!!, visibleThreshold)) addLoadingView() - dataSource!!.load(Result, Throwable>() - .withCallBack { + dataSource!!.load(PromiseResult, Throwable>() + .withCallback { clear() this add it }, 0, visibleThreshold) @@ -378,7 +374,7 @@ open class PromiseAdapter(list: List, var listener: Listener?, va } } else { - val fields = List(Arrays.asList(*viewableInstance.viewable().javaClass.declaredFields)) + val fields = List(listOf(*viewableInstance.viewable().javaClass.declaredFields)) for (field in fields) try { val viewable = viewableInstance.viewable() @@ -412,11 +408,11 @@ open class PromiseAdapter(list: List, var listener: Listener?, va val instance = ViewableInstance(t) list!!.add(instance) if (reverse) list!!.reverse() - Promise.instance().executeOnUi { this@PromiseAdapter.notifyDataSetChanged() } + UIJobScheduler.submitJob { this@PromiseAdapter.notifyDataSetChanged() } } else { val instance = ViewableInstance(t) list!!.add(instance) - Promise.instance().executeOnUi { notifyItemInserted(0) } + UIJobScheduler.submitJob { notifyItemInserted(0) } } } @@ -427,7 +423,7 @@ open class PromiseAdapter(list: List, var listener: Listener?, va list1.add(t) list1.addAll(list!!.map { (it as ViewableInstance).t }) setList(list1) - Promise.instance().executeOnUi { this@PromiseAdapter.notifyDataSetChanged() } + UIJobScheduler.submitJob { this@PromiseAdapter.notifyDataSetChanged() } } else { add(t) } @@ -435,14 +431,14 @@ open class PromiseAdapter(list: List, var listener: Listener?, va internal infix fun setList(list: List) { this@PromiseAdapter.list = list.map { ViewableInstance(it) } - Promise.instance().executeOnUi { this@PromiseAdapter.notifyDataSetChanged() } + UIJobScheduler.submitJob { this@PromiseAdapter.notifyDataSetChanged() } } internal infix fun remove(t: T) { if (list == null) return val instance = list!!.find { i -> (i as ViewableInstance).t === t } list!!.remove(instance) - Promise.instance().executeOnUi { this@PromiseAdapter.notifyDataSetChanged() } + UIJobScheduler.submitJob { this@PromiseAdapter.notifyDataSetChanged() } } internal infix fun update(viewHolder: T) { @@ -456,7 +452,7 @@ open class PromiseAdapter(list: List, var listener: Listener?, va } internal fun updateAll() { - Promise.instance().executeOnUi { this@PromiseAdapter.notifyDataSetChanged() } + UIJobScheduler.submitJob { this@PromiseAdapter.notifyDataSetChanged() } } internal infix fun add(list: List) { @@ -466,7 +462,7 @@ open class PromiseAdapter(list: List, var listener: Listener?, va internal fun clear() { if (list == null || list!!.isEmpty()) return list!!.clear() - Promise.instance().executeOnUi { this@PromiseAdapter.notifyDataSetChanged() } + UIJobScheduler.submitJob { this@PromiseAdapter.notifyDataSetChanged() } } internal fun size(): Int = if (list == null || list!!.isEmpty()) 0 else list!!.size @@ -476,9 +472,7 @@ open class PromiseAdapter(list: List, var listener: Listener?, va } } - inner class WrapContentLinearLayoutManager : LinearLayoutManager { - - constructor(context: Context, orientation: Int, reverseLayout: Boolean) : super(context, orientation, reverseLayout) {} + inner class WrapContentLinearLayoutManager(context: Context, orientation: Int, reverseLayout: Boolean) : LinearLayoutManager(context, orientation, reverseLayout) { override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State) { try { diff --git a/promiseui/src/main/java/promise/ui/adapter/Searchable.java b/promiseui/src/main/java/promise/ui/adapter/Searchable.java new file mode 100644 index 0000000..cbd1ea3 --- /dev/null +++ b/promiseui/src/main/java/promise/ui/adapter/Searchable.java @@ -0,0 +1,22 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + +package promise.ui.adapter; + +/** + * Created by yoctopus on 11/21/17. + */ + +public interface Searchable { + boolean onSearch(String query); +} diff --git a/promiseui/src/main/java/promise/ui/adapter/ViewHolder.java b/promiseui/src/main/java/promise/ui/adapter/ViewHolder.java new file mode 100644 index 0000000..25891ee --- /dev/null +++ b/promiseui/src/main/java/promise/ui/adapter/ViewHolder.java @@ -0,0 +1,21 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + +package promise.ui.adapter; + +import android.view.View; + +public interface ViewHolder { + void init(View view); + void bind(View view, Object args); +} diff --git a/promiseui/src/main/java/promise/ui/adapter/ViewableEntity.java b/promiseui/src/main/java/promise/ui/adapter/ViewableEntity.java new file mode 100644 index 0000000..719951d --- /dev/null +++ b/promiseui/src/main/java/promise/ui/adapter/ViewableEntity.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + +package promise.ui.adapter; + +import androidx.annotation.LayoutRes; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import promise.ui.adapter.ViewHolder; + + +@Target(value = {ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface ViewableEntity { + + @LayoutRes int layoutResource(); + + Class viewHolderClass(); +} diff --git a/promiseui/src/main/java/promise/ui/model/ViewableInstance.kt b/promiseui/src/main/java/promise/ui/adapter/ViewableInstance.kt similarity index 62% rename from promiseui/src/main/java/promise/ui/model/ViewableInstance.kt rename to promiseui/src/main/java/promise/ui/adapter/ViewableInstance.kt index ed04051..40bc6f9 100644 --- a/promiseui/src/main/java/promise/ui/model/ViewableInstance.kt +++ b/promiseui/src/main/java/promise/ui/adapter/ViewableInstance.kt @@ -1,7 +1,21 @@ -package promise.ui.model +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + +package promise.ui.adapter import android.view.View import promise.commons.makeInstance +import promise.ui.Viewable import kotlin.reflect.KClass class ViewableInstance(val t: T) { @@ -20,17 +34,15 @@ class ViewableInstance(val t: T) { } t is LoadingViewable -> throw IllegalStateException("Data type must not implement LoadingViewable") t is Viewable -> t - (t as Any).javaClass.isAnnotationPresent(promise.ui.scopes.Viewable::class.java) -> { - val annotation = t.javaClass.getAnnotation(promise.ui.scopes.Viewable::class.java)!! + (t as Any).javaClass.isAnnotationPresent(ViewableEntity::class.java) -> { + val annotation = t.javaClass.getAnnotation(ViewableEntity::class.java)!! viewClass = annotation.viewHolderClass viewClassObject = makeInstance(viewClass!!, arrayOf(t as Any)) as ViewHolder object : Viewable { override fun layout(): Int = annotation.layoutResource - override fun init(view: View?) { (viewClassObject!! as ViewHolder).init(view) } - override fun bind(view: View?, args: Any?) { (viewClassObject!! as ViewHolder).bind(view, args) } diff --git a/promiseui/src/main/java/promise/ui/loading/ProgressLayout.java b/promiseui/src/main/java/promise/ui/loading/LoadingLayout.java similarity index 85% rename from promiseui/src/main/java/promise/ui/loading/ProgressLayout.java rename to promiseui/src/main/java/promise/ui/loading/LoadingLayout.java index 8bfe567..8fd22dd 100644 --- a/promiseui/src/main/java/promise/ui/loading/ProgressLayout.java +++ b/promiseui/src/main/java/promise/ui/loading/LoadingLayout.java @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.ui.loading; import android.content.Context; @@ -20,9 +33,9 @@ import java.util.List; import promise.ui.R; -import promise.ui.model.Viewable; +import promise.ui.Viewable; -public class ProgressLayout extends FrameLayout implements LoadingListener { +public class LoadingLayout extends FrameLayout implements LoadingListener { private final String CONTENT = "type_content"; private final String LOADING = "type_loading"; @@ -74,16 +87,16 @@ public class ProgressLayout extends FrameLayout implements LoadingListener { private String state = CONTENT; - public ProgressLayout(Context context) { + public LoadingLayout(Context context) { super(context); } - public ProgressLayout(Context context, AttributeSet attrs) { + public LoadingLayout(Context context, AttributeSet attrs) { super(context, attrs); init(attrs); } - public ProgressLayout(Context context, AttributeSet attrs, int defStyle) { + public LoadingLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(attrs); } @@ -91,7 +104,7 @@ public ProgressLayout(Context context, AttributeSet attrs, int defStyle) { private void init(AttributeSet attrs) { inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ProgressLayout); + TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.LoadingLayout); /*//Loading state attrs loadingStateProgressBarWidth = @@ -104,57 +117,57 @@ private void init(AttributeSet attrs) { typedArray.getColor(R.styleable.ProgressFrameLayout_loadingProgressBarColor, Color.RED);*/ loadingStateBackgroundColor = - typedArray.getColor(R.styleable.ProgressLayout_loadingBackgroundColor, Color.TRANSPARENT); + typedArray.getColor(R.styleable.LoadingLayout_loadingBackgroundColor, Color.TRANSPARENT); //Empty state attrs emptyStateImageWidth = - typedArray.getDimensionPixelSize(R.styleable.ProgressLayout_emptyImageWidth, 308); + typedArray.getDimensionPixelSize(R.styleable.LoadingLayout_emptyImageWidth, 308); emptyStateImageHeight = - typedArray.getDimensionPixelSize(R.styleable.ProgressLayout_emptyImageHeight, 308); + typedArray.getDimensionPixelSize(R.styleable.LoadingLayout_emptyImageHeight, 308); emptyStateTitleTextSize = - typedArray.getDimensionPixelSize(R.styleable.ProgressLayout_emptyTitleTextSize, 15); + typedArray.getDimensionPixelSize(R.styleable.LoadingLayout_emptyTitleTextSize, 15); emptyStateTitleTextColor = - typedArray.getColor(R.styleable.ProgressLayout_emptyTitleTextColor, Color.BLACK); + typedArray.getColor(R.styleable.LoadingLayout_emptyTitleTextColor, Color.BLACK); emptyStateContentTextSize = - typedArray.getDimensionPixelSize(R.styleable.ProgressLayout_emptyContentTextSize, 14); + typedArray.getDimensionPixelSize(R.styleable.LoadingLayout_emptyContentTextSize, 14); emptyStateContentTextColor = - typedArray.getColor(R.styleable.ProgressLayout_emptyContentTextColor, Color.BLACK); + typedArray.getColor(R.styleable.LoadingLayout_emptyContentTextColor, Color.BLACK); emptyStateBackgroundColor = - typedArray.getColor(R.styleable.ProgressLayout_emptyBackgroundColor, Color.TRANSPARENT); + typedArray.getColor(R.styleable.LoadingLayout_emptyBackgroundColor, Color.TRANSPARENT); //Error state attrs errorStateImageWidth = - typedArray.getDimensionPixelSize(R.styleable.ProgressLayout_errorImageWidth, 308); + typedArray.getDimensionPixelSize(R.styleable.LoadingLayout_errorImageWidth, 308); errorStateImageHeight = - typedArray.getDimensionPixelSize(R.styleable.ProgressLayout_errorImageHeight, 308); + typedArray.getDimensionPixelSize(R.styleable.LoadingLayout_errorImageHeight, 308); errorStateTitleTextSize = - typedArray.getDimensionPixelSize(R.styleable.ProgressLayout_errorTitleTextSize, 15); + typedArray.getDimensionPixelSize(R.styleable.LoadingLayout_errorTitleTextSize, 15); errorStateTitleTextColor = - typedArray.getColor(R.styleable.ProgressLayout_errorTitleTextColor, Color.BLACK); + typedArray.getColor(R.styleable.LoadingLayout_errorTitleTextColor, Color.BLACK); errorStateContentTextSize = - typedArray.getDimensionPixelSize(R.styleable.ProgressLayout_errorContentTextSize, 14); + typedArray.getDimensionPixelSize(R.styleable.LoadingLayout_errorContentTextSize, 14); errorStateContentTextColor = - typedArray.getColor(R.styleable.ProgressLayout_errorContentTextColor, Color.BLACK); + typedArray.getColor(R.styleable.LoadingLayout_errorContentTextColor, Color.BLACK); errorStateButtonTextColor = - typedArray.getColor(R.styleable.ProgressLayout_errorButtonTextColor, Color.BLACK); + typedArray.getColor(R.styleable.LoadingLayout_errorButtonTextColor, Color.BLACK); errorStateButtonBackgroundColor = - typedArray.getColor(R.styleable.ProgressLayout_errorButtonBackgroundColor, Color.WHITE); + typedArray.getColor(R.styleable.LoadingLayout_errorButtonBackgroundColor, Color.WHITE); errorStateBackgroundColor = - typedArray.getColor(R.styleable.ProgressLayout_errorBackgroundColor, Color.TRANSPARENT); + typedArray.getColor(R.styleable.LoadingLayout_errorBackgroundColor, Color.TRANSPARENT); typedArray.recycle(); @@ -182,7 +195,7 @@ public void showLoading(Object args) { loadingStateProgressBarColor = typedArray.getColor(R.styleable.ProgressFrameLayout_loadingProgressBarColor, Color.RED);*/ - showLoading(new LoadingViewable().loadingStateProgressBarHeight(108).loadingStateProgressBarWidth(108), args); + showLoading(new LoadingViewable().loadingStateProgressBarHeight(108).loadingStateProgressBarWidth(), args); } @Override diff --git a/promiseui/src/main/java/promise/ui/loading/LoadingListener.java b/promiseui/src/main/java/promise/ui/loading/LoadingListener.java index 0e63a21..a5f5886 100644 --- a/promiseui/src/main/java/promise/ui/loading/LoadingListener.java +++ b/promiseui/src/main/java/promise/ui/loading/LoadingListener.java @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.ui.loading; import android.graphics.drawable.Drawable; @@ -5,7 +18,7 @@ import java.util.List; -import promise.ui.model.Viewable; +import promise.ui.Viewable; public interface LoadingListener { diff --git a/promiseui/src/main/java/promise/ui/loading/LoadingViewable.java b/promiseui/src/main/java/promise/ui/loading/LoadingViewable.java index b37b9aa..80c6888 100644 --- a/promiseui/src/main/java/promise/ui/loading/LoadingViewable.java +++ b/promiseui/src/main/java/promise/ui/loading/LoadingViewable.java @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.ui.loading; import android.graphics.PorterDuff; @@ -5,14 +18,14 @@ import android.widget.ProgressBar; import promise.ui.R; -import promise.ui.model.Viewable; +import promise.ui.Viewable; public class LoadingViewable implements Viewable { - protected ProgressBar progressBarLoading; + private ProgressBar progressBarLoading; private int loadingStateProgressBarWidth = 0, loadingStateProgressBarHeight = 0, loadingStateProgressBarColor = 0; - public LoadingViewable loadingStateProgressBarWidth(int loadingStateProgressBarWidth) { - this.loadingStateProgressBarWidth = loadingStateProgressBarWidth; + LoadingViewable loadingStateProgressBarWidth() { + this.loadingStateProgressBarWidth = 108; return this; } diff --git a/promiseui/src/main/java/promise/ui/model/LoadingViewable.java b/promiseui/src/main/java/promise/ui/model/LoadingViewable.java deleted file mode 100644 index ff0c3c6..0000000 --- a/promiseui/src/main/java/promise/ui/model/LoadingViewable.java +++ /dev/null @@ -1,11 +0,0 @@ -package promise.ui.model; - -import android.view.View; - -import androidx.annotation.LayoutRes; - -public interface LoadingViewable { - @LayoutRes - int layout(); - void init(View view); -} diff --git a/promiseui/src/main/java/promise/ui/model/Searchable.java b/promiseui/src/main/java/promise/ui/model/Searchable.java deleted file mode 100644 index 0f90dad..0000000 --- a/promiseui/src/main/java/promise/ui/model/Searchable.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * - */ - -package promise.ui.model; - -/** - * Created by yoctopus on 11/21/17. - */ - -public interface Searchable { - boolean onSearch(String query); -} diff --git a/promiseui/src/main/java/promise/ui/model/ViewHolder.java b/promiseui/src/main/java/promise/ui/model/ViewHolder.java deleted file mode 100644 index 6f91b87..0000000 --- a/promiseui/src/main/java/promise/ui/model/ViewHolder.java +++ /dev/null @@ -1,8 +0,0 @@ -package promise.ui.model; - -import android.view.View; - -public interface ViewHolder { - void init(View view); - void bind(View view, Object args); -} diff --git a/promiseui/src/main/java/promise/ui/model/Viewable.java b/promiseui/src/main/java/promise/ui/model/Viewable.java deleted file mode 100644 index 8c9cc04..0000000 --- a/promiseui/src/main/java/promise/ui/model/Viewable.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * - */ - -package promise.ui.model; - -import androidx.annotation.LayoutRes; - -/** - * Created by yoctopus on 11/6/17. - */ - -public interface Viewable extends ViewHolder { - @LayoutRes int layout(); -} diff --git a/promiseui/src/main/java/promise/ui/notif/Duration.java b/promiseui/src/main/java/promise/ui/notif/Duration.java deleted file mode 100644 index a3d8f0c..0000000 --- a/promiseui/src/main/java/promise/ui/notif/Duration.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * - */ - -package promise.ui.notif; - -/** - * Created by yoctopus on 11/13/16. - */ - -public enum Duration { - LONG(1), - SHORT(2); - static final int LON = 1; - static final int SHO = 2; - private int length; - Duration(int length) { - this.length = length; - } - - public int getLength() { - return length; - } -} diff --git a/promiseui/src/main/java/promise/ui/notif/NToast.java b/promiseui/src/main/java/promise/ui/notif/NToast.java deleted file mode 100644 index 51ba0a4..0000000 --- a/promiseui/src/main/java/promise/ui/notif/NToast.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * - */ - -package promise.ui.notif; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.widget.Toast; - -import androidx.annotation.StringRes; - -/** - * Created by octopus on 10/26/16. - */ -class NToast { - - private Context context; - private String message; - private @StringRes - int messageId; - - @SuppressLint("InflateParams") - NToast(Context context, String message) { - this.context = context; - this.message = message; - } - - @SuppressLint("InflateParams") - NToast(Context context, @StringRes int message) { - this.context = context; - this.message = context.getString(message); - } - - void show() { - Toast.makeText(context, - message, - Toast.LENGTH_LONG).show(); - } -} diff --git a/promiseui/src/main/java/promise/ui/notif/NType.java b/promiseui/src/main/java/promise/ui/notif/NType.java deleted file mode 100644 index 64d60c1..0000000 --- a/promiseui/src/main/java/promise/ui/notif/NType.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * - */ - -package promise.ui.notif; - -/** - * Created by yoctopus on 11/13/16. - */ - -public enum NType { - WARNING(1), - ERROR(2), - FAILURE(3), - SUCCESS(4), - INFO(5); - static final int WARN = 1; - static final int ERR = 2; - static final int FAIL = 3; - static final int SUCC = 4; - static final int INF = 5; - private final int type; - - - - NType(int t) { - type = t; - } - - public int getType() { - return type; - } -} diff --git a/promiseui/src/main/java/promise/ui/notif/Notification.java b/promiseui/src/main/java/promise/ui/notification/Notification.java similarity index 69% rename from promiseui/src/main/java/promise/ui/notif/Notification.java rename to promiseui/src/main/java/promise/ui/notification/Notification.java index 455fc99..9b08171 100644 --- a/promiseui/src/main/java/promise/ui/notif/Notification.java +++ b/promiseui/src/main/java/promise/ui/notification/Notification.java @@ -1,19 +1,17 @@ /* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. */ -package promise.ui.notif; +package promise.ui.notification; import android.Manifest; import android.app.PendingIntent; @@ -33,11 +31,11 @@ public class Notification { private String TAG = LogUtil.makeTag(Notification.class); - private NType nType; - private Duration duration; + private NotificationType notificationType; + private ToastDuration toastDuration; private Context context; - private NDialog nDialog; + private NotificationDialog notificationDialog; private ProgressDialog progressDialog; public Notification(Context context) { @@ -47,39 +45,39 @@ public Notification(Context context) { public void showDialog( String title, String message, - NDialog.DButton positive, - NDialog.DButton negative, - NDialog.DButton neutral) { + NotificationDialog.DialogButton positive, + NotificationDialog.DialogButton negative, + NotificationDialog.DialogButton neutral) { - NDialog nDialog = new NDialog(getContext(), title, message, positive, negative, neutral); + NotificationDialog notificationDialog = new NotificationDialog(getContext(), title, message, positive, negative, neutral); - nDialog.show(); + notificationDialog.show(); } public void showDialog( String title, String message, - NDialog.DButton positive, - NDialog.DButton negative, - NDialog.DButton neutral, + NotificationDialog.DialogButton positive, + NotificationDialog.DialogButton negative, + NotificationDialog.DialogButton neutral, boolean close) { - NDialog nDialog = - new NDialog(getContext(), title, message, positive, negative, neutral).close(close); + NotificationDialog notificationDialog = + new NotificationDialog(getContext(), title, message, positive, negative, neutral).close(close); - nDialog.show(); + notificationDialog.show(); } public void showDialog( String title, String message, - NDialog.DButton positive, - NDialog.DButton negative, - NDialog.DButton neutral, - NDialog.OnAnswer onAnswer) { + NotificationDialog.DialogButton positive, + NotificationDialog.DialogButton negative, + NotificationDialog.DialogButton neutral, + NotificationDialog.OnAnswer onAnswer) { - nDialog = new NDialog(getContext(), title, message, positive, negative, neutral, onAnswer); - nDialog.show(); + notificationDialog = new NotificationDialog(getContext(), title, message, positive, negative, neutral, onAnswer); + notificationDialog.show(); } public void showProgress(String message) { @@ -150,8 +148,8 @@ public void showProgress(String title, String message, int percent) { } public void dismiss() { - if (nDialog != null) { - nDialog.dismiss(); + if (notificationDialog != null) { + notificationDialog.dismiss(); } if (progressDialog != null) { progressDialog.dismiss(); @@ -159,12 +157,12 @@ public void dismiss() { } public void showToast(String message) { - NToast toast = new NToast(getContext(), message); + NotificationToast toast = new NotificationToast(getContext(), message); toast.show(); } - public void showToast(String message, Duration duration) { - NToast toast = new NToast(getContext(), message); + public void showToast(String message, ToastDuration toastDuration) { + NotificationToast toast = new NotificationToast(getContext(), message); toast.show(); } @@ -197,15 +195,15 @@ public void onFailure(String permission) {} } } - public void vibrate(Duration duration) { + public void vibrate(ToastDuration toastDuration) { final int length; - switch (duration.getLength()) { - case Duration.LON: + switch (toastDuration.getLength()) { + case ToastDuration.LON: { length = 1000; break; } - case Duration.SHO: + case ToastDuration.SHO: { length = 500; break; @@ -240,12 +238,12 @@ public void showNotification( String message, @DrawableRes int small_icon, PendingIntent pendingIntent) { - NBar.notify(getContext(), title, message, bitmap, small_icon, pendingIntent); + StatusBarNotification.notify(getContext(), title, message, bitmap, small_icon, pendingIntent); } public void showNotification( Bitmap bitmap, String title, String message, @DrawableRes int small_icon, int progress) { - NBar.notifyWithProgress(getContext(), title, message, bitmap, small_icon, progress); + StatusBarNotification.notifyWithProgress(getContext(), title, message, bitmap, small_icon, progress); } public Context getContext() { diff --git a/promiseui/src/main/java/promise/ui/notif/NDialog.java b/promiseui/src/main/java/promise/ui/notification/NotificationDialog.java similarity index 71% rename from promiseui/src/main/java/promise/ui/notif/NDialog.java rename to promiseui/src/main/java/promise/ui/notification/NotificationDialog.java index 54853ad..58565b9 100644 --- a/promiseui/src/main/java/promise/ui/notif/NDialog.java +++ b/promiseui/src/main/java/promise/ui/notification/NotificationDialog.java @@ -1,73 +1,73 @@ /* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. */ -package promise.ui.notif; +package promise.ui.notification; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; +import android.os.Build; import android.view.View; import android.view.Window; import androidx.annotation.StringRes; -public class NDialog extends AlertDialog { +public class NotificationDialog extends AlertDialog { private String title, message; - private DButton positive, negative, neutral; + private DialogButton positive, negative, neutral; private CListener cListener; private OnAnswer listener; private boolean close = true; - public NDialog( + public NotificationDialog( Context context, String title, String message, - DButton positive, - DButton negative, - DButton neutral) { + DialogButton positive, + DialogButton negative, + DialogButton neutral) { super(context); this.title = title; this.message = message; this.positive = positive; this.negative = negative; this.neutral = neutral; - requestWindowFeature(Window.FEATURE_SWIPE_TO_DISMISS); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) + requestWindowFeature(Window.FEATURE_SWIPE_TO_DISMISS); requestWindowFeature(Window.FEATURE_NO_TITLE); setCanceledOnTouchOutside(true); } - public NDialog( + public NotificationDialog( Context context, String title, String message, - DButton positive, - DButton negative, - DButton neutral, + DialogButton positive, + DialogButton negative, + DialogButton neutral, OnAnswer listener) { this(context, title, message, positive, negative, neutral); this.listener = listener; } - public NDialog( + public NotificationDialog( Context context, @StringRes int title, @StringRes int message, - DButton positive, - DButton negative, - DButton neutral) { + DialogButton positive, + DialogButton negative, + DialogButton neutral) { this( context, context.getResources().getString(title), @@ -81,7 +81,7 @@ public void setcListener(CListener cListener) { this.cListener = cListener; } - public NDialog close(boolean close) { + public NotificationDialog close(boolean close) { this.close = close; return this; } @@ -142,16 +142,16 @@ public interface OnAnswer { void onAnswer(String t); } - public static class DButton { + public static class DialogButton { private String text = ""; private int textId = 0; private BListener listener; - public DButton(String text, BListener listener) { + public DialogButton(String text, BListener listener) { this.text = text; this.listener = listener; } - public DButton(@StringRes int text, BListener listener) { + public DialogButton(@StringRes int text, BListener listener) { this.textId = text; this.listener = listener; } diff --git a/promiseui/src/main/java/promise/ui/notification/NotificationToast.java b/promiseui/src/main/java/promise/ui/notification/NotificationToast.java new file mode 100644 index 0000000..79ee0a5 --- /dev/null +++ b/promiseui/src/main/java/promise/ui/notification/NotificationToast.java @@ -0,0 +1,46 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + +package promise.ui.notification; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.widget.Toast; + +import androidx.annotation.StringRes; + +class NotificationToast { + + private Context context; + private String message; + private @StringRes + int messageId; + + @SuppressLint("InflateParams") + NotificationToast(Context context, String message) { + this.context = context; + this.message = message; + } + + @SuppressLint("InflateParams") + NotificationToast(Context context, @StringRes int message) { + this.context = context; + this.message = context.getString(message); + } + + void show() { + Toast.makeText(context, + message, + Toast.LENGTH_LONG).show(); + } +} diff --git a/promiseui/src/main/java/promise/ui/notification/NotificationType.java b/promiseui/src/main/java/promise/ui/notification/NotificationType.java new file mode 100644 index 0000000..b195c5b --- /dev/null +++ b/promiseui/src/main/java/promise/ui/notification/NotificationType.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + +package promise.ui.notification; + +/** + * Created by yoctopus on 11/13/16. + */ + +public enum NotificationType { + WARNING(1), + ERROR(2), + FAILURE(3), + SUCCESS(4), + INFO(5); + static final int WARN = 1; + static final int ERR = 2; + static final int FAIL = 3; + static final int SUCC = 4; + static final int INF = 5; + private final int type; + + NotificationType(int t) { + type = t; + } + + public int getType() { + return type; + } +} diff --git a/promiseui/src/main/java/promise/ui/notif/NBar.java b/promiseui/src/main/java/promise/ui/notification/StatusBarNotification.java similarity index 71% rename from promiseui/src/main/java/promise/ui/notif/NBar.java rename to promiseui/src/main/java/promise/ui/notification/StatusBarNotification.java index 2f30473..6fb4526 100644 --- a/promiseui/src/main/java/promise/ui/notif/NBar.java +++ b/promiseui/src/main/java/promise/ui/notification/StatusBarNotification.java @@ -1,19 +1,17 @@ /* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. */ -package promise.ui.notif; +package promise.ui.notification; import android.annotation.TargetApi; import android.app.Notification; @@ -27,11 +25,11 @@ import androidx.annotation.DrawableRes; import androidx.core.app.NotificationCompat; -class NBar { +class StatusBarNotification { private static final String NOTIFICATION_TAG = "Promise_Message"; private static String GROUP_KEY = "promise.GROUP_NOTIFICATION"; private static int id_normal; - private static NotificationManager notifManager; + private static NotificationManager notificationManager; static void notify(final Context context, String title, @@ -40,16 +38,18 @@ static void notify(final Context context, @DrawableRes int small, PendingIntent pendingIntent) { NotificationCompat.Builder builder; - if (notifManager == null) - notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + if (notificationManager == null) + notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { int importance = NotificationManager.IMPORTANCE_DEFAULT; - NotificationChannel mChannel = notifManager.getNotificationChannel("normal_channel_id"); + NotificationChannel mChannel = null; + if (notificationManager != null) + mChannel = notificationManager.getNotificationChannel("normal_channel_id"); if (mChannel == null) { mChannel = new NotificationChannel("normal_channel_id", title, importance); mChannel.enableVibration(true); mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}); - notifManager.createNotificationChannel(mChannel); + notificationManager.createNotificationChannel(mChannel); } builder = new NotificationCompat.Builder(context, "normal_channel_id"); builder.setContentTitle(message) @@ -85,16 +85,18 @@ static void notifyWithProgress(final Context context, @DrawableRes int small, int progress) { NotificationCompat.Builder builder; - if (notifManager == null) - notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + if (notificationManager == null) + notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { int importance = NotificationManager.IMPORTANCE_DEFAULT; - NotificationChannel mChannel = notifManager.getNotificationChannel("progress_channel_id"); + NotificationChannel mChannel = null; + if (notificationManager != null) + mChannel = notificationManager.getNotificationChannel("progress_channel_id"); if (mChannel == null) { mChannel = new NotificationChannel("progress_channel_id", title, importance); mChannel.enableVibration(true); mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}); - notifManager.createNotificationChannel(mChannel); + notificationManager.createNotificationChannel(mChannel); } builder = new NotificationCompat.Builder(context, "progress_channel_id"); builder.setContentTitle(message) @@ -125,9 +127,9 @@ static void notifyWithProgress(final Context context, @TargetApi(Build.VERSION_CODES.ECLAIR) private static void notify(final Context context, final Notification notification) { - final NotificationManager nm = (NotificationManager) context + final NotificationManager notificationManager = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); - nm.notify(NOTIFICATION_TAG, + if (notificationManager != null) notificationManager.notify(NOTIFICATION_TAG, id_normal, notification); id_normal++; @@ -136,9 +138,9 @@ private static void notify(final Context context, @TargetApi(Build.VERSION_CODES.ECLAIR) private static void notify(int id, final Context context, final Notification notification) { - final NotificationManager nm = (NotificationManager) context + final NotificationManager notificationManager = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); - nm.notify(NOTIFICATION_TAG, + if (notificationManager != null) notificationManager.notify(NOTIFICATION_TAG, id, notification); } diff --git a/promiseui/src/main/java/promise/ui/notification/ToastDuration.java b/promiseui/src/main/java/promise/ui/notification/ToastDuration.java new file mode 100644 index 0000000..66a7a78 --- /dev/null +++ b/promiseui/src/main/java/promise/ui/notification/ToastDuration.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + +package promise.ui.notification; + + +public enum ToastDuration { + LONG(1), + SHORT(2); + static final int LON = 1; + static final int SHO = 2; + private int length; + ToastDuration(int length) { + this.length = length; + } + + public int getLength() { + return length; + } +} diff --git a/promiseui/src/main/java/promise/ui/scopes/Viewable.java b/promiseui/src/main/java/promise/ui/scopes/Viewable.java deleted file mode 100644 index d743b09..0000000 --- a/promiseui/src/main/java/promise/ui/scopes/Viewable.java +++ /dev/null @@ -1,22 +0,0 @@ -package promise.ui.scopes; - -import androidx.annotation.LayoutRes; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import promise.ui.model.ViewHolder; - - -@Target(value = {ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Viewable { - - @LayoutRes int layoutResource() default 0; - - Class viewHolderClass() default ViewHolder.class; -} diff --git a/promiseui/src/main/java/promise/ui/utils/ApiHelper.java b/promiseui/src/main/java/promise/ui/utils/ApiHelper.java index 5605a98..a282c1c 100644 --- a/promiseui/src/main/java/promise/ui/utils/ApiHelper.java +++ b/promiseui/src/main/java/promise/ui/utils/ApiHelper.java @@ -1,16 +1,14 @@ /* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. */ package promise.ui.utils; @@ -40,7 +38,7 @@ import com.tbruyelle.rxpermissions2.RxPermissions; -import promise.commons.Promise; +import promise.commons.AndroidPromise; import promise.commons.model.List; import promise.commons.util.ClassUtil; import promise.commons.util.Conditions; @@ -48,7 +46,7 @@ public class ApiHelper { public static boolean isGooglePlayInstalled() { - PackageManager pm = Promise.instance().context().getPackageManager(); + PackageManager pm = AndroidPromise.instance().context().getPackageManager(); boolean app_installed; try { PackageInfo info = pm.getPackageInfo( @@ -56,9 +54,8 @@ public static boolean isGooglePlayInstalled() { PackageManager.GET_ACTIVITIES); String label = (String) info.applicationInfo.loadLabel(pm); - app_installed = (label != null - && label.equals( - "Google Play Store")); + app_installed = label.equals( + "Google Play Store"); } catch (PackageManager.NameNotFoundException e) { app_installed = false; } @@ -212,11 +209,13 @@ public static void requestPermission(FragmentActivity activity, final CallBack callBack, final String permission) { RxPermissions rxPermissions = new RxPermissions(activity); - rxPermissions.request(permission) + AndroidPromise.instance().getCompositeDisposable().add( + rxPermissions.request(permission) .subscribe(aBoolean -> { if (aBoolean) callBack.onSuccess(permission); else callBack.onFailure(permission); - }); + }) + ); } @@ -242,23 +241,23 @@ public static void enableStrictMode(Class classs) { } public static boolean hasFroyo() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO; + return true; } public static boolean hasGingerbread() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD; + return true; } public static boolean hasHoneycomb() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; + return true; } public static boolean hasHoneycombMR1() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1; + return true; } public static boolean hasICS() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH; + return true; } public static boolean hasJellyBean() { @@ -282,7 +281,7 @@ public static boolean hasNougat() { } public static boolean supportsPreferenceHeaders() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; + return true; } public interface VERSION_CODES { @@ -301,16 +300,16 @@ public interface VERSION_CODES { } public static final boolean HAS_ACTION_BAR_HOME_BUTTON = - Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + true; public static final boolean HAS_ICS = - Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + true; public static final boolean USE_888_PIXEL_FORMAT = Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; public static final boolean ENABLE_PHOTO_EDITOR = - Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + true; public static final boolean HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE = ClassUtil.hasField(View.class, "SYSTEM_UI_FLAG_LAYOUT_STABLE"); @@ -325,7 +324,7 @@ public interface VERSION_CODES { Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; public static final boolean HAS_REUSING_BITMAP_IN_BITMAP_FACTORY = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; public static final boolean HAS_SET_BEAM_PUSH_URIS = Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; @@ -338,19 +337,19 @@ public interface VERSION_CODES { "android.graphics.SurfaceTexture", "release"); public static final boolean HAS_SURFACE_TEXTURE = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; public static final boolean HAS_MTP = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1; + true; public static final boolean HAS_AUTO_FOCUS_MOVE_CALLBACK = Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; public static final boolean HAS_REMOTE_VIEWS_SERVICE = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; public static final boolean HAS_INTENT_EXTRA_LOCAL_ONLY = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; public static final boolean HAS_SET_SYSTEM_UI_VISIBILITY = ClassUtil.hasMethod(View.class, "setSystemUiVisibility", int.class); @@ -380,25 +379,26 @@ public interface VERSION_CODES { Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; public static final boolean HAS_OLD_PANORAMA = - Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + true; public static final boolean HAS_TIME_LAPSE_RECORDING = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; public static final boolean HAS_ZOOM_WHEN_RECORDING = - Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + true; public static final boolean HAS_CAMERA_FOCUS_AREA = - Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + true; public static final boolean HAS_CAMERA_METERING_AREA = - Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + true + ; public static final boolean HAS_FINE_RESOLUTION_QUALITY_LEVELS = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; public static final boolean HAS_MOTION_EVENT_TRANSFORM = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; public static final boolean HAS_EFFECTS_RECORDING = false; @@ -407,35 +407,35 @@ public interface VERSION_CODES { Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1; public static final boolean HAS_GET_SUPPORTED_VIDEO_SIZE = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; public static final boolean HAS_SET_ICON_ATTRIBUTE = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; public static final boolean HAS_MEDIA_PROVIDER_FILES_TABLE = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; public static final boolean HAS_SURFACE_TEXTURE_RECORDING = Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; public static final boolean HAS_ACTION_BAR = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; // Ex: View.setTranslationX. public static final boolean HAS_VIEW_TRANSFORM_PROPERTIES = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; public static final boolean HAS_CAMERA_HDR = Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1; public static final boolean HAS_OPTIONS_IN_MUTABLE = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + true; public static final boolean CAN_START_PREVIEW_IN_JPEG_CALLBACK = - Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + true; public static final boolean HAS_VIEW_PROPERTY_ANIMATOR = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1; + true; public static final boolean HAS_POST_ON_ANIMATION = Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; @@ -447,8 +447,8 @@ public interface CallBack { public static String getAppVersionCode() { try { - PackageInfo packageInfo = Promise.instance().context() - .getPackageManager().getPackageInfo(Promise.instance().context().getPackageName(), 0); + PackageInfo packageInfo = AndroidPromise.instance().context() + .getPackageManager().getPackageInfo(AndroidPromise.instance().context().getPackageName(), 0); return String.valueOf(packageInfo.versionName); } catch (PackageManager.NameNotFoundException e) { return ""; diff --git a/promiseui/src/main/java/promise/ui/utils/BitmapUtil.java b/promiseui/src/main/java/promise/ui/utils/BitmapUtil.java index 2b7aa34..8a64de7 100644 --- a/promiseui/src/main/java/promise/ui/utils/BitmapUtil.java +++ b/promiseui/src/main/java/promise/ui/utils/BitmapUtil.java @@ -1,16 +1,14 @@ /* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. */ package promise.ui.utils; @@ -24,6 +22,7 @@ import android.graphics.Matrix; import android.graphics.Paint; import android.net.Uri; +import android.os.Build; import android.os.ParcelFileDescriptor; import android.provider.MediaStore; import android.util.Base64; @@ -63,7 +62,8 @@ public static Bitmap getBitmap(@NonNull Context context, @DrawableRes int id) { public static void addImageToGallery(final String filePath, final Context context) { ContentValues values = new ContentValues(); - values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) + values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); values.put(MediaStore.MediaColumns.DATA, filePath); context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); @@ -102,17 +102,15 @@ public static String getPathFromGooglePhotosUri(Context context, Uri uriPhoto) { FileOutputStream output = null; try { ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uriPhoto, "r"); - FileDescriptor fd = pfd.getFileDescriptor(); + FileDescriptor fd = null; + if (pfd != null) fd = pfd.getFileDescriptor(); input = new FileInputStream(fd); - String tempFilename = getTempFilename(context); output = new FileOutputStream(tempFilename); int read; byte[] bytes = new byte[4096]; - while ((read = input.read(bytes)) != -1) { - output.write(bytes, 0, read); - } + while ((read = input.read(bytes)) != -1) output.write(bytes, 0, read); return tempFilename; } catch (IOException ignored) { // Nothing we can do @@ -184,7 +182,7 @@ public static Bitmap bitmap(String imgPath, int size) { return null; } ByteArrayOutputStream bos = new ByteArrayOutputStream(); - b.compress(Bitmap.CompressFormat.JPEG, 50, bos); + if (b != null) b.compress(Bitmap.CompressFormat.JPEG, 50, bos); return b; } diff --git a/promiseui/src/main/java/promise/ui/utils/DimenUtil.java b/promiseui/src/main/java/promise/ui/utils/DimenUtil.java index 0e68156..5dec20b 100644 --- a/promiseui/src/main/java/promise/ui/utils/DimenUtil.java +++ b/promiseui/src/main/java/promise/ui/utils/DimenUtil.java @@ -1,16 +1,14 @@ /* - * - * * Copyright 2017, Peter Vincent - * * Licensed under the Apache License, Version 2.0, Promise. - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * http://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. - * + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. */ package promise.ui.utils; diff --git a/promiseui/src/main/res/layout/loading_viewable.xml b/promiseui/src/main/res/layout/loading_viewable.xml index 127b2cc..6fb915c 100644 --- a/promiseui/src/main/res/layout/loading_viewable.xml +++ b/promiseui/src/main/res/layout/loading_viewable.xml @@ -1,4 +1,17 @@ + + + + + + + + + + + + - + diff --git a/promiseui/src/main/res/values/strings.xml b/promiseui/src/main/res/values/strings.xml index 9572f94..2f07110 100644 --- a/promiseui/src/main/res/values/strings.xml +++ b/promiseui/src/main/res/values/strings.xml @@ -1,3 +1,16 @@ + + PromiseUI Try Again diff --git a/promiseui/src/test/java/promise/ui/ExampleUnitTest.java b/promiseui/src/test/java/promise/ui/ExampleUnitTest.java index 37c7303..835f3e9 100644 --- a/promiseui/src/test/java/promise/ui/ExampleUnitTest.java +++ b/promiseui/src/test/java/promise/ui/ExampleUnitTest.java @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.ui; import org.junit.Test; diff --git a/settings.gradle b/settings.gradle index 2085105..2d93b96 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,14 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + include 'promiseui', 'uiapp' diff --git a/uiapp/build.gradle b/uiapp/build.gradle index 24d8fbe..b7e8587 100644 --- a/uiapp/build.gradle +++ b/uiapp/build.gradle @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' @@ -12,6 +25,7 @@ android { targetSdkVersion 29 versionCode 1 versionName "1.0" + multiDexEnabled = true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -30,17 +44,17 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'androidx.core:core-ktx:1.1.0' - implementation 'com.github.android-promise:commons:1.0' + implementation 'androidx.core:core-ktx:1.2.0' + implementation 'com.github.android-promise:commons:1.1-alpha03' implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'io.reactivex.rxjava2:rxjava:2.2.12' + implementation 'io.reactivex.rxjava2:rxjava:2.2.17' implementation 'androidx.recyclerview:recyclerview:1.1.0' // For control over item selection of both touch and mouse driven selection - implementation "androidx.recyclerview:recyclerview-selection:1.1.0-beta01" + implementation "androidx.recyclerview:recyclerview-selection:1.1.0-rc01" implementation 'com.facebook.shimmer:shimmer:0.5.0@aar' implementation project(path: ':promiseui') implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13' androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } diff --git a/uiapp/src/androidTest/java/promise/uiapp/ExampleInstrumentedTest.kt b/uiapp/src/androidTest/java/promise/uiapp/ExampleInstrumentedTest.kt index cb9b996..8869930 100644 --- a/uiapp/src/androidTest/java/promise/uiapp/ExampleInstrumentedTest.kt +++ b/uiapp/src/androidTest/java/promise/uiapp/ExampleInstrumentedTest.kt @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.uiapp import androidx.test.InstrumentationRegistry diff --git a/uiapp/src/main/AndroidManifest.xml b/uiapp/src/main/AndroidManifest.xml index 2e43dd9..91b90f3 100644 --- a/uiapp/src/main/AndroidManifest.xml +++ b/uiapp/src/main/AndroidManifest.xml @@ -1,4 +1,17 @@ + + diff --git a/uiapp/src/main/java/promise/uiapp/App.kt b/uiapp/src/main/java/promise/uiapp/App.kt index 27ea768..3cf752f 100644 --- a/uiapp/src/main/java/promise/uiapp/App.kt +++ b/uiapp/src/main/java/promise/uiapp/App.kt @@ -1,11 +1,24 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.uiapp import android.app.Application -import promise.commons.Promise +import promise.commons.AndroidPromise class App: Application() { override fun onCreate() { super.onCreate() - Promise.init(this, 2) + AndroidPromise.init(this, 2, BuildConfig.DEBUG) } } \ No newline at end of file diff --git a/uiapp/src/main/java/promise/uiapp/MainActivity.kt b/uiapp/src/main/java/promise/uiapp/MainActivity.kt index 383c886..04c9bb2 100644 --- a/uiapp/src/main/java/promise/uiapp/MainActivity.kt +++ b/uiapp/src/main/java/promise/uiapp/MainActivity.kt @@ -1,18 +1,32 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.uiapp import android.os.Bundle import android.text.Editable import android.text.TextWatcher +import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.collection.ArrayMap import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.synthetic.main.activity_main.* -import promise.commons.Promise +import promise.commons.AndroidPromise import promise.commons.data.log.LogUtil import promise.commons.model.List -import promise.ui.PromiseAdapter -import promise.ui.model.Viewable +import promise.ui.adapter.PromiseAdapter +import promise.ui.Viewable import promise.uiapp.models.ViewablePoJo import promise.uiapp.models.ViewablePoJoViewable import kotlin.reflect.KClass @@ -57,12 +71,15 @@ class MainActivity : AppCompatActivity(), PromiseAdapter.Listener recycler_view.adapter = adapter + loading_view.showLoading(null) + loading_view.showContent() + adapter.add(List.generate(10) { ViewablePoJo("test $it") }) - Promise.instance().executeOnUi({ + AndroidPromise.instance().executeOnUi({ adapter.args = null adapter setList List.generate(50) { @@ -71,3 +88,17 @@ class MainActivity : AppCompatActivity(), PromiseAdapter.Listener }, 5000) } } + +class LoadingViewable(private val message: String): Viewable { + override fun layout(): Int { + return R.layout.loading_viewable + } + + override fun init(view: View?) { + // init loading layout views + } + + override fun bind(view: View?, args: Any?) { + // bind message to the views + } +} \ No newline at end of file diff --git a/uiapp/src/main/java/promise/uiapp/models/ViewablePoJo.kt b/uiapp/src/main/java/promise/uiapp/models/ViewablePoJo.kt index b378447..6e5ff80 100644 --- a/uiapp/src/main/java/promise/uiapp/models/ViewablePoJo.kt +++ b/uiapp/src/main/java/promise/uiapp/models/ViewablePoJo.kt @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.uiapp.models import android.annotation.SuppressLint @@ -5,11 +18,13 @@ import android.view.View import android.widget.ImageView import android.widget.TextView import com.facebook.shimmer.ShimmerFrameLayout -import promise.ui.model.Searchable -import promise.ui.model.ViewHolder +import promise.ui.Viewable +import promise.ui.adapter.Searchable +import promise.ui.adapter.ViewHolder +import promise.ui.adapter.ViewableEntity import promise.uiapp.R -class ViewablePoJoViewable(private val viewablePoJo: ViewablePoJo) : promise.ui.model.Viewable { +class ViewablePoJoViewable(private val viewablePoJo: ViewablePoJo) : Viewable { lateinit var imageView: ImageView lateinit var textView: TextView @@ -48,8 +63,22 @@ class ViewablePoJoViewHolder(private val viewablePoJo: ViewablePoJo) : ViewHolde lateinit var textView: TextView } -//@Viewable(layoutResource = R.layout.pojo_layout, viewHolderClass = ViewablePoJoViewHolder::class) +@ViewableEntity(layoutResource = R.layout.pojo_layout, viewHolderClass = ViewablePoJoViewHolder::class) class ViewablePoJo(val text: String): Searchable { @SuppressLint("DefaultLocale") override fun onSearch(query: String): Boolean = text.toLowerCase().contains(query.toLowerCase()) +} + +class ImplementingViewable(): Viewable { + override fun layout(): Int { + return R.layout.pojo_layout + } + + override fun init(view: View?) { + // initialize the views + } + + override fun bind(view: View?, args: Any?) { + //bind data to the views + } } \ No newline at end of file diff --git a/uiapp/src/main/res/drawable-v24/ic_launcher_foreground.xml b/uiapp/src/main/res/drawable-v24/ic_launcher_foreground.xml index 1f6bb29..0d1d165 100644 --- a/uiapp/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ b/uiapp/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -1,3 +1,16 @@ + + + + + + + - - + \ No newline at end of file diff --git a/uiapp/src/main/res/layout/loading.xml b/uiapp/src/main/res/layout/loading.xml index f5e96e2..2bf8cd8 100644 --- a/uiapp/src/main/res/layout/loading.xml +++ b/uiapp/src/main/res/layout/loading.xml @@ -1,4 +1,17 @@ + + diff --git a/uiapp/src/main/res/layout/pojo_layout.xml b/uiapp/src/main/res/layout/pojo_layout.xml index acfae97..83de32b 100644 --- a/uiapp/src/main/res/layout/pojo_layout.xml +++ b/uiapp/src/main/res/layout/pojo_layout.xml @@ -1,4 +1,17 @@ + + + + diff --git a/uiapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/uiapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index eca70cf..db91ea0 100644 --- a/uiapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/uiapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,4 +1,17 @@ + + diff --git a/uiapp/src/main/res/values/colors.xml b/uiapp/src/main/res/values/colors.xml index 69b2233..a451cfd 100644 --- a/uiapp/src/main/res/values/colors.xml +++ b/uiapp/src/main/res/values/colors.xml @@ -1,4 +1,17 @@ + + #008577 #00574B diff --git a/uiapp/src/main/res/values/strings.xml b/uiapp/src/main/res/values/strings.xml index 39b43a1..f6b97fb 100644 --- a/uiapp/src/main/res/values/strings.xml +++ b/uiapp/src/main/res/values/strings.xml @@ -1,3 +1,16 @@ + + UIApp diff --git a/uiapp/src/main/res/values/styles.xml b/uiapp/src/main/res/values/styles.xml index 5885930..082277b 100644 --- a/uiapp/src/main/res/values/styles.xml +++ b/uiapp/src/main/res/values/styles.xml @@ -1,3 +1,16 @@ + + diff --git a/uiapp/src/test/java/promise/uiapp/ExampleUnitTest.kt b/uiapp/src/test/java/promise/uiapp/ExampleUnitTest.kt index 2a7991c..b5ef407 100644 --- a/uiapp/src/test/java/promise/uiapp/ExampleUnitTest.kt +++ b/uiapp/src/test/java/promise/uiapp/ExampleUnitTest.kt @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Peter Vincent + * Licensed under the Apache License, Version 2.0, Android Promise. + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://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. + */ + package promise.uiapp import org.junit.Test