mirror of
				https://github.com/commons-app/apps-android-commons.git
				synced 2025-10-31 14:53:59 +01:00 
			
		
		
		
	Migrated widget module to Kotlin
This commit is contained in:
		
							parent
							
								
									169f05e2fc
								
							
						
					
					
						commit
						c5f8892d05
					
				
					 4 changed files with 144 additions and 157 deletions
				
			
		|  | @ -2,7 +2,6 @@ package fr.free.nrw.commons.di; | |||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| 
 | ||||
| import fr.free.nrw.commons.actions.PageEditClient; | ||||
| import fr.free.nrw.commons.explore.categories.CategoriesModule; | ||||
| import fr.free.nrw.commons.navtab.MoreBottomSheetFragment; | ||||
| import fr.free.nrw.commons.navtab.MoreBottomSheetLoggedOutFragment; | ||||
|  |  | |||
|  | @ -1,48 +1,43 @@ | |||
| package fr.free.nrw.commons.widget; | ||||
| package fr.free.nrw.commons.widget | ||||
| 
 | ||||
| import android.app.Activity; | ||||
| import android.content.Context; | ||||
| import android.util.AttributeSet; | ||||
| import android.util.DisplayMetrics; | ||||
| import android.app.Activity | ||||
| import android.content.Context | ||||
| import android.util.AttributeSet | ||||
| import android.util.DisplayMetrics | ||||
| 
 | ||||
| import androidx.annotation.Nullable | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| 
 | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| 
 | ||||
