Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ plugins {

android {
namespace 'com.slavabarkov.tidy'
compileSdk 33
compileSdk 34

defaultConfig {
applicationId "com.slavabarkov.tidy"
minSdk 26
targetSdk 33
versionCode 2
versionName "1.1"
versionCode 3
versionName "1.2.1"
// Naming app bundles/APKs
setArchivesBaseName("TIDY-${versionName}-c${versionCode}")

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand All @@ -34,17 +36,17 @@ android {
}

dependencies {
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
implementation 'androidx.room:room-runtime:2.5.0'
kapt 'androidx.room:room-compiler:2.5.0'
implementation 'androidx.room:room-ktx:2.5.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.7.7'
implementation 'androidx.navigation:navigation-ui-ktx:2.7.7'
implementation 'androidx.room:room-runtime:2.6.1'
kapt 'androidx.room:room-compiler:2.6.1'
implementation 'androidx.room:room-ktx:2.6.1'
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.github.bumptech.glide:glide:4.13.2'
api 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
implementation 'androidx.core:core-ktx:1.9.0'
api 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0'
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.8.0'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
Expand Down
20 changes: 20 additions & 0 deletions app/release/output-metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.slavabarkov.tidy",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 3,
"versionName": "1.2.1",
"outputFile": "TIDY-1.2.1-c3-release.apk"
}
],
"elementType": "File"
}
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
android:supportsRtl="true"
android:theme="@style/Theme.TIDY"
tools:targetApi="31"
android:largeHeap="true">
android:largeHeap="true"
android:windowSoftInputMode="adjustResize">
<activity
android:name=".MainActivity"
android:exported="true"
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/java/com/slavabarkov/tidy/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@
package com.slavabarkov.tidy

import android.os.Bundle
import android.os.Build
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity

val apiLevel = Build.VERSION.SDK_INT

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
if (apiLevel >= 30 ) {
// Code to handle API level 30 (Android 11)
// When Android >= 11, enable “Display content edge-to-edge”
// See more in https://developer.android.com/develop/ui/views/layout/edge-to-edge
enableEdgeToEdge()
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package com.slavabarkov.tidy.fragments

import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
Expand Down Expand Up @@ -41,8 +42,10 @@ class IndexFragment : Fragment() {
val view = inflater.inflate(R.layout.fragment_index, container, false)
activity?.window?.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
// Request required permissions depending on the Android version
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
permissionsRequest.launch(android.Manifest.permission.READ_MEDIA_IMAGES)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
permissionsRequest.launch(android.Manifest.permission.READ_MEDIA_IMAGES)
}
}
else {
permissionsRequest.launch(android.Manifest.permission.READ_EXTERNAL_STORAGE)
Expand All @@ -54,7 +57,10 @@ class IndexFragment : Fragment() {
mORTImageViewModel.progress.observe(viewLifecycleOwner) { progress ->
var progressPercent: Int = (progress * 100).toInt()
progressBarView?.progress = progressPercent
progressBarTextView?.text = "Updating image index: ${progressPercent}%"

//Reference progress_bar_text in strings.xml for better localisation.
val myString = getString(R.string.progress_bar_text)
"${myString}: ${progressPercent}%".also { progressBarTextView?.text = it }

if (progress == 1.0) {
activity?.window?.clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
Expand Down
66 changes: 66 additions & 0 deletions app/src/main/java/com/slavabarkov/tidy/fragments/SearchFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsAnimationCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.RecyclerView
Expand Down Expand Up @@ -52,6 +55,69 @@ class SearchFragment : Fragment() {
recyclerView.adapter = ImageAdapter(requireContext(), mSearchViewModel.searchResults!!)
recyclerView.scrollToPosition(0)

// If Edge-to-edge display is enabled,
// tweak the top margin so that content will not overlap with status bar
ViewCompat.setOnApplyWindowInsetsListener(view) { v, windowInsets ->
// Handle window insets here
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())

// Update the layout parameters of the view's parent
(v.layoutParams as? ViewGroup.MarginLayoutParams)?.apply {
topMargin = insets.top
}

// Use WindowInsets to check the software keyboard visibility.
// val imeVisible = windowInsets.isVisible(WindowInsetsCompat.Type.ime())
// val imeHeight = windowInsets.getInsets(WindowInsetsCompat.Type.ime()).bottom

// Return CONSUMED if you don't want want the window insets to keep passing
// down to descendant views.
WindowInsetsCompat.CONSUMED
}

// New keyboard animation using WindowInsets
ViewCompat.setWindowInsetsAnimationCallback(
view,
object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) {

var startBottom = 0f
override fun onPrepare(
animation: WindowInsetsAnimationCompat
) {
startBottom = view.bottom.toFloat()
}

var endBottom = 0f
override fun onStart(
animation: WindowInsetsAnimationCompat,
bounds: WindowInsetsAnimationCompat.BoundsCompat
): WindowInsetsAnimationCompat.BoundsCompat {
// Record the position of the view after the IME transition.
endBottom = view.bottom.toFloat()

return bounds
}

override fun onProgress(
insets: WindowInsetsCompat,
runningAnimations: MutableList<WindowInsetsAnimationCompat>
): WindowInsetsCompat {
// Find an IME animation.
val imeAnimation = runningAnimations.find {
it.typeMask and WindowInsetsCompat.Type.ime() != 0
} ?: return insets

// Offset the view based on the interpolated fraction of the IME animation.
view.translationY =
(startBottom - endBottom) * (1 - imeAnimation.interpolatedFraction)

return insets
}

}
)


mORTTextViewModel.init()

searchText = view?.findViewById(R.id.searchText)
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout/fragment_index.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:text="Updating image index"
android:text="@string/progress_bar_text"
android:gravity="center"/>

<ProgressBar
Expand Down
45 changes: 29 additions & 16 deletions app/src/main/res/layout/fragment_search.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,66 @@
tools:context=".fragments.SearchFragment"
>

<LinearLayout
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center">
android:gravity="center"
android:layout_marginTop="12dp"
android:layout_marginHorizontal="12dp">

<EditText
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/searchText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="e.g. &quot;Black cat sitting on a table&quot;"
android:inputType="textWebEditText|text" />
android:hint="@string/search_text"
android:inputType="textWebEditText|text"
/>

<LinearLayout
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
android:gravity="center"
android:layout_marginTop="6dp">

<Button

<com.google.android.material.button.MaterialButton
android:id="@+id/searchButton"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
style="@style/Widget.Material3.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Search" />
android:text="@string/search_button"
android:layout_marginHorizontal="4dp"
app:cornerRadius="@dimen/buttonRadius"
/>

<Space
android:layout_width="10dp"
android:layout_height="wrap_content"
/>

<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/clearButton"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="match_parent"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clear" />
</LinearLayout>
android:text="@string/clear_button"
android:layout_marginHorizontal="4dp"
android:layout_toEndOf="@+id/searchButton"
app:cornerRadius="@dimen/buttonRadius"
/>
</RelativeLayout>


</LinearLayout>
</com.google.android.material.textfield.TextInputLayout>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:layout_marginTop="10dp"
app:layoutManager="GridLayoutManager"
app:spanCount="3" />

Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/values-ja/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<resources>
<string name="app_name">TIDY</string>
<string name="search_text">例えば「Black cat sitting on a table」</string>
<string name="search_button">探す</string>
<string name="clear_button">クリア</string>
<string name="progress_bar_text">画像インデックスを更新中</string>
</resources>
2 changes: 1 addition & 1 deletion app/src/main/res/values-night/themes.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.TIDY" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<style name="Theme.TIDY" parent="Theme.Material3.Dark.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">TIDY</string>
<string name="search_text">例如 “Black cat sitting on a table”</string>
<string name="search_button">搜索</string>
<string name="clear_button">清空</string>
<string name="progress_bar_text">正在更新图像索引</string>
</resources>
8 changes: 8 additions & 0 deletions app/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">TIDY</string>
<string name="search_text">例如「Black cat sitting on a table」</string>
<string name="search_button">搜尋</string>
<string name="clear_button">清空</string>
<string name="progress_bar_text">正在更新圖像索引</string>
</resources>
4 changes: 4 additions & 0 deletions app/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="buttonRadius">16dp</dimen>
</resources>
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<resources>
<string name="app_name">TIDY</string>
<string name="progress_bar_text">Updating image index</string>
<string name="search_text">e.g. “Black cat sitting on a table”</string>
<string name="search_button">SEARCH</string>
<string name="clear_button">CLEAR</string>
</resources>
2 changes: 1 addition & 1 deletion app/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.TIDY" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<style name="Theme.TIDY" parent="Theme.Material3.Light.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
Expand Down