diff --git a/.idea/gradle.xml b/.idea/gradle.xml index f43d4284..ed9c379e 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -1,11 +1,11 @@ + diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 00000000..11ec93cf --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index eda73df5..0642fc64 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,7 +5,7 @@ - + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index c9d1dc54..430bc46c 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,8 +2,8 @@ - - + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 39eafc3d..9a525caa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -44,6 +44,10 @@ if (project.file('../PiwigoSigning.properties').exists()) { } android { + signingConfigs { + release { + } + } compileSdkVersion 29 defaultConfig { applicationId "org.piwigo.android" @@ -52,6 +56,7 @@ android { versionCode 102 versionName "1.0.2" multiDexEnabled true + signingConfig signingConfigs.debug } buildTypes { debug { @@ -76,8 +81,8 @@ android { preDexLibraries = preDexEnabled && !isCi } - dataBinding { - enabled = true + buildFeatures { + dataBinding true } testOptions { unitTests { @@ -91,23 +96,25 @@ android { } } -def daggerVersion = '2.24' -def okhttpVersion = '4.2.2' -def retrofitVersion = '2.6.1' -def picassoVersion = '2.5.2' +def daggerVersion = '2.30.1' +def okhttpVersion = '4.9.0' +def retrofitVersion = '2.9.0' +def picassoVersion = '2.71828' def assertjVersion = '1.2.0' def acraVersion = '5.4.0' dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.annotation:annotation:1.1.0' - implementation 'com.google.android.material:material:1.0.0' + implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.cardview:cardview:1.0.0' implementation 'com.android.support:multidex:1.0.3' implementation "com.google.dagger:dagger:${daggerVersion}" - implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0' - annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.1.0' + implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' + implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' + + annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.2.0' annotationProcessor "com.google.dagger:dagger-compiler:${daggerVersion}" implementation "com.google.dagger:dagger-android:${daggerVersion}" @@ -118,12 +125,12 @@ dependencies { implementation "com.squareup.retrofit2:retrofit:${retrofitVersion}" implementation "com.squareup.retrofit2:converter-gson:${retrofitVersion}" implementation "com.squareup.retrofit2:adapter-rxjava:${retrofitVersion}" - implementation "com.squareup.picasso:picasso:${picassoVersion}" - implementation 'io.reactivex:rxjava:1.3.2' + + implementation 'io.reactivex:rxjava:1.3.8' implementation 'io.reactivex:rxandroid:1.2.1' - implementation 'com.google.guava:guava:28.1-jre' - annotationProcessor 'com.google.guava:guava:24.1-jre' - implementation 'org.apache.commons:commons-lang3:3.9' + implementation 'com.google.guava:guava:30.1-jre' + annotationProcessor 'com.google.guava:guava:30.1-jre' + implementation 'org.apache.commons:commons-lang3:3.11' implementation "ch.acra:acra-mail:$acraVersion" implementation "ch.acra:acra-dialog:$acraVersion" @@ -131,21 +138,25 @@ dependencies { implementation 'com.github.jorgecastilloprz:fabprogresscircle:1.01@aar' implementation "com.leinardi.android:speed-dial:3.0.0" implementation 'com.github.tingyik90:snackprogressbar:6.1.1' - implementation 'org.greenrobot:eventbus:3.1.1' + implementation 'org.greenrobot:eventbus:3.2.0' /* Don't forget to add to string libraries if you add a library here. */ - debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0-beta-3' + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.5' - testImplementation 'junit:junit:4.12' - testImplementation 'org.robolectric:robolectric:4.3' + testImplementation 'junit:junit:4.13.1' + testImplementation 'org.robolectric:robolectric:4.4' testImplementation("com.squareup.assertj:assertj-android:${assertjVersion}") { exclude group: 'com.android.support' } + implementation ("com.github.bumptech.glide:glide:4.11.0") { + exclude group: "com.android.support" + } testAnnotationProcessor "com.google.dagger:dagger-compiler:${daggerVersion}" testImplementation 'androidx.arch.core:core-testing:2.1.0' - testImplementation 'org.mockito:mockito-core:2.19.0' - testImplementation 'com.google.guava:guava:24.1-jre' - testImplementation 'androidx.appcompat:appcompat:1.1.0' - testAnnotationProcessor 'com.google.guava:guava:24.1-jre' + testImplementation 'org.mockito:mockito-core:3.6.28' + testImplementation 'com.google.guava:guava:30.1-jre' + testImplementation 'androidx.appcompat:appcompat:1.2.0' + testAnnotationProcessor 'com.google.guava:guava:30.1-jre' testImplementation 'com.google.code.findbugs:jsr305:3.0.2' + implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0' } diff --git a/app/src/main/java/org/piwigo/internal/binding/adapter/ImageViewBindingAdapter.java b/app/src/main/java/org/piwigo/internal/binding/adapter/ImageViewBindingAdapter.java index 2015afcc..04c17258 100644 --- a/app/src/main/java/org/piwigo/internal/binding/adapter/ImageViewBindingAdapter.java +++ b/app/src/main/java/org/piwigo/internal/binding/adapter/ImageViewBindingAdapter.java @@ -22,20 +22,28 @@ import android.view.ViewGroup; import android.widget.ImageView; -import com.squareup.picasso.Picasso; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; + +import org.piwigo.R; public class ImageViewBindingAdapter { - private final Picasso picasso; - public ImageViewBindingAdapter(Picasso picasso) { - this.picasso = picasso; + + public ImageViewBindingAdapter() { + } @BindingAdapter("android:src") public void loadImage(ImageView imageView, String url) { - picasso.load(url) - .resize(500,0) - .into(imageView); // centering and cropping is done by ImageView from the resources + + Glide.with(imageView) + .load(url) + .placeholder(R.drawable.ic_downloading_placeholder) + //.override(400) + .fitCenter() + .transition(DrawableTransitionOptions.withCrossFade()) + .into(imageView); } @BindingAdapter("heightRatio") public void setHeighRatio(ImageView imageView, double ratio) { diff --git a/app/src/main/java/org/piwigo/internal/cache/PiwigoImageCache.java b/app/src/main/java/org/piwigo/internal/cache/PiwigoImageCache.java deleted file mode 100644 index 7468880d..00000000 --- a/app/src/main/java/org/piwigo/internal/cache/PiwigoImageCache.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.piwigo.internal.cache; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.util.Log; - -import com.squareup.picasso.Cache; - -import org.piwigo.PiwigoApplication; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; - -public class PiwigoImageCache implements Cache { - - private String cacheDir; - - public PiwigoImageCache(PiwigoApplication piwigoApplication) { - this.cacheDir = piwigoApplication.getCacheDir().getAbsolutePath(); - } - - private String getPathFromKey(String key) - { - return (key.substring(key.indexOf("/"), key.indexOf("\n"))); - } - - @Override - public Bitmap get(String key) { - File file = new File(cacheDir + "/bmp/" + getPathFromKey(key)); - - Log.d("PiwigoImageCache", "Getting image from cache: " + file.getAbsolutePath()); - - if (file.exists()) { - try { - return BitmapFactory.decodeStream(new FileInputStream(file)); - } catch (FileNotFoundException e) { - //@TODO Here we silently do nothing to avoid flooding logs.. - } - } - return null; - } - - @Override - public void set(String key, Bitmap bitmap) { - File file = new File(cacheDir + "/bmp/" + getPathFromKey(key)); - file.getParentFile().mkdirs(); - - Log.d("PiwigoImageCache", "Writing image to cache: " + file.getAbsolutePath()); - - try { - bitmap.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(file)); - } catch (FileNotFoundException e) { - //@TODO Here we silently do nothing to avoid flooding logs.. - } - } - - @Override - public int size() { - File dir = new File(cacheDir + "/bmp/"); - int len = 0; - - for (File file : dir.listFiles()) - len += file.length(); - return (len); - } - - @Override - public int maxSize() { - File file = new File(cacheDir + "/bmp/"); - - return ((int)file.getFreeSpace()); - } - - @Override - public void clear() { - File dir = new File(cacheDir + "/bmp/"); - - for (File file : dir.listFiles()) - if (file.exists()) file.delete(); - } - - @Override - public void clearKeyUri(String keyPrefix) { - File dir = new File(cacheDir + "/bmp/"); - - for (File file : dir.listFiles()) - if (file.getName().startsWith(keyPrefix)) file.delete(); - } -} \ No newline at end of file diff --git a/app/src/main/java/org/piwigo/internal/di/component/ApplicationComponent.java b/app/src/main/java/org/piwigo/internal/di/component/ApplicationComponent.java index 5a4a18e9..c505d919 100644 --- a/app/src/main/java/org/piwigo/internal/di/component/ApplicationComponent.java +++ b/app/src/main/java/org/piwigo/internal/di/component/ApplicationComponent.java @@ -18,7 +18,7 @@ package org.piwigo.internal.di.component; -import com.squareup.picasso.Picasso; + import org.piwigo.PiwigoApplication; import org.piwigo.bg.UploadService; @@ -39,5 +39,4 @@ public interface ApplicationComponent { void inject(UploadService service); - Picasso picasso(); } diff --git a/app/src/main/java/org/piwigo/internal/di/module/ApplicationModule.java b/app/src/main/java/org/piwigo/internal/di/module/ApplicationModule.java index 04909045..7a2fdb9c 100644 --- a/app/src/main/java/org/piwigo/internal/di/module/ApplicationModule.java +++ b/app/src/main/java/org/piwigo/internal/di/module/ApplicationModule.java @@ -21,14 +21,10 @@ import android.accounts.AccountManager; import android.content.Context; -import com.squareup.picasso.Picasso; - import org.piwigo.BuildConfig; import org.piwigo.PiwigoApplication; import org.piwigo.accounts.UserManager; -import org.piwigo.internal.cache.PiwigoImageCache; import org.piwigo.io.repository.PreferencesRepository; - import javax.inject.Singleton; import dagger.Module; @@ -47,12 +43,6 @@ public ApplicationModule(PiwigoApplication application) { return application; } - @Provides @Singleton Picasso providePicasso() { - return new Picasso.Builder(application) - .indicatorsEnabled(BuildConfig.DEBUG) //We may not want this for production build.. - .memoryCache(new PiwigoImageCache(application)) //What about this ? - .build(); - } @Provides @Singleton AccountManager provideAccountManager() { return AccountManager.get(application); diff --git a/app/src/main/java/org/piwigo/internal/di/module/BindingModule.java b/app/src/main/java/org/piwigo/internal/di/module/BindingModule.java index be684b6e..d37b604b 100644 --- a/app/src/main/java/org/piwigo/internal/di/module/BindingModule.java +++ b/app/src/main/java/org/piwigo/internal/di/module/BindingModule.java @@ -29,7 +29,7 @@ @Module public class BindingModule { - @Provides @DataBinding ImageViewBindingAdapter provideImageBindingAdapter(Picasso picasso) { - return new ImageViewBindingAdapter(picasso); + @Provides @DataBinding ImageViewBindingAdapter provideImageBindingAdapter() { + return new ImageViewBindingAdapter(); } } diff --git a/app/src/main/java/org/piwigo/io/RestService.java b/app/src/main/java/org/piwigo/io/RestService.java index c8215864..01a3bb3a 100644 --- a/app/src/main/java/org/piwigo/io/RestService.java +++ b/app/src/main/java/org/piwigo/io/RestService.java @@ -72,7 +72,9 @@ public interface RestService { ); @GET("ws.php?method=pwg.categories.getImages") - Observable getImages(@Query("cat_id") int categoryId); + Observable getImages( + @Query("cat_id") int categoryId, + @Query("per_page") int count_to_fetch ); @Multipart @POST("ws.php?method=pwg.images.upload") diff --git a/app/src/main/java/org/piwigo/io/repository/ImageRepository.java b/app/src/main/java/org/piwigo/io/repository/ImageRepository.java index 7dbf5122..733a03ee 100644 --- a/app/src/main/java/org/piwigo/io/repository/ImageRepository.java +++ b/app/src/main/java/org/piwigo/io/repository/ImageRepository.java @@ -41,11 +41,11 @@ public class ImageRepository extends BaseRepository { super(restServiceFactory, ioScheduler, uiScheduler, userManager); } - public Observable> getImages(Account account, @Nullable Integer categoryId) { + public Observable> getImages(Account account, @Nullable Integer categoryId, @Nullable Integer number_of_images) { RestService restService = restServiceFactory.createForAccount(account); return restService - .getImages(categoryId) + .getImages(categoryId, number_of_images) .compose(applySchedulers()) // .map(imageListResponse -> imageListResponse.result.images) .map(imageListResponse -> { diff --git a/app/src/main/java/org/piwigo/ui/main/AlbumItemViewModel.java b/app/src/main/java/org/piwigo/ui/main/AlbumItemViewModel.java index f7ce24af..1a4dea28 100644 --- a/app/src/main/java/org/piwigo/ui/main/AlbumItemViewModel.java +++ b/app/src/main/java/org/piwigo/ui/main/AlbumItemViewModel.java @@ -34,12 +34,14 @@ public class AlbumItemViewModel extends ViewModel { private final String title; private final String photos; private final Integer catId; + private final Integer nbImages; - AlbumItemViewModel(String url, String title, String photos, Integer categoryId) { + AlbumItemViewModel(String url, String title, String photos, Integer categoryId, Integer nbImages) { this.url = url; this.title = title; this.photos = photos; this.catId = categoryId; + this.nbImages = nbImages; } public String getUrl() { @@ -56,6 +58,8 @@ public String getPhotos() { public Integer getCatId() { return catId;} + public Integer getImageCount() { return nbImages; } + public void onClickDo(View v){ Context ctx = v.getContext(); while (ctx instanceof ContextWrapper @@ -72,6 +76,7 @@ public void onClickDo(View v){ Bundle bndl = new Bundle(); bndl.putInt("Category", getCatId()); bndl.putString("Title", getTitle()); + bndl.putInt("ImageCount", getImageCount()); AlbumsFragment frag = new AlbumsFragment(); frag.setArguments(bndl); ((AppCompatActivity) ctx).getSupportFragmentManager() diff --git a/app/src/main/java/org/piwigo/ui/main/AlbumsFragment.java b/app/src/main/java/org/piwigo/ui/main/AlbumsFragment.java index db9246a7..e61722f9 100644 --- a/app/src/main/java/org/piwigo/ui/main/AlbumsFragment.java +++ b/app/src/main/java/org/piwigo/ui/main/AlbumsFragment.java @@ -57,6 +57,7 @@ public class AlbumsFragment extends BaseFragment { private FragmentAlbumsBinding binding; private int categoryID; private String categoryName; + private int imageCount; public AlbumsFragment() { super(); @@ -73,6 +74,7 @@ public void onAttach(Context context) { Bundle bundle = this.getArguments(); if (bundle != null) { categoryID = bundle.getInt("Category", 0); + imageCount = bundle.getInt( "ImageCount", 100); categoryName = bundle.getString("Title", getString(R.string.nav_albums)); } super.onAttach(context); @@ -120,7 +122,7 @@ public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); AlbumsViewModel viewModel = ViewModelProviders.of(this, viewModelFactory).get(AlbumsViewModel.class); binding.setViewModel(viewModel); - binding.getViewModel().loadAlbums(categoryID); + binding.getViewModel().loadAlbums(categoryID, imageCount); } private int calculateColumnCount() { diff --git a/app/src/main/java/org/piwigo/ui/main/AlbumsViewModel.java b/app/src/main/java/org/piwigo/ui/main/AlbumsViewModel.java index 811823c8..cb5289b9 100644 --- a/app/src/main/java/org/piwigo/ui/main/AlbumsViewModel.java +++ b/app/src/main/java/org/piwigo/ui/main/AlbumsViewModel.java @@ -63,6 +63,7 @@ public class AlbumsViewModel extends ViewModel { private Subscription photosSubscription; private Integer category = null; + private Integer mImageCount; AlbumsViewModel(UserManager userManager, CategoriesRepository categoriesRepository, ImageRepository imageRepository, Resources resources) { @@ -99,14 +100,16 @@ private void forcedLoadAlbums(){ if (account != null) { albumsSubscription = categoriesRepository.getCategories(account, category) .subscribe(new CategoriesSubscriber()); - photosSubscription = imageRepository.getImages(account, category) + photosSubscription = imageRepository.getImages( account, category, mImageCount ) .subscribe(new ImagesSubscriber()); + } } - void loadAlbums(Integer categoryId) { + void loadAlbums(Integer categoryId, Integer imageCount) { if(category == null || category != category) { category = categoryId; + mImageCount = imageCount; forcedLoadAlbums(); } } @@ -120,6 +123,7 @@ private class CategoriesSubscriber extends Subscriber> { @Override public void onCompleted() { + } @Override @@ -161,7 +165,7 @@ public void bind(BindingRecyclerViewAdapter.ViewHolder viewHolder, Category cate int subPhotos = category.totalNbImages - category.nbImages; photos += resources.getQuantityString(R.plurals.album_photos_subs, subPhotos, subPhotos); } - AlbumItemViewModel viewModel = new AlbumItemViewModel(category.thumbnailUrl, category.name, photos, category.id); + AlbumItemViewModel viewModel = new AlbumItemViewModel(category.thumbnailUrl, category.name, photos, category.id, category.nbImages); viewHolder.getBinding().setVariable(BR.viewModel, viewModel); } } @@ -209,7 +213,7 @@ public int getLayout(int viewType) { public void bind(BindingRecyclerViewAdapter.ViewHolder viewHolder, ImageInfo image) { // TODO: make image size selectable via settings (jca) // TODO: make configurable to also show the photo name here - ImagesItemViewModel viewModel = new ImagesItemViewModel(image.derivatives.medium.url, images.indexOf(image), image.name, images); + ImagesItemViewModel viewModel = new ImagesItemViewModel(image.derivatives.small.url, images.indexOf(image), image.name, images); viewHolder.getBinding().setVariable(BR.viewModel, viewModel); } diff --git a/app/src/main/java/org/piwigo/ui/photoviewer/PhotoViewerDialogFragment.java b/app/src/main/java/org/piwigo/ui/photoviewer/PhotoViewerDialogFragment.java index aad3ded1..ce8f940a 100644 --- a/app/src/main/java/org/piwigo/ui/photoviewer/PhotoViewerDialogFragment.java +++ b/app/src/main/java/org/piwigo/ui/photoviewer/PhotoViewerDialogFragment.java @@ -26,8 +26,7 @@ public class PhotoViewerDialogFragment extends DialogFragment private PhotoViewerPagerAdapter pagerAdapter; private int selectedPosition = 0; - @Inject - Picasso picasso; + public static PhotoViewerDialogFragment newInstance() { PhotoViewerDialogFragment f = new PhotoViewerDialogFragment(); @@ -43,7 +42,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa selectedPosition = getArguments().getInt("position"); pagerAdapter = new PhotoViewerPagerAdapter(getContext(), images); - pagerAdapter.setPicassoInstance(picasso); + viewPager.setAdapter(pagerAdapter); viewPager.setOffscreenPageLimit(3); setCurrentItem(selectedPosition); diff --git a/app/src/main/java/org/piwigo/ui/photoviewer/PhotoViewerPagerAdapter.java b/app/src/main/java/org/piwigo/ui/photoviewer/PhotoViewerPagerAdapter.java index 0eb99e9f..b8258862 100644 --- a/app/src/main/java/org/piwigo/ui/photoviewer/PhotoViewerPagerAdapter.java +++ b/app/src/main/java/org/piwigo/ui/photoviewer/PhotoViewerPagerAdapter.java @@ -7,6 +7,8 @@ import androidx.annotation.NonNull; import androidx.viewpager.widget.PagerAdapter; + +import com.bumptech.glide.Glide; import com.squareup.picasso.Picasso; import org.piwigo.R; @@ -19,7 +21,7 @@ public class PhotoViewerPagerAdapter extends PagerAdapter { private Context context; private List images; private LayoutInflater inflater; - private Picasso picasso; + public PhotoViewerPagerAdapter(Context context, List images) { @@ -36,7 +38,7 @@ public Object instantiateItem(@NonNull ViewGroup container, int position) TouchImageView imageViewPreview = view.findViewById(R.id.imgDisplay); ImageInfo image = images.get(position); - picasso.load(image.derivatives.medium.url).noFade().into(imageViewPreview); + Glide.with(container).load(image.derivatives.large.url).into(imageViewPreview); container.addView(view); return view; } @@ -56,8 +58,4 @@ public void destroyItem(ViewGroup container, int position, @NonNull Object objec container.removeView((View) object); } - void setPicassoInstance(Picasso picasso) - { - this.picasso = picasso; - } } \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/ic_downloading_placeholder.png b/app/src/main/res/drawable-hdpi/ic_downloading_placeholder.png new file mode 100644 index 00000000..a08aa68a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_downloading_placeholder.png differ diff --git a/app/src/main/res/layout/fragment_albums.xml b/app/src/main/res/layout/fragment_albums.xml index 5a784922..5e6d169b 100644 --- a/app/src/main/res/layout/fragment_albums.xml +++ b/app/src/main/res/layout/fragment_albums.xml @@ -41,15 +41,15 @@ android:id="@+id/photoRecycler" android:layout_width="match_parent" android:layout_height="wrap_content" - android:padding="0dp" - android:nestedScrollingEnabled="false" - android:scrollbars="vertical" - android:orientation="vertical" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" + android:minHeight="8dp" + android:nestedScrollingEnabled="false" + android:orientation="vertical" + android:padding="0dp" + android:scrollbars="vertical" app:items="@{viewModel.images}" - app:viewBinder="@{viewModel.photoViewBinder}" - android:minHeight="8dp"/> + app:viewBinder="@{viewModel.photoViewBinder}" /> diff --git a/app/src/main/res/layout/item_album.xml b/app/src/main/res/layout/item_album.xml index 967febb7..81650237 100644 --- a/app/src/main/res/layout/item_album.xml +++ b/app/src/main/res/layout/item_album.xml @@ -21,13 +21,12 @@ + android:onClick="@{viewModel::onClickDo}" + android:scaleType="fitCenter" + android:src="@{viewModel.url}" + app:heightRatio="@{0.66}" />