| /** | ||||
|  * Created by Ilgaz Er on 8/7/2018. | ||||
|  */ | ||||
| public class HeightLimitedRecyclerView extends RecyclerView { | ||||
|     int height; | ||||
|     public HeightLimitedRecyclerView(Context context) { | ||||
|         super(context); | ||||
|         DisplayMetrics displayMetrics = new DisplayMetrics(); | ||||
|         ((Activity) getContext()).getWindowManager() | ||||
|                 .getDefaultDisplay() | ||||
|                 .getMetrics(displayMetrics); | ||||
|         height=displayMetrics.heightPixels; | ||||
| class HeightLimitedRecyclerView : RecyclerView { | ||||
|     private var height: Int = 0 | ||||
| 
 | ||||
|     constructor(context: Context) : super(context) { | ||||
|         initializeHeight(context) | ||||
|     } | ||||
| 
 | ||||
|     public HeightLimitedRecyclerView(Context context, @Nullable AttributeSet attrs) { | ||||
|         super(context, attrs); | ||||
|         DisplayMetrics displayMetrics = new DisplayMetrics(); | ||||
|         ((Activity) getContext()).getWindowManager() | ||||
|                 .getDefaultDisplay() | ||||
|                 .getMetrics(displayMetrics); | ||||
|         height=displayMetrics.heightPixels; | ||||
|     constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { | ||||
|         initializeHeight(context) | ||||
|     } | ||||
| 
 | ||||
|     public HeightLimitedRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { | ||||
|         super(context, attrs, defStyle); | ||||
|         DisplayMetrics displayMetrics = new DisplayMetrics(); | ||||
|         ((Activity) getContext()).getWindowManager() | ||||
|                 .getDefaultDisplay() | ||||
|                 .getMetrics(displayMetrics); | ||||
|         height=displayMetrics.heightPixels; | ||||
|     constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle) { | ||||
|         initializeHeight(context) | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onMeasure(int widthSpec, int heightSpec) { | ||||
|         heightSpec = MeasureSpec.makeMeasureSpec((int) (height*0.3), MeasureSpec.AT_MOST); | ||||
|         super.onMeasure(widthSpec, heightSpec); | ||||
|     private fun initializeHeight(context: Context) { | ||||
|         val displayMetrics = DisplayMetrics() | ||||
|         (context as Activity).windowManager.defaultDisplay.getMetrics(displayMetrics) | ||||
|         height = displayMetrics.heightPixels | ||||
|     } | ||||
| 
 | ||||
|     override fun onMeasure(widthSpec: Int, heightSpec: Int) { | ||||
|         val limitedHeightSpec = MeasureSpec.makeMeasureSpec( | ||||
|             (height * 0.3).toInt(), | ||||
|             MeasureSpec.AT_MOST | ||||
|         ) | ||||
|         super.onMeasure(widthSpec, limitedHeightSpec) | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,69 +1,65 @@ | |||
| package fr.free.nrw.commons.widget; | ||||
| package fr.free.nrw.commons.widget | ||||
| 
 | ||||
| import android.app.PendingIntent; | ||||
| import android.appwidget.AppWidgetManager; | ||||
| import android.appwidget.AppWidgetProvider; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.graphics.Bitmap; | ||||
| import android.graphics.Canvas; | ||||
| import android.graphics.Paint; | ||||
| import android.net.Uri; | ||||
| import android.os.Build; | ||||
| import android.widget.RemoteViews; | ||||
| import androidx.annotation.Nullable; | ||||
| import com.facebook.common.executors.CallerThreadExecutor; | ||||
| import com.facebook.common.references.CloseableReference; | ||||
| import com.facebook.datasource.DataSource; | ||||
| import com.facebook.drawee.backends.pipeline.Fresco; | ||||
| import com.facebook.imagepipeline.core.ImagePipeline; | ||||
| import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber; | ||||
| import com.facebook.imagepipeline.image.CloseableImage; | ||||
| import com.facebook.imagepipeline.request.ImageRequest; | ||||
| import com.facebook.imagepipeline.request.ImageRequestBuilder; | ||||
| import fr.free.nrw.commons.media.MediaClient; | ||||
| import javax.inject.Inject; | ||||
| import fr.free.nrw.commons.R; | ||||
| import fr.free.nrw.commons.contributions.MainActivity; | ||||
| import fr.free.nrw.commons.di.ApplicationlessInjection; | ||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.disposables.CompositeDisposable; | ||||
| import io.reactivex.schedulers.Schedulers; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
| import static android.content.Intent.ACTION_VIEW; | ||||
| import android.app.PendingIntent | ||||
| import android.appwidget.AppWidgetManager | ||||
| import android.appwidget.AppWidgetProvider | ||||
| import android.content.Context | ||||
| import android.content.Intent | ||||
| import android.graphics.Bitmap | ||||
| import android.graphics.Canvas | ||||
| import android.graphics.Paint | ||||
| import android.net.Uri | ||||
| import android.os.Build | ||||
| import android.widget.RemoteViews | ||||
| import androidx.annotation.Nullable | ||||
| import com.facebook.common.executors.CallerThreadExecutor | ||||
| import com.facebook.common.references.CloseableReference | ||||
| import com.facebook.datasource.DataSource | ||||
| import com.facebook.drawee.backends.pipeline.Fresco | ||||
| import com.facebook.imagepipeline.core.ImagePipeline | ||||
| import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber | ||||
| import com.facebook.imagepipeline.image.CloseableImage | ||||
| import com.facebook.imagepipeline.request.ImageRequest | ||||
| import com.facebook.imagepipeline.request.ImageRequestBuilder | ||||
| import fr.free.nrw.commons.media.MediaClient | ||||
| import javax.inject.Inject | ||||
| import fr.free.nrw.commons.R | ||||
| import fr.free.nrw.commons.contributions.MainActivity | ||||
| import fr.free.nrw.commons.di.ApplicationlessInjection | ||||
| import io.reactivex.android.schedulers.AndroidSchedulers | ||||
| import io.reactivex.disposables.CompositeDisposable | ||||
| import io.reactivex.schedulers.Schedulers | ||||
| import timber.log.Timber | ||||
| 
 | ||||
| /** | ||||
|  * Implementation of App Widget functionality. | ||||
|  */ | ||||
| public class PicOfDayAppWidget extends AppWidgetProvider { | ||||
| class PicOfDayAppWidget : AppWidgetProvider() { | ||||
| 
 | ||||
|     private final CompositeDisposable compositeDisposable = new CompositeDisposable(); | ||||
|     private val compositeDisposable = CompositeDisposable() | ||||
| 
 | ||||
|     @Inject | ||||
|     MediaClient mediaClient; | ||||
|     lateinit var mediaClient: MediaClient | ||||
| 
 | ||||
|     void updateAppWidget( | ||||
|         final Context context, | ||||
|         final AppWidgetManager appWidgetManager, | ||||
|         final int appWidgetId | ||||
|     private fun updateAppWidget( | ||||
|         context: Context, | ||||
|         appWidgetManager: AppWidgetManager, | ||||
|         appWidgetId: Int | ||||
|     ) { | ||||
|         final RemoteViews views = new RemoteViews( | ||||
|             context.getPackageName(), R.layout.pic_of_day_app_widget); | ||||
|         val views = RemoteViews(context.packageName, R.layout.pic_of_day_app_widget) | ||||
| 
 | ||||
|         // Launch App on Button Click | ||||
|         final Intent viewIntent = new Intent(context, MainActivity.class); | ||||
|         int flags = PendingIntent.FLAG_UPDATE_CURRENT; | ||||
|         if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.M) { | ||||
|             flags |= PendingIntent.FLAG_IMMUTABLE; | ||||
|         val viewIntent = Intent(context, MainActivity::class.java) | ||||
|         var flags = PendingIntent.FLAG_UPDATE_CURRENT | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||||
|             flags = flags or PendingIntent.FLAG_IMMUTABLE | ||||
|         } | ||||
|         final PendingIntent pendingIntent = PendingIntent.getActivity( | ||||
|             context, 0, viewIntent, flags); | ||||
|         val pendingIntent = PendingIntent.getActivity(context, 0, viewIntent, flags) | ||||
|         views.setOnClickPendingIntent(R.id.camera_button, pendingIntent) | ||||
| 
 | ||||
|         views.setOnClickPendingIntent(R.id.camera_button, pendingIntent); | ||||
|         appWidgetManager.updateAppWidget(appWidgetId, views); | ||||
|         appWidgetManager.updateAppWidget(appWidgetId, views) | ||||
| 
 | ||||
|         loadPictureOfTheDay(context, views, appWidgetManager, appWidgetId); | ||||
|         loadPictureOfTheDay(context, views, appWidgetManager, appWidgetId) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -71,41 +67,53 @@ public class PicOfDayAppWidget extends AppWidgetProvider { | |||
|      * @param context The application context. | ||||
|      * @param views The RemoteViews object used to update the App Widget UI. | ||||
|      * @param appWidgetManager The AppWidgetManager instance for managing the widget. | ||||
|      * @param appWidgetId he ID of the App Widget to update. | ||||
|      * @param appWidgetId The ID of the App Widget to update. | ||||
|      */ | ||||
|     private void loadPictureOfTheDay( | ||||
|         final Context context, | ||||
|         final RemoteViews views, | ||||
|         final AppWidgetManager appWidgetManager, | ||||
|         final int appWidgetId | ||||
|     private fun loadPictureOfTheDay( | ||||
|         context: Context, | ||||
|         views: RemoteViews, | ||||
|         appWidgetManager: AppWidgetManager, | ||||
|         appWidgetId: Int | ||||
|     ) { | ||||
|         compositeDisposable.add(mediaClient.getPictureOfTheDay() | ||||
|         compositeDisposable.add( | ||||
|             mediaClient.getPictureOfTheDay() | ||||
|                 .subscribeOn(Schedulers.io()) | ||||
|                 .observeOn(AndroidSchedulers.mainThread()) | ||||
|                 .subscribe( | ||||
|                     response -> { | ||||
|                     { response -> | ||||
|                         if (response != null) { | ||||
|                             views.setTextViewText(R.id.appwidget_title, response.getDisplayTitle()); | ||||
|                             views.setTextViewText(R.id.appwidget_title, response.displayTitle) | ||||
| 
 | ||||
|                             // View in browser | ||||
|                             final Intent viewIntent = new Intent(); | ||||
|                             viewIntent.setAction(ACTION_VIEW); | ||||
|                             viewIntent.setData(Uri.parse(response.getPageTitle().getMobileUri())); | ||||
| 
 | ||||
|                             int flags = PendingIntent.FLAG_UPDATE_CURRENT; | ||||
|                             if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.M) { | ||||
|                                 flags |= PendingIntent.FLAG_IMMUTABLE; | ||||
|                             val viewIntent = Intent().apply { | ||||
|                                 action = Intent.ACTION_VIEW | ||||
|                                 data = Uri.parse(response.pageTitle.mobileUri) | ||||
|                             } | ||||
|                             final PendingIntent pendingIntent = PendingIntent.getActivity( | ||||
|                                 context, 0, viewIntent, flags); | ||||
| 
 | ||||
|                             views.setOnClickPendingIntent(R.id.appwidget_image, pendingIntent); | ||||
|                             loadImageFromUrl(response.getThumbUrl(), | ||||
|                                 context, views, appWidgetManager, appWidgetId); | ||||
|                             var flags = PendingIntent.FLAG_UPDATE_CURRENT | ||||
|                             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||||
|                                 flags = flags or PendingIntent.FLAG_IMMUTABLE | ||||
|                             } | ||||
|                             val pendingIntent = PendingIntent.getActivity( | ||||
|                                 context, | ||||
|                                 0, | ||||
|                                 viewIntent, | ||||
|                                 flags | ||||
|                             ) | ||||
| 
 | ||||
|                             views.setOnClickPendingIntent(R.id.appwidget_image, pendingIntent) | ||||
|                             loadImageFromUrl( | ||||
|                                 response.thumbUrl, | ||||
|                                 context, | ||||
|                                 views, | ||||
|                                 appWidgetManager, | ||||
|                                 appWidgetId | ||||
|                             ) | ||||
|                         } | ||||
|                     }, | ||||
|                     t -> Timber.e(t, "Fetching picture of the day failed") | ||||
|                 )); | ||||
|                     { t -> Timber.e(t, "Fetching picture of the day failed") } | ||||
|                 ) | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -114,68 +122,53 @@ public class PicOfDayAppWidget extends AppWidgetProvider { | |||
|      * @param context The application context. | ||||
|      * @param views The RemoteViews object used to update the App Widget UI. | ||||
|      * @param appWidgetManager The AppWidgetManager instance for managing the widget. | ||||
|      * @param appWidgetId he ID of the App Widget to update. | ||||
|      * @param appWidgetId The ID of the App Widget to update. | ||||
|      */ | ||||
|     private void loadImageFromUrl( | ||||
|         final String imageUrl, | ||||
|         final Context context, | ||||
|         final RemoteViews views, | ||||
|         final AppWidgetManager appWidgetManager, | ||||
|         final int appWidgetId | ||||
|     private fun loadImageFromUrl( | ||||
|         imageUrl: String?, | ||||
|         context: Context, | ||||
|         views: RemoteViews, | ||||
|         appWidgetManager: AppWidgetManager, | ||||
|         appWidgetId: Int | ||||
|     ) { | ||||
|         final ImageRequest request = ImageRequestBuilder | ||||
|             .newBuilderWithSource(Uri.parse(imageUrl)).build(); | ||||
|         final ImagePipeline imagePipeline = Fresco.getImagePipeline(); | ||||
|         final DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline | ||||
|             .fetchDecodedImage(request, context); | ||||
|         val request = ImageRequestBuilder.newBuilderWithSource(Uri.parse(imageUrl)).build() | ||||
|         val imagePipeline = Fresco.getImagePipeline() | ||||
|         val dataSource = imagePipeline.fetchDecodedImage(request, context) | ||||
| 
 | ||||
|         dataSource.subscribe(new BaseBitmapDataSubscriber() { | ||||
|             @Override | ||||
|             protected void onNewResultImpl(@Nullable final Bitmap tempBitmap) { | ||||
|                 Bitmap bitmap = null; | ||||
|                 if (tempBitmap != null) { | ||||
|                     bitmap = Bitmap.createBitmap( | ||||
|                         tempBitmap.getWidth(), tempBitmap.getHeight(), Bitmap.Config.ARGB_8888 | ||||
|                     ); | ||||
|                     final Canvas canvas = new Canvas(bitmap); | ||||
|                     canvas.drawBitmap(tempBitmap, 0f, 0f, new Paint()); | ||||
|         dataSource.subscribe(object : BaseBitmapDataSubscriber() { | ||||
|             override fun onNewResultImpl(tempBitmap: Bitmap?) { | ||||
|                 val bitmap = tempBitmap?.let { | ||||
|                     Bitmap.createBitmap(it.width, it.height, Bitmap.Config.ARGB_8888).apply { | ||||
|                         Canvas(this).drawBitmap(it, 0f, 0f, Paint()) | ||||
|                     } | ||||
|                 } | ||||
|                 views.setImageViewBitmap(R.id.appwidget_image, bitmap); | ||||
|                 appWidgetManager.updateAppWidget(appWidgetId, views); | ||||
|                 views.setImageViewBitmap(R.id.appwidget_image, bitmap) | ||||
|                 appWidgetManager.updateAppWidget(appWidgetId, views) | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             protected void onFailureImpl( | ||||
|                 final DataSource<CloseableReference<CloseableImage>> dataSource | ||||
|             ) { | ||||
|             override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) { | ||||
|                 // Ignore failure for now. | ||||
|             } | ||||
|         }, CallerThreadExecutor.getInstance()); | ||||
|         }, CallerThreadExecutor.getInstance()) | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onUpdate( | ||||
|         final Context context, | ||||
|         final AppWidgetManager appWidgetManager, | ||||
|         final int[] appWidgetIds | ||||
|     ) { | ||||
|     override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { | ||||
|         ApplicationlessInjection | ||||
|                 .getInstance(context.getApplicationContext()) | ||||
|                 .getCommonsApplicationComponent() | ||||
|                 .inject(this); | ||||
|             .getInstance(context.applicationContext) | ||||
|             .commonsApplicationComponent | ||||
|             .inject(this) | ||||
| 
 | ||||
|         // There may be multiple widgets active, so update all of them | ||||
|         for (final int appWidgetId : appWidgetIds) { | ||||
|             updateAppWidget(context, appWidgetManager, appWidgetId); | ||||
|         for (appWidgetId in appWidgetIds) { | ||||
|             updateAppWidget(context, appWidgetManager, appWidgetId) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onEnabled(final Context context) { | ||||
|     override fun onEnabled(context: Context) { | ||||
|         // Enter relevant functionality for when the first widget is created | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDisabled(final Context context) { | ||||
|     override fun onDisabled(context: Context) { | ||||
|         // Enter relevant functionality for when the last widget is disabled | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| package fr.free.nrw.commons.widget; | ||||
| package fr.free.nrw.commons.widget | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.content.Context | ||||
| 
 | ||||
| public interface ViewHolder<T> { | ||||
|     void bindModel(Context context, T model); | ||||
| interface ViewHolder<T> { | ||||
|     fun bindModel(context: Context, model: T) | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Saifuddin
						Saifuddin