Migrated ui and theme modules from Java to Kotlin (#5942)

* Rename .java to .kt

* Migrated ui and theme module to Kotlin
This commit is contained in:
Saifuddin Adenwala 2024-11-20 19:25:13 +05:30 committed by GitHub
parent cb4ffd8ca8
commit ed18a37577
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 230 additions and 245 deletions

View file

@ -367,7 +367,7 @@ public class LocationPickerActivity extends BaseActivity implements
*/ */
private void removeLocationFromImage() { private void removeLocationFromImage() {
if (media != null) { if (media != null) {
compositeDisposable.add(coordinateEditHelper.makeCoordinatesEdit(getApplicationContext() getCompositeDisposable().add(coordinateEditHelper.makeCoordinatesEdit(getApplicationContext()
, media, "0.0", "0.0", "0.0f") , media, "0.0", "0.0", "0.0f")
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -479,7 +479,7 @@ public class LocationPickerActivity extends BaseActivity implements
} }
try { try {
compositeDisposable.add( getCompositeDisposable().add(
coordinateEditHelper.makeCoordinatesEdit(getApplicationContext(), media, coordinateEditHelper.makeCoordinatesEdit(getApplicationContext(), media,
Latitude, Longitude, Accuracy) Latitude, Longitude, Accuracy)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())

View file

@ -1,6 +1,7 @@
package fr.free.nrw.commons.customselector.ui.selector package fr.free.nrw.commons.customselector.ui.selector
import android.app.Activity import android.app.Activity
import android.content.Context
import android.content.Context.MODE_PRIVATE import android.content.Context.MODE_PRIVATE
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
@ -346,7 +347,7 @@ class ImageFragment :
context context
.getSharedPreferences( .getSharedPreferences(
"CustomSelector", "CustomSelector",
BaseActivity.MODE_PRIVATE, MODE_PRIVATE,
)?.let { prefs -> )?.let { prefs ->
prefs.edit()?.let { editor -> prefs.edit()?.let { editor ->
editor.putLong("ItemId", imageAdapter.getImageIdAt(position))?.apply() editor.putLong("ItemId", imageAdapter.getImageIdAt(position))?.apply()

View file

@ -104,7 +104,7 @@ public class SearchActivity extends BaseActivity
viewPagerAdapter.setTabData(fragmentList, titleList); viewPagerAdapter.setTabData(fragmentList, titleList);
viewPagerAdapter.notifyDataSetChanged(); viewPagerAdapter.notifyDataSetChanged();
compositeDisposable.add(RxSearchView.queryTextChanges(binding.searchBox) getCompositeDisposable().add(RxSearchView.queryTextChanges(binding.searchBox)
.takeUntil(RxView.detaches(binding.searchBox)) .takeUntil(RxView.detaches(binding.searchBox))
.debounce(500, TimeUnit.MILLISECONDS) .debounce(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -284,7 +284,7 @@ public class SearchActivity extends BaseActivity
@Override protected void onDestroy() { @Override protected void onDestroy() {
super.onDestroy(); super.onDestroy();
//Dispose the disposables when the activity is destroyed //Dispose the disposables when the activity is destroyed
compositeDisposable.dispose(); getCompositeDisposable().dispose();
binding = null; binding = null;
} }
} }

View file

@ -133,7 +133,7 @@ public class NotificationActivity extends BaseActivity {
} }
binding.progressBar.setVisibility(View.GONE); binding.progressBar.setVisibility(View.GONE);
}); });
compositeDisposable.add(disposable); getCompositeDisposable().add(disposable);
} }
@ -178,7 +178,7 @@ public class NotificationActivity extends BaseActivity {
Timber.d("Add notifications"); Timber.d("Add notifications");
if (mNotificationWorkerFragment == null) { if (mNotificationWorkerFragment == null) {
binding.progressBar.setVisibility(View.VISIBLE); binding.progressBar.setVisibility(View.VISIBLE);
compositeDisposable.add(controller.getNotifications(archived) getCompositeDisposable().add(controller.getNotifications(archived)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(notificationList -> { .subscribe(notificationList -> {

View file

@ -157,7 +157,7 @@ public class ProfileActivity extends BaseActivity {
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
compositeDisposable.clear(); getCompositeDisposable().clear();
} }
/** /**

View file

@ -1,66 +0,0 @@
package fr.free.nrw.commons.theme;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import javax.inject.Inject;
import javax.inject.Named;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.di.CommonsDaggerAppCompatActivity;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.utils.SystemThemeUtils;
import io.reactivex.disposables.CompositeDisposable;
public abstract class BaseActivity extends CommonsDaggerAppCompatActivity {
@Inject
@Named("default_preferences")
public JsonKvStore defaultKvStore;
@Inject
SystemThemeUtils systemThemeUtils;
protected CompositeDisposable compositeDisposable = new CompositeDisposable();
protected boolean wasPreviouslyDarkTheme;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
wasPreviouslyDarkTheme = systemThemeUtils.isDeviceInNightMode();
setTheme(wasPreviouslyDarkTheme ? R.style.DarkAppTheme : R.style.LightAppTheme);
float fontScale = android.provider.Settings.System.getFloat(
getBaseContext().getContentResolver(),
android.provider.Settings.System.FONT_SCALE,
1f);
adjustFontScale(getResources().getConfiguration(), fontScale);
}
@Override
protected void onResume() {
// Restart activity if theme is changed
if (wasPreviouslyDarkTheme != systemThemeUtils.isDeviceInNightMode()) {
recreate();
}
super.onResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
compositeDisposable.clear();
}
/**
* Apply fontScale on device
*/
public void adjustFontScale(Configuration configuration, float scale) {
configuration.fontScale = scale;
final DisplayMetrics metrics = getResources().getDisplayMetrics();
final WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(metrics);
metrics.scaledDensity = configuration.fontScale * metrics.density;
getBaseContext().getResources().updateConfiguration(configuration, metrics);
}
}

View file

@ -0,0 +1,65 @@
package fr.free.nrw.commons.theme
import android.content.res.Configuration
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.WindowManager
import javax.inject.Inject
import javax.inject.Named
import fr.free.nrw.commons.R
import fr.free.nrw.commons.di.CommonsDaggerAppCompatActivity
import fr.free.nrw.commons.kvstore.JsonKvStore
import fr.free.nrw.commons.utils.SystemThemeUtils
import io.reactivex.disposables.CompositeDisposable
abstract class BaseActivity : CommonsDaggerAppCompatActivity() {
@Inject
@field:Named("default_preferences")
lateinit var defaultKvStore: JsonKvStore
@Inject
lateinit var systemThemeUtils: SystemThemeUtils
protected val compositeDisposable = CompositeDisposable()
protected var wasPreviouslyDarkTheme: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
wasPreviouslyDarkTheme = systemThemeUtils.isDeviceInNightMode()
setTheme(if (wasPreviouslyDarkTheme) R.style.DarkAppTheme else R.style.LightAppTheme)
val fontScale = android.provider.Settings.System.getFloat(
baseContext.contentResolver,
android.provider.Settings.System.FONT_SCALE,
1f
)
adjustFontScale(resources.configuration, fontScale)
}
override fun onResume() {
// Restart activity if theme is changed
if (wasPreviouslyDarkTheme != systemThemeUtils.isDeviceInNightMode()) {
recreate()
}
super.onResume()
}
override fun onDestroy() {
super.onDestroy()
compositeDisposable.clear()
}
/**
* Apply fontScale on device
*/
fun adjustFontScale(configuration: Configuration, scale: Float) {
configuration.fontScale = scale
val metrics = resources.displayMetrics
val wm = getSystemService(WINDOW_SERVICE) as WindowManager
wm.defaultDisplay.getMetrics(metrics)
metrics.scaledDensity = configuration.fontScale * metrics.density
baseContext.resources.updateConfiguration(configuration, metrics)
}
}

View file

@ -1,65 +0,0 @@
package fr.free.nrw.commons.ui;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build.VERSION;
import android.util.AttributeSet;
import com.google.android.material.textfield.TextInputEditText;
import fr.free.nrw.commons.R;
public class PasteSensitiveTextInputEditText extends TextInputEditText {
private boolean formattingAllowed = true;
public PasteSensitiveTextInputEditText(final Context context) {
super(context);
}
public PasteSensitiveTextInputEditText(final Context context, final AttributeSet attrs) {
super(context, attrs);
formattingAllowed = extractFormattingAttribute(context, attrs);
}
@Override
public boolean onTextContextMenuItem(int id) {
// if not paste command, or formatting is allowed, return default
if(id != android.R.id.paste || formattingAllowed){
return super.onTextContextMenuItem(id);
}
// if its paste and formatting not allowed
boolean proceeded;
if(VERSION.SDK_INT >= 23) {
proceeded = super.onTextContextMenuItem(android.R.id.pasteAsPlainText);
}else {
proceeded = super.onTextContextMenuItem(id);
if (proceeded && getText() != null) {
// rewrite with plain text so formatting is lost
setText(getText().toString());
setSelection(getText().length());
}
}
return proceeded;
}
private boolean extractFormattingAttribute(Context context, AttributeSet attrs){
boolean formatAllowed = true;
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs, R.styleable.PasteSensitiveTextInputEditText, 0, 0);
try {
formatAllowed = a.getBoolean(
R.styleable.PasteSensitiveTextInputEditText_allowFormatting, true);
} finally {
a.recycle();
}
return formatAllowed;
}
public void setFormattingAllowed(boolean formattingAllowed){
this.formattingAllowed = formattingAllowed;
}
}

View file

@ -0,0 +1,60 @@
package fr.free.nrw.commons.ui
import android.content.Context
import android.content.res.TypedArray
import android.os.Build
import android.os.Build.VERSION
import android.util.AttributeSet
import com.google.android.material.textfield.TextInputEditText
import fr.free.nrw.commons.R
class PasteSensitiveTextInputEditText @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : TextInputEditText(context, attrs) {
private var formattingAllowed: Boolean = true
init {
if (attrs != null) {
formattingAllowed = extractFormattingAttribute(context, attrs)
}
}
override fun onTextContextMenuItem(id: Int): Boolean {
// if not paste command, or formatting is allowed, return default
if (id != android.R.id.paste || formattingAllowed) {
return super.onTextContextMenuItem(id)
}
// if it's paste and formatting not allowed
val proceeded: Boolean = if (VERSION.SDK_INT >= 23) {
super.onTextContextMenuItem(android.R.id.pasteAsPlainText)
} else {
val success = super.onTextContextMenuItem(id)
if (success && text != null) {
// rewrite with plain text so formatting is lost
setText(text.toString())
setSelection(text?.length ?: 0)
}
success
}
return proceeded
}
private fun extractFormattingAttribute(context: Context, attrs: AttributeSet): Boolean {
val a = context.theme.obtainStyledAttributes(
attrs, R.styleable.PasteSensitiveTextInputEditText, 0, 0
)
return try {
a.getBoolean(R.styleable.PasteSensitiveTextInputEditText_allowFormatting, true)
} finally {
a.recycle()
}
}
fun setFormattingAllowed(formattingAllowed: Boolean) {
this.formattingAllowed = formattingAllowed
}
}

View file

@ -1,36 +0,0 @@
package fr.free.nrw.commons.ui.widget;
import android.content.Context;
import android.text.method.LinkMovementMethod;
import android.util.AttributeSet;
import androidx.appcompat.widget.AppCompatTextView;
import fr.free.nrw.commons.utils.StringUtil;
/**
* An {@link AppCompatTextView} which formats the text to HTML displayable text and makes any
* links clickable.
*/
public class HtmlTextView extends AppCompatTextView {
/**
* Constructs a new instance of HtmlTextView
* @param context the context of the view
* @param attrs the set of attributes for the view
*/
public HtmlTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setMovementMethod(LinkMovementMethod.getInstance());
setText(StringUtil.fromHtml(getText().toString()));
}
/**
* Sets the text to be displayed
* @param newText the text to be displayed
*/
public void setHtmlText(String newText) {
setText(StringUtil.fromHtml(newText));
}
}

View file

@ -0,0 +1,32 @@
package fr.free.nrw.commons.ui.widget
import android.content.Context
import android.text.method.LinkMovementMethod
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatTextView
import fr.free.nrw.commons.utils.StringUtil
/**
* An [AppCompatTextView] which formats the text to HTML displayable text and makes any
* links clickable.
*/
class HtmlTextView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : AppCompatTextView(context, attrs) {
init {
movementMethod = LinkMovementMethod.getInstance()
text = StringUtil.fromHtml(text.toString())
}
/**
* Sets the text to be displayed
* @param newText the text to be displayed
*/
fun setHtmlText(newText: String) {
text = StringUtil.fromHtml(newText)
}
}

View file

@ -1,70 +0,0 @@
package fr.free.nrw.commons.ui.widget;
import android.app.Dialog;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
/**
* a formatted dialog fragment
* This class is used by NearbyInfoDialog
*/
public abstract class OverlayDialog extends DialogFragment {
/**
* creates a DialogFragment with the correct style and theme
* @param savedInstanceState bundle re-constructed from a previous saved state
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_FRAME, android.R.style.Theme_Holo_Light);
}
/**
* When the view is created, sets the dialog layout to full screen
*
* @param view the view being used
* @param savedInstanceState bundle re-constructed from a previous saved state
*/
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
setDialogLayoutToFullScreen();
super.onViewCreated(view, savedInstanceState);
}
/**
* sets the dialog layout to fullscreen
*/
private void setDialogLayoutToFullScreen() {
Window window = getDialog().getWindow();
WindowManager.LayoutParams wlp = window.getAttributes();
window.requestFeature(Window.FEATURE_NO_TITLE);
wlp.gravity = Gravity.BOTTOM;
wlp.width = WindowManager.LayoutParams.MATCH_PARENT;
wlp.height = WindowManager.LayoutParams.MATCH_PARENT;
window.setAttributes(wlp);
}
/**
* builds custom dialog container
*
* @param savedInstanceState the previously saved state
* @return the dialog
*/
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
Window window = dialog.getWindow();
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
return dialog;
}
}

View file

@ -0,0 +1,64 @@
package fr.free.nrw.commons.ui.widget
import android.app.Dialog
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.view.Window
import android.view.WindowManager
import androidx.fragment.app.DialogFragment
/**
* A formatted dialog fragment
* This class is used by NearbyInfoDialog
*/
abstract class OverlayDialog : DialogFragment() {
/**
* Creates a DialogFragment with the correct style and theme
* @param savedInstanceState bundle re-constructed from a previous saved state
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_FRAME, android.R.style.Theme_Holo_Light)
}
/**
* When the view is created, sets the dialog layout to full screen
*
* @param view the view being used
* @param savedInstanceState bundle re-constructed from a previous saved state
*/
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
setDialogLayoutToFullScreen()
super.onViewCreated(view, savedInstanceState)
}
/**
* Sets the dialog layout to fullscreen
*/
private fun setDialogLayoutToFullScreen() {
val window = dialog?.window ?: return
val wlp = window.attributes
window.requestFeature(Window.FEATURE_NO_TITLE)
wlp.gravity = Gravity.BOTTOM
wlp.width = WindowManager.LayoutParams.MATCH_PARENT
wlp.height = WindowManager.LayoutParams.MATCH_PARENT
window.attributes = wlp
}
/**
* Builds custom dialog container
*
* @param savedInstanceState the previously saved state
* @return the dialog
*/
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
return dialog
}
}