From 330b65a97892cb2fececbf51cf963a5085b65e70 Mon Sep 17 00:00:00 2001 From: Raphael Mack Date: Fri, 5 Oct 2018 00:04:23 +0200 Subject: [PATCH] Account management (#48) * Merge Jeffs changes * bump to new versions * first working implementation of Account management, closes #10 * fix #29 --- .idea/gradle.xml | 18 +++ .idea/misc.xml | 28 ++++ .idea/modules.xml | 9 ++ .idea/vcs.xml | 6 + README.md | 4 +- app/build.gradle | 40 ++--- app/src/debug/res/values/constants.xml | 5 + .../java/io/fabric/sdk/android/Fabric.java | 1 + app/src/main/AndroidManifest.xml | 9 ++ .../java/org/piwigo/accounts/UserManager.java | 94 ++++++++++-- .../java/org/piwigo/helper/CommonVars.java | 61 ++++++++ .../FABProgressCircleBindingAdapter.java | 47 ------ .../adapter/ImageViewBindingAdapter.java | 1 - .../di/module/AndroidInjectorModule.java | 7 + .../main/java/org/piwigo/io/RestService.java | 23 +++ .../piwigo/io/model/ImageListResponse.java | 26 ++++ .../piwigo/io/model/ImageUploadResponse.java | 12 ++ .../piwigo/io/repository/ImageRepository.java | 45 ++++++ .../io/repository/PreferencesRepository.java | 6 +- .../piwigo/ui/account/AccountViewModel.java | 48 ++++++ .../ui/account/ManageAccountsActivity.java | 128 ++++++++++++++++ .../ui/account/ManageAccountsViewModel.java | 86 +++++++++++ .../ManageAccountsViewModelFactory.java | 51 ++++++ .../org/piwigo/ui/login/LoginActivity.java | 26 ++-- .../org/piwigo/ui/login/LoginViewModel.java | 2 +- .../piwigo/ui/main/AlbumItemViewModel.java | 25 ++- .../org/piwigo/ui/main/AlbumsFragment.java | 12 +- .../org/piwigo/ui/main/AlbumsViewModel.java | 12 +- .../java/org/piwigo/ui/main/ClickHandler.java | 19 +++ .../org/piwigo/ui/main/ImagesFragment.java | 110 +++++++++++++ .../ImagesFragmentModule.java} | 17 +- .../piwigo/ui/main/ImagesItemViewModel.java | 50 ++++++ .../org/piwigo/ui/main/ImagesViewModel.java | 145 ++++++++++++++++++ .../ui/main/ImagesViewModelFactory.java | 51 ++++++ .../java/org/piwigo/ui/main/MainActivity.java | 31 ++++ .../org/piwigo/ui/main/MainViewModel.java | 9 -- .../piwigo/ui/main/MainViewModelFactory.java | 2 - .../org/piwigo/ui/shared/BaseFragment.java | 7 +- .../ui/shared/BindingRecyclerViewAdapter.java | 2 +- .../piwigo/ui/shared/SimpleTextWatcher.java | 31 ---- .../org/piwigo/ui/text/SimpleTextWatcher.java | 32 ---- .../ic_action_account_manage.png | Bin 0 -> 423 bytes .../main/res/drawable-hdpi/ic_action_add.png | Bin 353 -> 157 bytes .../res/drawable-hdpi/ic_action_delete.png | Bin 0 -> 228 bytes .../ic_action_account_manage.png | Bin 0 -> 298 bytes .../main/res/drawable-mdpi/ic_action_add.png | Bin 208 -> 134 bytes .../res/drawable-mdpi/ic_action_delete.png | Bin 0 -> 181 bytes .../ic_action_account_manage.png | Bin 0 -> 544 bytes .../main/res/drawable-xhdpi/ic_action_add.png | Bin 347 -> 202 bytes .../res/drawable-xhdpi/ic_action_delete.png | Bin 0 -> 267 bytes .../ic_action_account_manage.png | Bin 0 -> 840 bytes .../res/drawable-xxhdpi/ic_action_add.png | Bin 685 -> 223 bytes .../res/drawable-xxhdpi/ic_action_delete.png | Bin 0 -> 366 bytes .../res/drawable-xxxhdpi/ic_action_add.png | Bin 870 -> 320 bytes .../res/drawable-xxxhdpi/ic_action_delete.png | Bin 0 -> 500 bytes app/src/main/res/layout/account_row.xml | 52 +++++++ app/src/main/res/layout/activity_login.xml | 10 +- .../res/layout/activity_manage_accounts.xml | 71 +++++++++ app/src/main/res/layout/complete_fab.xml | 14 -- app/src/main/res/layout/drawer_header.xml | 14 +- app/src/main/res/layout/fragment_images.xml | 25 +++ app/src/main/res/layout/item_album.xml | 5 + app/src/main/res/layout/item_images.xml | 55 +++++++ app/src/main/res/menu/drawer_main.xml | 27 ++-- app/src/main/res/menu/manage_accounts.xml | 35 +++++ app/src/main/res/values-w480dp/dimens.xml | 4 +- app/src/main/res/values/dimens.xml | 1 + app/src/main/res/values/strings.xml | 22 ++- .../org/piwigo/accounts/UserManagerTest.java | 22 ++- .../org/piwigo/ui/main/MainViewModelTest.java | 11 +- build.gradle | 5 +- gradle/wrapper/gradle-wrapper.properties | 4 +- settings.gradle | 2 +- 73 files changed, 1458 insertions(+), 259 deletions(-) create mode 100644 .idea/gradle.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 app/src/debug/res/values/constants.xml create mode 100644 app/src/main/java/org/piwigo/helper/CommonVars.java delete mode 100644 app/src/main/java/org/piwigo/internal/binding/adapter/FABProgressCircleBindingAdapter.java create mode 100644 app/src/main/java/org/piwigo/io/model/ImageListResponse.java create mode 100644 app/src/main/java/org/piwigo/io/model/ImageUploadResponse.java create mode 100644 app/src/main/java/org/piwigo/io/repository/ImageRepository.java create mode 100644 app/src/main/java/org/piwigo/ui/account/AccountViewModel.java create mode 100644 app/src/main/java/org/piwigo/ui/account/ManageAccountsActivity.java create mode 100644 app/src/main/java/org/piwigo/ui/account/ManageAccountsViewModel.java create mode 100644 app/src/main/java/org/piwigo/ui/account/ManageAccountsViewModelFactory.java create mode 100644 app/src/main/java/org/piwigo/ui/main/ClickHandler.java create mode 100644 app/src/main/java/org/piwigo/ui/main/ImagesFragment.java rename app/src/main/java/org/piwigo/ui/{login/LoginView.java => main/ImagesFragmentModule.java} (73%) create mode 100644 app/src/main/java/org/piwigo/ui/main/ImagesItemViewModel.java create mode 100644 app/src/main/java/org/piwigo/ui/main/ImagesViewModel.java create mode 100644 app/src/main/java/org/piwigo/ui/main/ImagesViewModelFactory.java delete mode 100644 app/src/main/java/org/piwigo/ui/shared/SimpleTextWatcher.java delete mode 100644 app/src/main/java/org/piwigo/ui/text/SimpleTextWatcher.java create mode 100644 app/src/main/res/drawable-hdpi/ic_action_account_manage.png create mode 100644 app/src/main/res/drawable-hdpi/ic_action_delete.png create mode 100644 app/src/main/res/drawable-mdpi/ic_action_account_manage.png create mode 100644 app/src/main/res/drawable-mdpi/ic_action_delete.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_account_manage.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_delete.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_account_manage.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_delete.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_action_delete.png create mode 100644 app/src/main/res/layout/account_row.xml create mode 100644 app/src/main/res/layout/activity_manage_accounts.xml delete mode 100644 app/src/main/res/layout/complete_fab.xml create mode 100644 app/src/main/res/layout/fragment_images.xml create mode 100644 app/src/main/res/layout/item_images.xml create mode 100644 app/src/main/res/menu/manage_accounts.xml diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 00000000..7ac24c77 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..f7fa9698 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,28 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..c9d1dc54 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 4c491af4..541eb056 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![](https://travis-ci.org/Piwigo/Piwigo-Android.svg) -Currently under development by [@Philio](https://github.com/Philio), please get in touch if you're interested in contributing to +Currently under development by the Piwigo-Mobile team, please get in touch if you're interested in contributing to the project. If you're considering contributing, a working knowledge of the following would be extremely useful: @@ -33,4 +33,4 @@ If you're considering contributing, a working knowledge of the following would b ## Licensing The project is delivered under the GPL in version 3, or (at your option) any later version of that license. By submitting code to the project by patches, pull request or any other form the authors guarantee that it is either their own work and they accept to distribute their content under this license or the contribution is (re-)distributable under the terms of this license. If not specifically marked with a dedicated copyright notice, the copyright of the source code is transfered to to Piwigo project as far as permitted by applicable law. If necessary for legal reasons the source code author(s) shall be extracted from the meta data of the version control system. -Copyright notices in this project are mostly given with a reference to the year in form of xxxx-yyyy as a short cut with the meaning, that every year in the given range is a copyrigthable year. \ No newline at end of file +Copyright notices in this project are mostly given with a reference to the year in form of xxxx-yyyy as a short cut with the meaning, that every year in the given range is a copyrightable year. diff --git a/app/build.gradle b/app/build.gradle index 6ceaf9a0..121c5574 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,20 +1,18 @@ apply plugin: 'com.android.application' apply plugin: 'com.fernandocejas.frodo' -apply plugin: 'io.fabric' -def isCi = "true".equals(System.getenv("CI")) -def preDexEnabled = "true".equals(System.getProperty("pre-dex", "true")) +def isCi = "true" == System.getenv("CI") +def preDexEnabled = "true" == System.getProperty("pre-dex", "true") android { - compileSdkVersion 26 - buildToolsVersion '26.0.2' + compileSdkVersion 28 defaultConfig { applicationId "org.piwigo" minSdkVersion 14 - targetSdkVersion 26 + targetSdkVersion 28 versionCode 1 - versionName "2.0" + versionName "0.4" } buildTypes { debug { @@ -56,11 +54,11 @@ android { } ext { - supportVersion = '26.1.0' - lifecycleVersion = '1.0.0-rc1' - daggerVersion = '2.11' - okhttpVersion = '3.9.0' - retrofitVersion = '2.3.0' + supportVersion = '28.0.0' + lifecycleVersion = '1.1.1' + daggerVersion = '2.15' + okhttpVersion = '3.11.0' + retrofitVersion = '2.4.0' assertjVersion = '1.2.0' } @@ -86,17 +84,13 @@ dependencies { implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0' implementation 'io.reactivex:rxjava:1.3.2' implementation 'io.reactivex:rxandroid:1.2.1' - googlePlayImplementation('com.crashlytics.sdk.android:crashlytics:2.5.2@aar') { - transitive = true - } - implementation 'com.github.jorgecastilloprz:fabprogresscircle:1.01@aar' - implementation 'com.google.guava:guava:23.2-android' - annotationProcessor 'com.google.guava:guava:23.2-jre' - implementation 'org.apache.commons:commons-lang3:3.4' + implementation 'com.google.guava:guava:24.1-jre' + annotationProcessor 'com.google.guava:guava:24.1-jre' + implementation 'org.apache.commons:commons-lang3:3.8.1' testImplementation 'junit:junit:4.12' - testImplementation "org.robolectric:robolectric:3.4.2" + testImplementation "org.robolectric:robolectric:3.6.1" testImplementation("com.squareup.assertj:assertj-android:${assertjVersion}") { exclude group: 'com.android.support' } @@ -108,8 +102,8 @@ dependencies { } testAnnotationProcessor "com.google.dagger:dagger-compiler:${daggerVersion}" testImplementation "android.arch.core:core-testing:${lifecycleVersion}" - testImplementation 'org.mockito:mockito-core:2.10.0' - testImplementation 'com.google.guava:guava:23.2-android' - testAnnotationProcessor 'com.google.guava:guava:23.2-jre' + testImplementation 'org.mockito:mockito-core:2.13.0' + testImplementation 'com.google.guava:guava:24.1-jre' + testAnnotationProcessor 'com.google.guava:guava:24.1-jre' testImplementation 'com.google.code.findbugs:jsr305:3.0.1' } diff --git a/app/src/debug/res/values/constants.xml b/app/src/debug/res/values/constants.xml new file mode 100644 index 00000000..6cd38d83 --- /dev/null +++ b/app/src/debug/res/values/constants.xml @@ -0,0 +1,5 @@ + + + org.piwigo.account_debug + + diff --git a/app/src/floss/java/io/fabric/sdk/android/Fabric.java b/app/src/floss/java/io/fabric/sdk/android/Fabric.java index 62f1d7fc..e453dac9 100644 --- a/app/src/floss/java/io/fabric/sdk/android/Fabric.java +++ b/app/src/floss/java/io/fabric/sdk/android/Fabric.java @@ -19,6 +19,7 @@ import android.content.Context; +@SuppressWarnings("EmptyMethod") public class Fabric { public static void with(Context context, Object... kits) { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 92764900..7eb68ad8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,6 +10,10 @@ android:name="android.permission.GET_ACCOUNTS" android:maxSdkVersion="22" /> + + + diff --git a/app/src/main/java/org/piwigo/accounts/UserManager.java b/app/src/main/java/org/piwigo/accounts/UserManager.java index 5200ba8e..625e37b0 100644 --- a/app/src/main/java/org/piwigo/accounts/UserManager.java +++ b/app/src/main/java/org/piwigo/accounts/UserManager.java @@ -1,6 +1,7 @@ /* * Piwigo for Android - * Copyright (C) 2016-2017 Piwigo Team http://piwigo.org + * Copyright (C) 2016-2018 Piwigo Team http://piwigo.org + * Copyright (C) 2018 Raphael Mack * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,18 +21,22 @@ import android.accounts.Account; import android.accounts.AccountManager; +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.MutableLiveData; import android.content.res.Resources; import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; import org.apache.commons.lang3.StringUtils; import org.piwigo.R; import org.piwigo.io.repository.PreferencesRepository; +import java.util.List; + public class UserManager { @VisibleForTesting static final String KEY_IS_GUEST = "is_guest"; @@ -46,10 +51,28 @@ public class UserManager { private final Resources resources; private final PreferencesRepository preferencesRepository; + private final MutableLiveData mCurrentAccount; + private final MutableLiveData> mAllAccounts; + public UserManager(AccountManager accountManager, Resources resources, PreferencesRepository preferencesRepository) { this.accountManager = accountManager; this.resources = resources; this.preferencesRepository = preferencesRepository; + this.mCurrentAccount = new MutableLiveData<>(); + this.mAllAccounts = new MutableLiveData<>(); + + refreshAccounts(); + setActiveAccount(preferencesRepository.getActiveAccountName()); + } + + /* refresh account list - to be called by activities which are aware + * of a change in the accounts */ + public void refreshAccounts() { + Account[] accounts = accountManager.getAccountsByType(resources.getString(R.string.account_type)); + mAllAccounts.setValue(ImmutableList.copyOf(accounts)); + + Account a = mCurrentAccount.getValue(); + setActiveAccount(a == null ? "" : a.name); } public boolean isLoggedIn() { @@ -74,21 +97,13 @@ public Account createUser(String siteUrl, String username, String password, Stri } } - @SuppressWarnings("Guava") - public Optional getActiveAccount() { - Account[] accounts = accountManager.getAccountsByType(resources.getString(R.string.account_type)); - if (accounts.length == 0) { - return Optional.absent(); - } - String activeAccount = preferencesRepository.getActiveAccount(); - if (!TextUtils.isEmpty(activeAccount)) { - for (Account account : accounts) { - if (account.name.equals(activeAccount)) { - return Optional.of(account); - } - } - } - return Optional.of(accounts[0]); + /* observe this LiveData for notifications on account switches */ + public LiveData getActiveAccount() { + return mCurrentAccount; + } + + public LiveData> getAccounts(){ + return mAllAccounts; } public String getSiteUrl(Account account) { @@ -107,6 +122,14 @@ public String getToken(Account account) { return accountManager.getUserData(account, KEY_TOKEN); } + public boolean isGuest(Account account) { + return Boolean.parseBoolean(accountManager.getUserData(account, KEY_IS_GUEST)); + } + + public String getAccountName(Account account){ + return getAccountName(getSiteUrl(account), getUsername(account)); + } + private String getAccountName(String siteUrl, String username) { Uri uri = Uri.parse(siteUrl); String sitename = uri.getHost() + uri.getPath(); @@ -139,4 +162,41 @@ private Account createGuestUser(String siteUrl) { accountManager.addAccountExplicitly(account, null, userdata); return account; } + + public Account getAccountWithName(String accountName){ + Account[] accounts = accountManager.getAccountsByType(resources.getString(R.string.account_type)); + + for (Account account : accounts) { + if (account.name.equals(accountName)) { + return account; + } + } + return null; + } + + public void setActiveAccount(Account activeAccount) { + mCurrentAccount.setValue(activeAccount); + } + + public void setActiveAccount(String activeAccount) { + Account[] accounts = accountManager.getAccountsByType(resources.getString(R.string.account_type)); + + if (!TextUtils.isEmpty(activeAccount)) { + for (Account account : accounts) { + if (account.name.equals(activeAccount)) { + preferencesRepository.setActiveAccount(activeAccount); + mCurrentAccount.setValue(account); + return; + } + } + } + + /* the selected account is not available select default */ + if(accounts.length > 0) { + mCurrentAccount.setValue(accounts[0]); + }else{ + mCurrentAccount.setValue(null); + } + } + } diff --git a/app/src/main/java/org/piwigo/helper/CommonVars.java b/app/src/main/java/org/piwigo/helper/CommonVars.java new file mode 100644 index 00000000..b240a1f3 --- /dev/null +++ b/app/src/main/java/org/piwigo/helper/CommonVars.java @@ -0,0 +1,61 @@ +/* + * Copyright 2017 Phil Bayfield https://philio.me + * Copyright 2017 Piwigo Team http://piwigo.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 org.piwigo.helper; + +/** + * Created by Jeff on 10/1/2017. + * + * https://stackoverflow.com/questions/1944656/android-global-variable + */ + + + +public class CommonVars { + + private static CommonVars instance = new CommonVars(); + + + // Getter-Setters + public static CommonVars getInstance() { + return instance; + } + + public static void setInstance(CommonVars instance) { + CommonVars.instance = instance; + } + + private int cat_selected; + + private CommonVars() { + + } + + + public int getValue() { + return cat_selected ; + } + + + public void setValue(int catid) { + this.cat_selected = catid; + } + + + + +} diff --git a/app/src/main/java/org/piwigo/internal/binding/adapter/FABProgressCircleBindingAdapter.java b/app/src/main/java/org/piwigo/internal/binding/adapter/FABProgressCircleBindingAdapter.java deleted file mode 100644 index a70e5d34..00000000 --- a/app/src/main/java/org/piwigo/internal/binding/adapter/FABProgressCircleBindingAdapter.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Piwigo for Android - * Copyright (C) 2016-2017 Piwigo Team http://piwigo.org - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.piwigo.internal.binding.adapter; - -import android.databinding.BindingAdapter; - -import com.github.jorgecastilloprz.FABProgressCircle; -import com.github.jorgecastilloprz.listeners.FABProgressListener; - -import org.piwigo.internal.binding.observable.FABProgressCircleObservable; - -public class FABProgressCircleBindingAdapter { - - @BindingAdapter("onProgressAnimationEnd") public static void setAnimationEndListener(FABProgressCircle progressCircle, FABProgressListener listener) { - progressCircle.attachListener(listener); - } - - @BindingAdapter("state") public static void setState(FABProgressCircle progressCircle, FABProgressCircleObservable observable) { - switch (observable.getState()) { - case FABProgressCircleObservable.STATE_VISIBLE: - progressCircle.show(); - break; - case FABProgressCircleObservable.STATE_HIDDEN: - progressCircle.hide(); - break; - case FABProgressCircleObservable.STATE_FINAL: - progressCircle.beginFinalAnimation(); - break; - } - } -} 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 bb319364..062ec664 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 @@ -19,7 +19,6 @@ package org.piwigo.internal.binding.adapter; import android.databinding.BindingAdapter; -import android.util.Log; import android.view.ViewGroup; import android.widget.ImageView; diff --git a/app/src/main/java/org/piwigo/internal/di/module/AndroidInjectorModule.java b/app/src/main/java/org/piwigo/internal/di/module/AndroidInjectorModule.java index 619b5acc..839a2a47 100644 --- a/app/src/main/java/org/piwigo/internal/di/module/AndroidInjectorModule.java +++ b/app/src/main/java/org/piwigo/internal/di/module/AndroidInjectorModule.java @@ -20,11 +20,14 @@ import org.piwigo.internal.di.scope.PerActivity; import org.piwigo.internal.di.scope.PerFragment; +import org.piwigo.ui.account.ManageAccountsActivity; import org.piwigo.ui.launcher.LauncherActivity; import org.piwigo.ui.login.LoginActivity; import org.piwigo.ui.login.LoginActivityModule; import org.piwigo.ui.main.AlbumsFragment; import org.piwigo.ui.main.AlbumsFragmentModule; +import org.piwigo.ui.main.ImagesFragment; +import org.piwigo.ui.main.ImagesFragmentModule; import org.piwigo.ui.main.MainActivity; import org.piwigo.ui.main.MainActivityModule; @@ -41,5 +44,9 @@ public abstract class AndroidInjectorModule { @PerActivity @ContributesAndroidInjector(modules = MainActivityModule.class) abstract MainActivity mainActivity(); + @PerActivity @ContributesAndroidInjector(modules = MainActivityModule.class) abstract ManageAccountsActivity accountActivity(); + @PerFragment @ContributesAndroidInjector(modules = AlbumsFragmentModule.class) abstract AlbumsFragment albumsFragment(); + + @PerFragment @ContributesAndroidInjector(modules = ImagesFragmentModule.class) abstract ImagesFragment imagesFragment(); } diff --git a/app/src/main/java/org/piwigo/io/RestService.java b/app/src/main/java/org/piwigo/io/RestService.java index a79fa519..17d3ea7a 100644 --- a/app/src/main/java/org/piwigo/io/RestService.java +++ b/app/src/main/java/org/piwigo/io/RestService.java @@ -21,6 +21,7 @@ import org.piwigo.io.model.AddCategoryResponse; import org.piwigo.io.model.CategoryListResponse; import org.piwigo.io.model.GetImageInfoResponse; +import org.piwigo.io.model.ImageListResponse; import org.piwigo.io.model.StatusResponse; import org.piwigo.io.model.SuccessResponse; @@ -29,7 +30,9 @@ import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.Header; +import retrofit2.http.Multipart; import retrofit2.http.POST; +import retrofit2.http.Part; import retrofit2.http.Query; import rx.Observable; @@ -64,4 +67,24 @@ public interface RestService { @Query("image_id") int imageId ); + + //JCA added + @GET("ws.php?method=pwg.categories.getImages") + // List getImages(@Query("cat_id") Integer categoryId); + Observable getImages(@Query("cat_id") int categoryId); + + + @Multipart + @POST("ws.php?method=pwg.images.upload") + // @FormUrlEncoded + // Observable uploadImage( + String uploadImage( + @Part("image") String image, + @Part("category") String category, + @Part("name") String name, + @Part("pwg_token") String token + // @Part("file") TypedFile file <--- TO DO convert to Requestbody + + ); + } \ No newline at end of file diff --git a/app/src/main/java/org/piwigo/io/model/ImageListResponse.java b/app/src/main/java/org/piwigo/io/model/ImageListResponse.java new file mode 100644 index 00000000..ea42e36f --- /dev/null +++ b/app/src/main/java/org/piwigo/io/model/ImageListResponse.java @@ -0,0 +1,26 @@ +package org.piwigo.io.model; + +/** + * Created by Jeff on 7/18/2017. + */ + + +import com.google.gson.annotations.SerializedName; + +import java.util.ArrayList; +import java.util.List; + + +public class ImageListResponse { + + @SerializedName("stat") public String stat; + + @SerializedName("result") public Result result; + + public class Result { + + @SerializedName("images") public List images = new ArrayList<>(); + + } + +} diff --git a/app/src/main/java/org/piwigo/io/model/ImageUploadResponse.java b/app/src/main/java/org/piwigo/io/model/ImageUploadResponse.java new file mode 100644 index 00000000..d1a5e316 --- /dev/null +++ b/app/src/main/java/org/piwigo/io/model/ImageUploadResponse.java @@ -0,0 +1,12 @@ +package org.piwigo.io.model; + +/** + * Created by Jeff on 6/24/2017. + */ + +public class ImageUploadResponse { + + public String strg1; + + +} diff --git a/app/src/main/java/org/piwigo/io/repository/ImageRepository.java b/app/src/main/java/org/piwigo/io/repository/ImageRepository.java new file mode 100644 index 00000000..df60c854 --- /dev/null +++ b/app/src/main/java/org/piwigo/io/repository/ImageRepository.java @@ -0,0 +1,45 @@ +package org.piwigo.io.repository; + +/** + * Created by Jeff on 7/18/2017. + */ + + +import android.accounts.Account; +import android.support.annotation.Nullable; + +import org.piwigo.io.RestService; +import org.piwigo.io.RestServiceFactory; +import org.piwigo.io.model.ImageInfo; + +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Named; + +import rx.Observable; +import rx.Scheduler; + + +public class ImageRepository extends BaseRepository { + + @Inject public ImageRepository(RestServiceFactory restServiceFactory, @Named("IoScheduler") Scheduler ioScheduler, @Named("UiScheduler") Scheduler uiScheduler) { + super(restServiceFactory, ioScheduler, uiScheduler); + } + + public Observable> getImages(Account account, @Nullable Integer categoryId) { + RestService restService = restServiceFactory.createForAccount(account); + + return restService + .getImages(categoryId) + .map(imageListResponse -> imageListResponse.result.images) + .compose(applySchedulers()); + + + } + + + + } + + diff --git a/app/src/main/java/org/piwigo/io/repository/PreferencesRepository.java b/app/src/main/java/org/piwigo/io/repository/PreferencesRepository.java index 1732edb8..3cad3f98 100644 --- a/app/src/main/java/org/piwigo/io/repository/PreferencesRepository.java +++ b/app/src/main/java/org/piwigo/io/repository/PreferencesRepository.java @@ -34,12 +34,14 @@ public class PreferencesRepository { preferences = PreferenceManager.getDefaultSharedPreferences(context); } + /* double check whether this is really what you want. + * Maybe UserManager.setActiveAccount() is what you want */ public void setActiveAccount(String name) { set(KEY_ACTIVE_ACCOUNT, name); } - public String getActiveAccount() { - return preferences.getString(KEY_ACTIVE_ACCOUNT, null); + public String getActiveAccountName() { + return preferences.getString(KEY_ACTIVE_ACCOUNT,null); } private void set(String key, String value) { diff --git a/app/src/main/java/org/piwigo/ui/account/AccountViewModel.java b/app/src/main/java/org/piwigo/ui/account/AccountViewModel.java new file mode 100644 index 00000000..54e269f5 --- /dev/null +++ b/app/src/main/java/org/piwigo/ui/account/AccountViewModel.java @@ -0,0 +1,48 @@ +/* + * Piwigo for Android + * Copyright (C) 2018-2018 Raphael Mack http://www.raphael-mack.de + * Copyright (C) 2018-2018 Piwigo Team http://piwigo.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.piwigo.ui.account; + +import android.accounts.Account; +import android.arch.lifecycle.ViewModel; +import android.support.annotation.NonNull; + +import org.piwigo.accounts.UserManager; + +public class AccountViewModel extends ViewModel { + private final @NonNull Account account; + private final @NonNull UserManager userManager; + + public AccountViewModel(@NonNull UserManager userManager, @NonNull Account account) { + this.account = account; + this.userManager = userManager; + } + + public String getSiteUrl(){ + return userManager.getSiteUrl(account); + } + + public String getUsername(){ + return userManager.getUsername(account); + } + + public boolean isActive(){ + return userManager.getActiveAccount().getValue().name.equals(account.name); + } +} diff --git a/app/src/main/java/org/piwigo/ui/account/ManageAccountsActivity.java b/app/src/main/java/org/piwigo/ui/account/ManageAccountsActivity.java new file mode 100644 index 00000000..7abb584e --- /dev/null +++ b/app/src/main/java/org/piwigo/ui/account/ManageAccountsActivity.java @@ -0,0 +1,128 @@ +/* + * Piwigo for Android + * Copyright (C) 2016-2018 Piwigo Team http://piwigo.org + * Copyright (C) 2018-2018 Raphael Mack http://www.raphael-mack.de + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.piwigo.ui.account; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.accounts.AccountManagerCallback; +import android.accounts.AccountManagerFuture; +import android.accounts.OnAccountsUpdateListener; +import android.arch.lifecycle.ViewModelProviders; +import android.content.Intent; +import android.databinding.DataBindingUtil; +import android.os.Build; +import android.os.Bundle; + +import android.support.v4.app.Fragment; +import android.support.v4.app.NavUtils; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.Toolbar; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.ListView; + +import org.piwigo.R; +import org.piwigo.databinding.ActivityManageAccountsBinding; +import org.piwigo.ui.login.LoginActivity; +import org.piwigo.ui.shared.BaseActivity; + +import javax.inject.Inject; + +import dagger.android.AndroidInjection; +import dagger.android.DispatchingAndroidInjector; + +public class ManageAccountsActivity extends BaseActivity implements OnAccountsUpdateListener { + + @Inject + DispatchingAndroidInjector fragmentInjector; + + @Inject + ManageAccountsViewModelFactory viewModelFactory; + + @Inject AccountManager accountManager; + + private ManageAccountsViewModel viewModel; + + /** + * This invoked when the AccountManager starts up and whenever the account + * set changes. + * + * @param accounts the current accounts + */ + @Override + public void onAccountsUpdated(Account[] accounts) { + viewModel.refresh(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + AndroidInjection.inject(this); + super.onCreate(savedInstanceState); + + ActivityManageAccountsBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_manage_accounts); + + viewModel = ViewModelProviders.of(this, viewModelFactory).get(ManageAccountsViewModel.class); + + binding.setViewModel(viewModel); + Toolbar toolbar = findViewById(R.id.account_toolbar); + setSupportActionBar(toolbar); + viewModel.title.set(getString(R.string.title_activity_accounts)); + + binding.accountRecycler.setLayoutManager(new LinearLayoutManager(this)); + + accountManager.addOnAccountsUpdatedListener(this, null, true); + } + + public void onDestroy() { + /* cleanup the account update listener */ + accountManager.removeOnAccountsUpdatedListener(this); + super.onDestroy(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.manage_accounts, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_add_account: + startActivity(new Intent(getApplicationContext(), + LoginActivity.class)); + break; + case R.id.action_del_account: + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { + accountManager.removeAccount(userManager.getActiveAccount().getValue(), this, future -> viewModel.refresh(), null); + }else { + accountManager.removeAccount(userManager.getActiveAccount().getValue(), future -> viewModel.refresh(), null); + } + break; + case android.R.id.home: + NavUtils.navigateUpFromSameTask(this); + break; + default: + break; + } + return super.onOptionsItemSelected(item); + } + +} diff --git a/app/src/main/java/org/piwigo/ui/account/ManageAccountsViewModel.java b/app/src/main/java/org/piwigo/ui/account/ManageAccountsViewModel.java new file mode 100644 index 00000000..f43c4f29 --- /dev/null +++ b/app/src/main/java/org/piwigo/ui/account/ManageAccountsViewModel.java @@ -0,0 +1,86 @@ +/* + * Piwigo for Android + * Copyright (C) 2016-2018 Piwigo Team http://piwigo.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.piwigo.ui.account; + +import android.accounts.Account; +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.ViewModel; +import android.databinding.ObservableArrayList; +import android.databinding.ObservableField; +import android.view.View; + +import org.piwigo.BR; +import org.piwigo.R; +import org.piwigo.accounts.UserManager; +import org.piwigo.ui.shared.BindingRecyclerViewAdapter; + +import java.util.List; + + +public class ManageAccountsViewModel extends ViewModel { + public final ObservableField title = new ObservableField<>(); + + public final LiveData> accounts; + + private final ObservableArrayList items = new ObservableArrayList<>(); + public final BindingRecyclerViewAdapter.ViewBinder viewBinder = new AccountViewBinder(); + + private final UserManager userManager; + + public ManageAccountsViewModel(UserManager userManager) { + this.userManager = userManager; + accounts = userManager.getAccounts(); + items.addAll(accounts.getValue()); + } + + public void refresh(){ + userManager.refreshAccounts(); +// TODO: this is horrible + items.clear(); + items.addAll(accounts.getValue()); + + } + + public ObservableArrayList getItems() { + return items; + } + + private class AccountViewBinder implements BindingRecyclerViewAdapter.ViewBinder { + + @Override public int getViewType(Account account) { + return 0; + } + + @Override public int getLayout(int viewType) { + return R.layout.account_row; + } + + @Override public void bind(BindingRecyclerViewAdapter.ViewHolder viewHolder, Account account) { + AccountViewModel vm = new AccountViewModel(userManager, account); + viewHolder.getBinding().setVariable(BR.viewModel, vm); + boolean x = vm.isActive(); + viewHolder.itemView.setSelected(x); + viewHolder.itemView.setOnClickListener(v -> { + userManager.setActiveAccount(account); + refresh(); // dirty way to redraw the recycler... + }); + } + } + +} diff --git a/app/src/main/java/org/piwigo/ui/account/ManageAccountsViewModelFactory.java b/app/src/main/java/org/piwigo/ui/account/ManageAccountsViewModelFactory.java new file mode 100644 index 00000000..b7068991 --- /dev/null +++ b/app/src/main/java/org/piwigo/ui/account/ManageAccountsViewModelFactory.java @@ -0,0 +1,51 @@ +/* + * Piwigo for Android + * Copyright (C) 2016-2018 Piwigo Team http://piwigo.org + * Copyright (C) 2018-2018 Raphael Mack http://www.raphael-mack.de + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.piwigo.ui.account; + +import android.arch.lifecycle.ViewModel; +import android.arch.lifecycle.ViewModelProvider; +import android.content.Context; + +import org.piwigo.accounts.UserManager; +import org.piwigo.io.repository.UserRepository; + +import javax.inject.Inject; + +public class ManageAccountsViewModelFactory implements ViewModelProvider.Factory { + + private final Context context; + private final UserRepository userRepository; + + private final UserManager userManager; + + @Inject public ManageAccountsViewModelFactory(UserManager userManager, Context context, UserRepository userRepository) { + this.userManager = userManager; + this.context = context; + this.userRepository = userRepository; + } + + @Override public T create(Class viewModelClass) { + if (viewModelClass.isAssignableFrom(ManageAccountsViewModel.class)) { + //noinspection unchecked + return (T) new ManageAccountsViewModel(userManager); + } + throw new IllegalStateException("Unable to create " + viewModelClass.getName()); + } +} diff --git a/app/src/main/java/org/piwigo/ui/login/LoginActivity.java b/app/src/main/java/org/piwigo/ui/login/LoginActivity.java index 5a720361..96be8670 100644 --- a/app/src/main/java/org/piwigo/ui/login/LoginActivity.java +++ b/app/src/main/java/org/piwigo/ui/login/LoginActivity.java @@ -28,7 +28,6 @@ import android.os.Bundle; import android.os.Handler; import android.support.design.widget.Snackbar; -import android.support.v4.app.ActivityCompat; import org.piwigo.R; import org.piwigo.databinding.ActivityLoginBinding; @@ -62,22 +61,27 @@ public class LoginActivity extends BaseActivity { if (authenticatorResponse != null) { authenticatorResponse.onRequestContinued(); } - viewModel = ViewModelProviders.of(this, viewModelFactory).get(LoginViewModel.class); + + if(getIntent().hasExtra(AccountManager.KEY_ACCOUNT_NAME)) { + String accountName = getIntent().getStringExtra(AccountManager.KEY_ACCOUNT_NAME); + Account account = userManager.getAccountWithName(accountName); + + viewModel.username.set(userManager.getUsername(account)); + viewModel.url.set(userManager.getSiteUrl(account)); + if (!userManager.isGuest(account)) { + viewModel.password.set("******"); + } + } viewModel.getLoginSuccess().observe(this, this::loginSuccess); viewModel.getLoginError().observe(this, this::loginError); - viewModel.getAnimationFinished().observe(this, animationFinished -> { - if (animationFinished != null && animationFinished) { - finishWithDelay(); - } - }); binding = DataBindingUtil.setContentView(this, R.layout.activity_login); binding.setViewModel(viewModel); } + /** Clean up the account authenticator stuff, see {@link AccountAuthenticatorActivity} */ @Override public void finish() { - /** Clean up the account authenticator stuff, see {@link AccountAuthenticatorActivity} */ if (authenticatorResponse != null) { if (resultBundle != null) { authenticatorResponse.onResult(resultBundle); @@ -86,6 +90,7 @@ public class LoginActivity extends BaseActivity { } authenticatorResponse = null; } +// navigator.startMain(this); super.finish(); } @@ -98,6 +103,7 @@ private void loginSuccess(LoginResponse response) { Account account = userManager.createUser(response.url, response.statusResponse.result.username, response.password, response.pwgId, response.statusResponse.result.pwgToken); setResultIntent(account); viewModel.accountCreated(); + finish(); } } @@ -106,10 +112,6 @@ private void loginError(Throwable throwable) { .show(); } - private void finishWithDelay() { - handler.postDelayed(() -> ActivityCompat.finishAfterTransition(LoginActivity.this), 500); - } - private void setResultIntent(Account account) { Intent intent = new Intent(); intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name); diff --git a/app/src/main/java/org/piwigo/ui/login/LoginViewModel.java b/app/src/main/java/org/piwigo/ui/login/LoginViewModel.java index f126914c..d5d1217e 100644 --- a/app/src/main/java/org/piwigo/ui/login/LoginViewModel.java +++ b/app/src/main/java/org/piwigo/ui/login/LoginViewModel.java @@ -44,7 +44,7 @@ public class LoginViewModel extends ViewModel { @VisibleForTesting static Pattern WEB_URL = Patterns.WEB_URL; - public ObservableField url = new ObservableField<>("http://"); + public ObservableField url = new ObservableField<>("https://"); public ObservableField urlError = new ObservableField<>(); public ObservableField username = new ObservableField<>(); public ObservableField usernameError = new ObservableField<>(); 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 e3a87e7c..789551f0 100644 --- a/app/src/main/java/org/piwigo/ui/main/AlbumItemViewModel.java +++ b/app/src/main/java/org/piwigo/ui/main/AlbumItemViewModel.java @@ -19,17 +19,26 @@ package org.piwigo.ui.main; import android.arch.lifecycle.ViewModel; +import android.support.v7.app.AppCompatActivity; +import android.view.View; + +import org.piwigo.R; +import org.piwigo.helper.CommonVars; public class AlbumItemViewModel extends ViewModel { private final String url; private final String title; private final String photos; + private final Integer catid; + + CommonVars comvars = CommonVars.getInstance(); - AlbumItemViewModel(String url, String title, String photos) { + AlbumItemViewModel(String url, String title, String photos, Integer CategoryId) { this.url = url; this.title = title; this.photos = photos; + this.catid = CategoryId; } public String getUrl() { @@ -43,4 +52,18 @@ public String getTitle() { public String getPhotos() { return photos; } + + public Integer getCatId() { return catid;} + + public void onclickdo(View v){ + comvars.setValue(catid); + if(v.getContext() instanceof AppCompatActivity) { + ((AppCompatActivity) v.getContext()).getSupportFragmentManager() + .beginTransaction() + .replace(R.id.content, new ImagesFragment()) + .addToBackStack(null) + .commit(); + } + + } } 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 c41ed1f7..ff8f8a48 100644 --- a/app/src/main/java/org/piwigo/ui/main/AlbumsFragment.java +++ b/app/src/main/java/org/piwigo/ui/main/AlbumsFragment.java @@ -18,8 +18,11 @@ package org.piwigo.ui.main; +import android.accounts.Account; import android.app.Activity; import android.arch.lifecycle.ViewModelProviders; +import android.arch.lifecycle.Observer; + import android.content.Context; import android.content.res.Configuration; import android.databinding.DataBindingUtil; @@ -72,7 +75,12 @@ public class AlbumsFragment extends BaseFragment { super.onActivityCreated(savedInstanceState); AlbumsViewModel viewModel = ViewModelProviders.of(this, viewModelFactory).get(AlbumsViewModel.class); binding.setViewModel(viewModel); - viewModel.loadAlbums(null); + + final Observer accountObserver = account -> { + // reload the albums on account changes + viewModel.loadAlbums(null); + }; + userManager.getActiveAccount().observe(this, accountObserver); } private int calculateColumnCount() { @@ -81,4 +89,6 @@ private int calculateColumnCount() { boolean largeScreen = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE || screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE; return (int) Math.floor(configuration.screenWidthDp / (largeScreen ? TABLET_MIN_WIDTH : PHONE_MIN_WIDTH)); } + + } 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 53a82451..6dad2604 100644 --- a/app/src/main/java/org/piwigo/ui/main/AlbumsViewModel.java +++ b/app/src/main/java/org/piwigo/ui/main/AlbumsViewModel.java @@ -24,8 +24,6 @@ import android.databinding.ObservableArrayList; import android.util.Log; -import com.google.common.base.Optional; - import org.piwigo.BR; import org.piwigo.R; import org.piwigo.accounts.UserManager; @@ -64,9 +62,9 @@ public class AlbumsViewModel extends ViewModel { } void loadAlbums(Integer categoryId) { - Optional account = userManager.getActiveAccount(); - if (account.isPresent()) { - subscription = categoriesRepository.getCategories(account.get(), categoryId) + Account account = userManager.getActiveAccount().getValue(); + if (account != null) { + subscription = categoriesRepository.getCategories(account, categoryId) .subscribe(new CategoriesSubscriber()); } } @@ -101,8 +99,10 @@ private class CategoryViewBinder implements BindingRecyclerViewAdapter.ViewBinde 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); + AlbumItemViewModel viewModel = new AlbumItemViewModel(category.thumbnailUrl, category.name, photos, category.id); viewHolder.getBinding().setVariable(BR.viewModel, viewModel); } } + + } diff --git a/app/src/main/java/org/piwigo/ui/main/ClickHandler.java b/app/src/main/java/org/piwigo/ui/main/ClickHandler.java new file mode 100644 index 00000000..13c14510 --- /dev/null +++ b/app/src/main/java/org/piwigo/ui/main/ClickHandler.java @@ -0,0 +1,19 @@ +package org.piwigo.ui.main; + +import android.view.View; + +public class ClickHandler { + + private final String TAG = "LoginHandler"; + + public void performLogin(String userName, String password) { + // Some magic code of login + + // Log.d(TAG, "Username: " + userName + " & Password:" + password); + } + + public void setPasswordVisible(View view, boolean isVisible) { + + // Log.d(TAG, isVisible ? "Password is visible" : "Password is not visible"); + } +} diff --git a/app/src/main/java/org/piwigo/ui/main/ImagesFragment.java b/app/src/main/java/org/piwigo/ui/main/ImagesFragment.java new file mode 100644 index 00000000..2c7c7218 --- /dev/null +++ b/app/src/main/java/org/piwigo/ui/main/ImagesFragment.java @@ -0,0 +1,110 @@ +/* + * Copyright 2018 Jeff Amn + * Copyright 2018 Piwigo Team http://piwigo.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 org.piwigo.ui.main; + +/** + * Created by Jeff on 9/26/2017. + */ + + +import android.accounts.Account; +import android.app.Activity; +import android.arch.lifecycle.Observer; +import android.arch.lifecycle.ViewModelProviders; +import android.content.Context; +import android.content.res.Configuration; +import android.databinding.DataBindingUtil; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.GridLayoutManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import org.piwigo.R; +import org.piwigo.databinding.FragmentImagesBinding; +import org.piwigo.ui.shared.BaseFragment; + +import org.piwigo.helper.CommonVars; + +import javax.inject.Inject; + +import dagger.android.support.AndroidSupportInjection; + +public class ImagesFragment extends BaseFragment { + + private static final int PHONE_MIN_WIDTH = 320; + private static final int TABLET_MIN_WIDTH = 360; + + CommonVars comvars = CommonVars.getInstance(); + + @Inject + ImagesViewModelFactory viewModelFactory; + + private FragmentImagesBinding binding; + + @Override public void onAttach(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + AndroidSupportInjection.inject(this); + } + super.onAttach(context); + } + + @Override @SuppressWarnings("deprecation") public void onAttach(Activity activity) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + AndroidSupportInjection.inject(this); + } + super.onAttach(activity); + } + + @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + binding = DataBindingUtil.inflate(inflater, R.layout.fragment_images, container, false); + binding.recycler2.setLayoutManager(new GridLayoutManager(getContext(), calculateColumnCount())); + return binding.getRoot(); + + } + + @Override public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + // getActivityComponent().inject(this); + // bindLifecycleEvents(viewModel); + // binding.setViewModel(viewModel); + // viewModel.loadImages(comvars.getValue()); + + ImagesViewModel viewModel = ViewModelProviders.of(this, viewModelFactory).get(ImagesViewModel.class); + binding.setViewModel(viewModel); + + final Observer accountObserver = newName -> { + // reload the albums on account changes + viewModel.loadImages(comvars.getValue()); + }; + userManager.getActiveAccount().observe(this, accountObserver); + } + + private int calculateColumnCount() { + Configuration configuration = getResources().getConfiguration(); + int screenSize = configuration.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK; + boolean largeScreen = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE || screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE; + return (int) Math.floor(configuration.screenWidthDp / (largeScreen ? TABLET_MIN_WIDTH : PHONE_MIN_WIDTH)); + } + + + +} + diff --git a/app/src/main/java/org/piwigo/ui/login/LoginView.java b/app/src/main/java/org/piwigo/ui/main/ImagesFragmentModule.java similarity index 73% rename from app/src/main/java/org/piwigo/ui/login/LoginView.java rename to app/src/main/java/org/piwigo/ui/main/ImagesFragmentModule.java index 7c26e7d4..5ac20fa8 100644 --- a/app/src/main/java/org/piwigo/ui/login/LoginView.java +++ b/app/src/main/java/org/piwigo/ui/main/ImagesFragmentModule.java @@ -16,16 +16,17 @@ * along with this program. If not, see . */ -package org.piwigo.ui.login; +package org.piwigo.ui.main; -import org.piwigo.io.model.LoginResponse; +import android.content.res.Resources; -public interface LoginView { +import dagger.Module; +import dagger.Provides; - void onSuccess(LoginResponse response); - - void onError(); - - void onAnimationFinished(); +@Module +public class ImagesFragmentModule { + @Provides Resources provideResources(ImagesFragment fragment) { + return fragment.getResources(); + } } diff --git a/app/src/main/java/org/piwigo/ui/main/ImagesItemViewModel.java b/app/src/main/java/org/piwigo/ui/main/ImagesItemViewModel.java new file mode 100644 index 00000000..c2e5cc5f --- /dev/null +++ b/app/src/main/java/org/piwigo/ui/main/ImagesItemViewModel.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Phil Bayfield https://philio.me + * Copyright 2017 Piwigo Team http://piwigo.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 org.piwigo.ui.main; + +/** + * Created by Jeff on 9/26/2017. + */ + +import android.arch.lifecycle.ViewModel; + +public class ImagesItemViewModel extends ViewModel { + + + private final String url; + private final String title; + + + + public ImagesItemViewModel(String url, String title) { + this.url = url; + this.title = title; + + + } + + public String getUrl() { + return url; + } + + public String getTitle() { + return title; + } + + +} diff --git a/app/src/main/java/org/piwigo/ui/main/ImagesViewModel.java b/app/src/main/java/org/piwigo/ui/main/ImagesViewModel.java new file mode 100644 index 00000000..fe922b69 --- /dev/null +++ b/app/src/main/java/org/piwigo/ui/main/ImagesViewModel.java @@ -0,0 +1,145 @@ +/* + * Copyright 2017 Phil Bayfield https://philio.me + * Copyright 2017 Piwigo Team http://piwigo.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 org.piwigo.ui.main; + +/** + * Created by Jeff on 9/26/2017. + */ + +import android.accounts.Account; +import android.arch.lifecycle.ViewModel; +import android.content.res.Resources; +import android.databinding.ObservableArrayList; +import android.util.Log; + +import org.piwigo.BR; +import org.piwigo.R; +import org.piwigo.accounts.UserManager; +import org.piwigo.io.model.ImageInfo; +import org.piwigo.io.repository.ImageRepository; +import org.piwigo.ui.shared.BindingRecyclerViewAdapter; + +import java.util.List; + +import javax.inject.Inject; + + +import rx.Subscriber; +import rx.Subscription; + +public class ImagesViewModel extends ViewModel { + + + public ObservableArrayList images = new ObservableArrayList<>(); + public BindingRecyclerViewAdapter.ViewBinder viewBinder = new ImagesViewBinder(); + + private final UserManager userManager; + private final ImageRepository imageRepository; + private final Resources resources; + + private Integer categoryId; + private Subscription subscription; + + @Inject public ImagesViewModel(UserManager userManager, ImageRepository imageRepository, Resources resources) { + this.userManager = userManager; + this.imageRepository = imageRepository; + this.resources = resources; + } + public void onDestroy() { + // Log.e(TAG, "onDestroy"); + if (subscription != null) { + subscription.unsubscribe(); + } + } + + public void loadImages(Integer categoryId) { + this.categoryId = categoryId; + Account account = userManager.getActiveAccount().getValue(); + if (account != null) { + subscription = imageRepository.getImages(account, categoryId) + .subscribe(new ImagesSubscriber()); + } + } + + + private class ImagesSubscriber extends Subscriber> { + + @Override public void onCompleted() {} + + @Override public void onError(Throwable e) { + Log.e("error", e.getMessage()); + } + + @Override public void onNext(List imagelist) { + images.clear(); + images.addAll(imagelist); + } + + } + + + + + + + + + private class ImagesViewBinder implements BindingRecyclerViewAdapter.ViewBinder { + + @Override public int getViewType(ImageInfo image) { + return 0; + } + + @Override public int getLayout(int viewType) { + return R.layout.item_images; + } + + @Override public void bind(BindingRecyclerViewAdapter.ViewHolder viewHolder, ImageInfo image) { + // String photos = resources.getQuantityString(R.plurals.album_photos, item.first.nbImages, item.first.nbImages); + // if (item.first.totalNbImages > item.first.nbImages) { + // int subPhotos = item.first.totalNbImages - item.first.nbImages; + // photos += resources.getQuantityString(R.plurals.album_photos_subs, subPhotos, subPhotos); + // } + //Album has no photos yet - set to dummy value + // String imageurl =""; + // if (item.second == null){ + // } + // else + // { + // imageurl = item.second.derivatives.large.url; + // } + // AlbumItemViewModel viewModel = new AlbumItemViewModel(imageurl, item.first.name, photos); + // viewHolder.getBinding().setVariable(BR.viewModel, viewModel); + String imageurl =""; + imageurl = image.elementUrl; + + String imagename = image.name; + + ImagesItemViewModel viewModel = new ImagesItemViewModel(imageurl, imagename); + viewHolder.getBinding().setVariable(BR.viewModel, viewModel); + } + + } + + + + + + + +} diff --git a/app/src/main/java/org/piwigo/ui/main/ImagesViewModelFactory.java b/app/src/main/java/org/piwigo/ui/main/ImagesViewModelFactory.java new file mode 100644 index 00000000..8e33f74f --- /dev/null +++ b/app/src/main/java/org/piwigo/ui/main/ImagesViewModelFactory.java @@ -0,0 +1,51 @@ +/* + * Piwigo for Android + * Copyright (C) 2016-2017 Piwigo Team http://piwigo.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.piwigo.ui.main; + +import android.arch.lifecycle.ViewModel; +import android.arch.lifecycle.ViewModelProvider; +import android.content.Context; + +import org.piwigo.accounts.UserManager; +import org.piwigo.io.repository.ImageRepository; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class ImagesViewModelFactory implements ViewModelProvider.Factory { + + private final Context context; + private final UserManager userManager; + private final ImageRepository imageRepository; + + @Inject public ImagesViewModelFactory(Context context, UserManager userManager, ImageRepository imageRepository) { + this.context = context; + this.userManager = userManager; + this.imageRepository = imageRepository; + } + + @Override public T create(Class viewModelClass) { + if (viewModelClass.isAssignableFrom(ImagesViewModel.class)) { + //noinspection unchecked + return (T) new ImagesViewModel(userManager, imageRepository, context.getResources()); + } + throw new IllegalStateException("Unable to create " + viewModelClass.getName()); + } +} diff --git a/app/src/main/java/org/piwigo/ui/main/MainActivity.java b/app/src/main/java/org/piwigo/ui/main/MainActivity.java index 34d32158..4c6355ed 100644 --- a/app/src/main/java/org/piwigo/ui/main/MainActivity.java +++ b/app/src/main/java/org/piwigo/ui/main/MainActivity.java @@ -18,14 +18,19 @@ package org.piwigo.ui.main; +import android.accounts.Account; +import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProviders; +import android.content.Intent; import android.databinding.DataBindingUtil; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.widget.Toast; import org.piwigo.R; import org.piwigo.databinding.ActivityMainBinding; import org.piwigo.databinding.DrawerHeaderBinding; +import org.piwigo.ui.account.ManageAccountsActivity; import org.piwigo.ui.shared.BaseActivity; import javax.inject.Inject; @@ -55,6 +60,18 @@ public class MainActivity extends BaseActivity implements HasSupportFragmentInje binding.navigationView.addHeaderView(headerBinding.getRoot()); setSupportActionBar(binding.toolbar); + final Observer accountObserver = account -> { + // reload the albums on account changes + if(account != null) { + viewModel.username.set(userManager.getUsername(account)); + viewModel.url.set(userManager.getSiteUrl(account)); + }else{ + viewModel.username.set(""); + viewModel.url.set(""); + } + }; + userManager.getActiveAccount().observe(this, accountObserver); + if (savedInstanceState == null) { viewModel.setTitle(getString(R.string.nav_albums)); getSupportFragmentManager() @@ -69,9 +86,23 @@ public class MainActivity extends BaseActivity implements HasSupportFragmentInje } private void itemSelected(int itemId) { + + // TODO: this one is called often, also if the screen is rotated. switch (itemId) { case R.id.nav_albums: break; + case R.id.nav_manage_accounts: + startActivity(new Intent(getApplicationContext(), + ManageAccountsActivity.class)); + break; + case R.id.nav_upload: + default: + Toast.makeText(this,"not yet implemented",Toast.LENGTH_LONG).show(); + break; } } + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + } + } diff --git a/app/src/main/java/org/piwigo/ui/main/MainViewModel.java b/app/src/main/java/org/piwigo/ui/main/MainViewModel.java index b19ca9bb..f8a34bb6 100644 --- a/app/src/main/java/org/piwigo/ui/main/MainViewModel.java +++ b/app/src/main/java/org/piwigo/ui/main/MainViewModel.java @@ -18,7 +18,6 @@ package org.piwigo.ui.main; -import android.accounts.Account; import android.arch.lifecycle.LiveData; import android.arch.lifecycle.MutableLiveData; import android.arch.lifecycle.ViewModel; @@ -27,8 +26,6 @@ import android.databinding.ObservableField; import android.databinding.ObservableInt; -import com.google.common.base.Optional; - import org.piwigo.R; import org.piwigo.accounts.UserManager; @@ -43,12 +40,6 @@ public class MainViewModel extends ViewModel { private MutableLiveData selectedNavigationItemId = new MutableLiveData<>(); MainViewModel(UserManager userManager) { - Optional account = userManager.getActiveAccount(); - if (account.isPresent()) { - username.set(userManager.getUsername(account.get())); - url.set(userManager.getSiteUrl(account.get())); - } - navigationItemId.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() { @Override public void onPropertyChanged(Observable sender, int propertyId) { diff --git a/app/src/main/java/org/piwigo/ui/main/MainViewModelFactory.java b/app/src/main/java/org/piwigo/ui/main/MainViewModelFactory.java index 6415009f..0279f723 100644 --- a/app/src/main/java/org/piwigo/ui/main/MainViewModelFactory.java +++ b/app/src/main/java/org/piwigo/ui/main/MainViewModelFactory.java @@ -20,10 +20,8 @@ import android.arch.lifecycle.ViewModel; import android.arch.lifecycle.ViewModelProvider; -import android.content.Context; import org.piwigo.accounts.UserManager; -import org.piwigo.io.repository.CategoriesRepository; import javax.inject.Inject; import javax.inject.Singleton; diff --git a/app/src/main/java/org/piwigo/ui/shared/BaseFragment.java b/app/src/main/java/org/piwigo/ui/shared/BaseFragment.java index 7b7cf448..2932d7df 100644 --- a/app/src/main/java/org/piwigo/ui/shared/BaseFragment.java +++ b/app/src/main/java/org/piwigo/ui/shared/BaseFragment.java @@ -20,6 +20,11 @@ import android.support.v4.app.Fragment; -public abstract class BaseFragment extends Fragment { +import org.piwigo.accounts.UserManager; + +import javax.inject.Inject; +public abstract class BaseFragment extends Fragment { + @Inject + protected UserManager userManager; } diff --git a/app/src/main/java/org/piwigo/ui/shared/BindingRecyclerViewAdapter.java b/app/src/main/java/org/piwigo/ui/shared/BindingRecyclerViewAdapter.java index c7157b58..c6fb1906 100644 --- a/app/src/main/java/org/piwigo/ui/shared/BindingRecyclerViewAdapter.java +++ b/app/src/main/java/org/piwigo/ui/shared/BindingRecyclerViewAdapter.java @@ -1,6 +1,6 @@ /* * Piwigo for Android - * Copyright (C) 2016-2017 Piwigo Team http://piwigo.org + * Copyright (C) 2016-2018 Piwigo Team http://piwigo.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/app/src/main/java/org/piwigo/ui/shared/SimpleTextWatcher.java b/app/src/main/java/org/piwigo/ui/shared/SimpleTextWatcher.java deleted file mode 100644 index ec0e4b5b..00000000 --- a/app/src/main/java/org/piwigo/ui/shared/SimpleTextWatcher.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Piwigo for Android - * Copyright (C) 2016-2017 Piwigo Team http://piwigo.org - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.piwigo.ui.shared; - -import android.text.Editable; -import android.text.TextWatcher; - -public class SimpleTextWatcher implements TextWatcher { - - @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - - @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override public void afterTextChanged(Editable s) {} -} diff --git a/app/src/main/java/org/piwigo/ui/text/SimpleTextWatcher.java b/app/src/main/java/org/piwigo/ui/text/SimpleTextWatcher.java deleted file mode 100644 index e2192509..00000000 --- a/app/src/main/java/org/piwigo/ui/text/SimpleTextWatcher.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Piwigo for Android - * Copyright (C) 2016-2017 Piwigo Team http://piwigo.org - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.piwigo.ui.text; - -import android.text.Editable; -import android.text.TextWatcher; - -public class SimpleTextWatcher implements TextWatcher { - - @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - - @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override public void afterTextChanged(Editable s) {} - -} diff --git a/app/src/main/res/drawable-hdpi/ic_action_account_manage.png b/app/src/main/res/drawable-hdpi/ic_action_account_manage.png new file mode 100644 index 0000000000000000000000000000000000000000..c41703d139760fb237b3e75cce0f91c892af6d64 GIT binary patch literal 423 zcmV;Y0a*TtP)S6orep5XE)7s=CnZLjESnszkBi8~6w<^chM6fiYgoC%XWc=XHIvuXO-itaW{}uK-929or&y{xy0G8=3o`67n@F z0Nnxbjr0ziBlj1uk3;fbI{*UxMms}$ABN%8zFisD&htFKR!ThrXx0=+3jl(8LBJyh z*VMn~d6)1};NDl`02sj^wBxcYPY$g;VYW`;?+GAlBLJ)r1VM1ybrB7F#a&e;q%#1F z)`PA}Abo2G@O}S67XW>02hd%Q6#&_ZZ2@q;xa)j*-T5CJ&i`T(i9{kJ+5+@x;#tZZ R|F!@C002ovPDHLkV1m{Gx5oeg literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_action_add.png b/app/src/main/res/drawable-hdpi/ic_action_add.png index 244eff767f3fe14a92e606e8961a8276e68b339b..0ed679add7950a63675dc0f41d59e1b58442c76e 100644 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBQaoK8Ln>~)y|Iy#L6OHH@c9Xw zm7BY(@A+ABa|>!eG+A!{;r0ivK!c@|kKJ9G61z!w$nZ|Ej|GCjj`i zf=~boC>el-lmx2VvnkNF?Izr=>$to+Sui56^bBAH5t+nScO4N0IXqv`y z_vOB|SpXv0hO>u{5x#chG)c3Q1VDH#3U*ml%Fa%I1t5&aOSI0!_$cjbCnCBnHDjVh#|k1|%Oc%$NbBR(rZQhE&{od&8E`!9k!cG0>uM zmhy_wz6F7rGRgc44qW|nC-ZCxm$bdH_X+h%>$LeSXIT!)>t*LUnzD=fCwgTqn%4Yd zUeN0cbF#```6X>zan4YCKhr9GnX2tl3cdjzuJgFx*W59jsv++EZ`;ActECv2I20OS z#Deb*d)Wi@8727@lo?a6tm$|dIkQCg(C&GGjE9Y-)_(Qz3RRyLvhK&tFOzTY6lIvV W>iW4$8!~{-X7F_Nb6Mw<&;$TW1XP;< literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_action_account_manage.png b/app/src/main/res/drawable-mdpi/ic_action_account_manage.png new file mode 100644 index 0000000000000000000000000000000000000000..217c343b85b70232844a8b4db83716c042cdb8dc GIT binary patch literal 298 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJkDe}$Ar-fh6C_v{Gw`lhz5271 zq-3hJw6wpeq2WwVULI3z=@c_Z_6D8h(~d?I09gT-pWkq5TELv~qS|0t7juJMCex)h zK0ZDf1)e15qZ#iRCb&ABX;po-qoa_;)aiggf1L9yYX*@gJH9wAPM%?%aA0wQfy$xA zvu(|b6r=*!8MIeRI_zSUc%tbb!}X+{u~2KmU5=@Xdzl;BuFsw|>(=bqvp+w)#65}G z>WJVIiB*;iQPx%rOC>sUgH23K3?!wbtddtpdX_OSn=#*(uETG-N-d{nU^sWMIg7Z*06Oa*_+s^9-J@elF{r5}E*`_-kwc literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_action_add.png b/app/src/main/res/drawable-mdpi/ic_action_add.png index 5a8cae4d5f6c395d22d31ad6c5b6666514816580..0bd6ce55d85bc1e1090d12f88b0fdc8faf546b98 100644 GIT binary patch literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjzMd|QAr-fh6C`vV{Qv)7(qRvK zmvKg-qoTn4#z%(&x!rUn^28jB0~HzfNStgs>ayaz!?pzeNoiRRZA-Q`Y;!c3<>Rg^ hu{B{r$gd|%3^$%T?cP##csI~s22WQ%mvv4FO#pd!E^`0? literal 208 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ>7Fi*ArbD$DG~_>EDn4#?y*WR zVL8FaC@LyCbASE+s0JZJW8=@A*5&VP6xAIkzh!WBJu1M))^;_(+xh+d{rl6dFfLX! zkYWnqWqeZ8cR0ZtD5ta{MxL4ZaA6GJfpEVEI_wudSz69>zSg{Xj>H~5i4PhIBF`4P ze$3$LX*FVdQ&MBb@ E0O)E-RsaA1 diff --git a/app/src/main/res/drawable-mdpi/ic_action_delete.png b/app/src/main/res/drawable-mdpi/ic_action_delete.png new file mode 100644 index 0000000000000000000000000000000000000000..a794cfc1c0eb0d0470aa1233c2115fb71052dc86 GIT binary patch literal 181 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjHJ&bxAr-fh6C^x7{QqCisSwA0 zI2pXtkNow``s)aE2ZN`ppUXO@geCwL9YJmY literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_action_account_manage.png b/app/src/main/res/drawable-xhdpi/ic_action_account_manage.png new file mode 100644 index 0000000000000000000000000000000000000000..b2bedacc00ccd9669b53e17ab32c4a222695e727 GIT binary patch literal 544 zcmV+*0^j|KP);K$$^c9(ctr}MiWC^z zYy@B$08GmVROe&lXD7?DH8FWF*W_Mp0pv?*HX4nVrumY4@)?!Ot`Pw8fZPH;T~!cF znE_b|zgaB+NM6sH_OsGKMNQBSK#E&g-|}7S0Z4_funX;24?vc=vcBcJ1i%zv5#%z+ zjS#oOJPh$T%pXJufB*=904&}Ie8BEdE^cctyZh2rO_MXSJx`e!sttaUzUyi`O@603h&3*in^Z@NdUrjClfkF&03+ zdppDH^1ON!JkMLfj5sfn9*Y9-g#6uIRI`TE3-M_L0LgXb9U1@ot)MHuO_%|vy4rTc zw{`%Sj$66_h;Qux@R7F0-mSI?0JMq#coral`2uKslT_o|Wq9}^0rM>|+Qm1NyABvv<0000P!Mnk%zt<+ zxg=fup0fGfOsRveCj?x$eE&4=-`Ki$fszKxvvg&pz|&EZS=kqv6*701@oe470yG2x zR_|MKsl{xqRKu10G` iWMDY(dp+Bk!3AI^5qVBEo3N5?wD`<&9kc8%& zXs+G=Jx*D{!jeTEp;V5vANdlUeST5*z{ei>yCa1-g`IsUC%An3syYOSBo(;G&BUwWe)$e z>C*ZMD=(i*wPW;c_+Q5ibO$zYhar@~;i+%{3xkLqV`tSHi#?XwA8SueTz#GI@NDBx xYxA;#N`w8cuKls+LHOLem*31SQZHNbmGxoeqNj6S&N>1z($m$?Wt~$(695(KYL);1 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_account_manage.png b/app/src/main/res/drawable-xxhdpi/ic_action_account_manage.png new file mode 100644 index 0000000000000000000000000000000000000000..4a65df32d523e3e281a51514a1879e8749e37dc8 GIT binary patch literal 840 zcmV-O1GoH%P)^17Oj>N8M3`&W7v)Mc$4y=n!Tn~B*jENM$r=I5>FFg2R7`|E6!2but>mngE zIw46w=yA1#`wjJO1?`p8;`KR0Hwz>}h zvMKeiTCLW(gZioa=)M3rgoR=FU^E&XUDj9KSC0XJB}@Kcf09d4{xkzj0pweR&(L{CO4jAX?`xpRoOdqK7^4&hH0U*uvsWva) z_1FNIV|nEN>3RSF03ZbcfJ&HVC;)g6<5dIzcp1m*XaLY5Lzg4~=#=MYDFEPySpWb4 z00000000000H_`S`x)rxFbv;|ZOHn|APAnz`V0L~TI`)2Lg0%m_W+Phz~4%M?}@c# z{c^wGKV{NChHiMCcedSbUx}i~m*d=5Fk<@vm>=*TTDoQZq3`>*(xz(wwzBMG&s(+=f6EB~QkuR?E9a`Inbc?X-30*aRm}MdsG+{s9)Ogj8>XgG z-(9!^PS+KH`d)hgrse_w000000MH`_00000003a%)+!9#%Fx9n4_(aQ-DM8m&G7Xl z4_|MXz@gj;98^qUQtlKce;_c4Pf3&bOs6BJv8rWnA3_Krgb+dqA%qYrLB9dm(@;f< ST{hGJ0000~)y>pQBfPw&v!|tsj z-5dCJd-xx7zZb~SaWV47e?$GFhXq_xu3w2t&VFYyk7r8MdOu+WhXw{lCKe6>9E@MQ z7e0s0Q`^SFF!iMIQS${h1|Qy?g=$%#+$bXw9wk*O&Wzgth}riWYc{A9mE}!yInHr= T*2PAkiy1s!{an^LB{Ts5ojgF; literal 685 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>U@Gx+aSW-5dppO_i z=8Q}N32F&)=h+kv_#CjA$Lr8Av!T*Px`Dx%@pFY417jM~vyV9pOlMfmJif`mGJ|u* z@y(1J2EqpY@psvBw%?weIm^%PeW8qf`R=>BXJ%&pS;dlLHv40Ng^lZxyJuF{$hJK! z+<)I+mFw6CDOMZzBY$}|PfwJP6S(lD?-$TKlaIdHf)kWp@hU8so`0*aK_oDrfpKrm zaXn3wg(`|YgEH6bVGG*;~lF4#n;x#U8E&s u@E*R{&%pjQ-dK=upl diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_delete.png b/app/src/main/res/drawable-xxhdpi/ic_action_delete.png new file mode 100644 index 0000000000000000000000000000000000000000..405e2575353fee1bb30f03b8419aea1f0ae09e90 GIT binary patch literal 366 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2U^Mk~aSW-r_4dw2t|kYDV;_rq zmux+FF!In=#alIPaZA}>$_hoZWM=V3y_);RddD;~$Gz4+>p!f$dp%!3#xI#eapUs$ zzt>iU$}3;_cdjhc!u+doQhv8Xk;T~)7W>T{6*GNSzGMHg;F|EmKT*4j+ump`XPWiv z{JE=A3JnZQ96;h1d(_I;tR+WJ%X9vh)eh|!G@UD*A%3&Dl3l=ofsutQ;wOvNm2wq} zvUEf9fOY$n7&lpe-r4x(>8@%OhjRVtFG^lm3N6_DQBZcy&h;BxdXm4V9t$t2SZc?7 zbmMNV$Hr0U}X1naSW-r_4f8b&K3g^*TB`D zyxWp>BbTjWEcf%D$r9wi)Kvc=rouY*MWJZHZ52=JUdH)}X$+r! zG%2m!e<7Rkfz)@G>OLFh05Q2M*TR5KMFI{E4DN#b@~##=)t?N`6>dSX3P~LS=7Y2b nlYjSgCZDeV?L0^2rRiUWV|qt)ea|Mufi!x$`njxgN@xNAAk0+n literal 870 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7xzrVAl0?aSW-5dwb_#u5=(zOX7P+ zUzQ85p-cLfObeM9HOVTbRgdXT3m;dJ={E<)YaRZ7YSgAZDVX;D{?;XL&)&~q-FESA z_P<`nw%HAg5(zt)4&UBR1GHS`BUKu8v9e7#tt8n+- ze<5t!a&Mpi{PWLtq1{zH%x`=qFotda>i5^|z`uZ82I&W^`Q_3JY(k_DuxZRred)l{ zz-YtvE_e6R{MXi9+Zl5hfD#|nK5S;UVXffW@mL|&LWDVi0jSD=flWgu`JZ%zK;~8f z2>$?s#Dapd#D*r1)vYi!2N+s6b2E#$MCr01^v#KtSfFqzOHqOWA~x?B!}l8d|ANO) zzb*Uy|2D(^uIvBy=H9M0{C4{Ar2YN^zXM*_rhk~Oz3T?+WPwu*yk`$G@U~CV>13Rg zWq#%;5$vy%*gk0Oc(-MGjc82%f5VC2_jLK)YwUlyt?ufL)eovX`#Vz_YGWl6+{L9I z7@9u}UZ2H$gTYR4%l5bPs-oE@-)1mt;7wru;qxG!zk=(7h=5JU{25#b|HwGsV-dse zMFWS2Zw@iAP7LEd$N=*;SGqWxM#q*Y4mM!OfrBEzVz+^VVBGEL;uunK>+Rj$Ud(|atQQp7 zJabd)+&CkaZ}{?&J!85*W>^;vfCEaC@EA2&I<@Cu~3~m=sPMaIL8b-QtUm6B4>SM67IUp^hUeO~gxX2yC;dq$Wt z+RzTY3~Ia#GoJ7mHv^a z68L1E#3tFj`rm)IzKJcL`R2u6=oVgU{ym z?*i`UpFjTL_{GgHoWEH968n2%OMd3Dc9YMAib_hG7XM)obMv|KY=gu`kOw_o{an^L HB{Ts5H88#j literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/account_row.xml b/app/src/main/res/layout/account_row.xml new file mode 100644 index 00000000..833764c2 --- /dev/null +++ b/app/src/main/res/layout/account_row.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index bded346d..cda3dfa7 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -60,6 +60,7 @@ android:inputType="textUri" android:maxLines="1" android:nextFocusDown="@+id/username" + android:autofillHints="url" android:text="@={viewModel.url}" /> @@ -79,6 +80,7 @@ android:maxLines="1" android:nextFocusDown="@+id/password" android:nextFocusUp="@+id/url" + android:autofillHints="username" android:text="@={viewModel.username}" /> @@ -99,9 +101,10 @@ android:maxLines="1" android:nextFocusDown="@+id/login_button" android:nextFocusUp="@+id/username" + android:autofillHints="password" android:text="@={viewModel.password}" /> - + - + diff --git a/app/src/main/res/layout/activity_manage_accounts.xml b/app/src/main/res/layout/activity_manage_accounts.xml new file mode 100644 index 00000000..5be3233c --- /dev/null +++ b/app/src/main/res/layout/activity_manage_accounts.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/complete_fab.xml b/app/src/main/res/layout/complete_fab.xml deleted file mode 100644 index 7965174c..00000000 --- a/app/src/main/res/layout/complete_fab.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/drawer_header.xml b/app/src/main/res/layout/drawer_header.xml index b77fcb5a..a7a360b8 100644 --- a/app/src/main/res/layout/drawer_header.xml +++ b/app/src/main/res/layout/drawer_header.xml @@ -20,7 +20,8 @@ android:layout_height="wrap_content" android:layout_gravity="start" android:layout_margin="@dimen/nav_header_padding" - android:src="@drawable/piwigo_logo" /> + android:src="@drawable/piwigo_logo" + android:contentDescription="@string/nav_icon_description"/> - + - \ No newline at end of file + diff --git a/app/src/main/res/layout/fragment_images.xml b/app/src/main/res/layout/fragment_images.xml new file mode 100644 index 00000000..9191c9a4 --- /dev/null +++ b/app/src/main/res/layout/fragment_images.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_album.xml b/app/src/main/res/layout/item_album.xml index 1d3f8483..fa21bb27 100644 --- a/app/src/main/res/layout/item_album.xml +++ b/app/src/main/res/layout/item_album.xml @@ -6,6 +6,10 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/drawer_main.xml b/app/src/main/res/menu/drawer_main.xml index e9dc0acd..7a645f8b 100644 --- a/app/src/main/res/menu/drawer_main.xml +++ b/app/src/main/res/menu/drawer_main.xml @@ -11,29 +11,28 @@ android:icon="@drawable/ic_action_cloud_upload" android:title="@string/nav_upload" /> + + + + android:checkableBehavior="single"> - - - - \ No newline at end of file diff --git a/app/src/main/res/menu/manage_accounts.xml b/app/src/main/res/menu/manage_accounts.xml new file mode 100644 index 00000000..44caa360 --- /dev/null +++ b/app/src/main/res/menu/manage_accounts.xml @@ -0,0 +1,35 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-w480dp/dimens.xml b/app/src/main/res/values-w480dp/dimens.xml index 04c43fc0..f9eb3de1 100644 --- a/app/src/main/res/values-w480dp/dimens.xml +++ b/app/src/main/res/values-w480dp/dimens.xml @@ -1,6 +1,6 @@ - + - 400dp + 400dp \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index ccb83216..9ea2131f 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -9,4 +9,5 @@ 16dp 18sp + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bdb1903a..72b01461 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,14 +1,18 @@ Piwigo - @string/app_name + @string/app_name Login + Manage Accounts + About + Piwigo logo Albums Upload Settings About Add account + Remove account Manage accounts @@ -23,9 +27,20 @@ An account for this site already exists - %1$s@%2$s + %1$s@%2$s + Shortcut icon of the gallery (favicon) + Select an account for deletion first - + + %1$s +
version %2$s

+

distributed under GPL v3 (or later) license

+

For bugs and suggestions use the issue tacker

+

Source Code can be found on Github

]]> +
+ + 1 photo %1$d photos @@ -34,4 +49,5 @@ , 1 photo in sub-albums , %1$d photos in sub-albums + ManageAccountsActivity
diff --git a/app/src/test/java/org/piwigo/accounts/UserManagerTest.java b/app/src/test/java/org/piwigo/accounts/UserManagerTest.java index 6c3d22e6..cac250ce 100644 --- a/app/src/test/java/org/piwigo/accounts/UserManagerTest.java +++ b/app/src/test/java/org/piwigo/accounts/UserManagerTest.java @@ -67,7 +67,7 @@ public class UserManagerTest { when(resources.getString(R.string.account_type)).thenReturn(ACCOUNT_TYPE); when(resources.getString(eq(R.string.account_name), anyString(), anyString())).thenReturn(ACCOUNT_NAME); - + when(accountManager.getAccountsByType(ACCOUNT_TYPE)).thenReturn(new Account[] {}); userManager = new UserManager(accountManager, resources, preferencesRepository); } @@ -144,34 +144,40 @@ public class UserManagerTest { @Test public void getActiveAccount_withNoAccounts_returnsAbsent() { when(accountManager.getAccountsByType(ACCOUNT_TYPE)).thenReturn(new Account[0]); - assertThat(userManager.getActiveAccount().isPresent()).isFalse(); + assertThat(userManager.getActiveAccount().getValue() == null); } @Test public void getActiveAccount_withNoActiveAccount_returnsFirstAccount() { Account firstAccount = mock(Account.class); Account secondAccount = mock(Account.class); when(accountManager.getAccountsByType(ACCOUNT_TYPE)).thenReturn(new Account[] {firstAccount, secondAccount}); - when(preferencesRepository.getActiveAccount()).thenReturn(null); + when(preferencesRepository.getActiveAccountName()).thenReturn(null); + + userManager = new UserManager(accountManager, resources, preferencesRepository); - assertThat(userManager.getActiveAccount().get()).isEqualTo(firstAccount); + assertThat(userManager.getActiveAccount().getValue()).isEqualTo(firstAccount); } @Test public void getActiveAccount_withActiveAccount_returnsActiveAccount() { Account firstAccount = new Account("first_account", ACCOUNT_TYPE); Account secondAccount = new Account(ACCOUNT_NAME, ACCOUNT_TYPE); when(accountManager.getAccountsByType(ACCOUNT_TYPE)).thenReturn(new Account[] {firstAccount, secondAccount}); - when(preferencesRepository.getActiveAccount()).thenReturn(ACCOUNT_NAME); + when(preferencesRepository.getActiveAccountName()).thenReturn(ACCOUNT_NAME); - assertThat(userManager.getActiveAccount().get()).isEqualTo(secondAccount); + userManager = new UserManager(accountManager, resources, preferencesRepository); + + assertThat(userManager.getActiveAccount().getValue()).isEqualTo(secondAccount); } @Test public void getActiveAccount_withInvalidActiveAccount_returnsFirstAccount() { Account firstAccount = new Account("first_account", ACCOUNT_TYPE); Account secondAccount = new Account("second_account", ACCOUNT_TYPE); when(accountManager.getAccountsByType(ACCOUNT_TYPE)).thenReturn(new Account[] {firstAccount, secondAccount}); - when(preferencesRepository.getActiveAccount()).thenReturn(ACCOUNT_NAME); + when(preferencesRepository.getActiveAccountName()).thenReturn(ACCOUNT_NAME); + + userManager = new UserManager(accountManager, resources, preferencesRepository); - assertThat(userManager.getActiveAccount().get()).isEqualTo(firstAccount); + assertThat(userManager.getActiveAccount().getValue()).isEqualTo(firstAccount); } @Test public void getSiteUrl_callsAccountManager() { diff --git a/app/src/test/java/org/piwigo/ui/main/MainViewModelTest.java b/app/src/test/java/org/piwigo/ui/main/MainViewModelTest.java index b0733fe5..b8ff905d 100644 --- a/app/src/test/java/org/piwigo/ui/main/MainViewModelTest.java +++ b/app/src/test/java/org/piwigo/ui/main/MainViewModelTest.java @@ -20,6 +20,7 @@ import android.accounts.Account; import android.arch.core.executor.testing.InstantTaskExecutorRule; +import android.arch.lifecycle.MutableLiveData; import android.arch.lifecycle.Observer; import com.google.common.base.Optional; @@ -48,19 +49,15 @@ public class MainViewModelTest { @Before @SuppressWarnings("Guava") public void setup() { MockitoAnnotations.initMocks(this); - when(userManager.getActiveAccount()).thenReturn(Optional.of(account)); + MutableLiveData ml = new MutableLiveData<>(); + ml.setValue(account); + when(userManager.getActiveAccount()).thenReturn(ml); when(userManager.getUsername(account)).thenReturn("username"); when(userManager.getSiteUrl(account)).thenReturn("http://piwigo.org/demo"); viewModel = new MainViewModel(userManager); } - @Test public void constructor_getAccountInfoFromUserManager() { - verify(userManager).getActiveAccount(); - verify(userManager).getUsername(account); - verify(userManager).getSiteUrl(account); - } - @Test @SuppressWarnings("unchecked") public void getSelectedMenuItem_observerReceivesSelectedMenuItem() { int itemId = 1; Observer observer = (Observer) mock(Observer.class); diff --git a/build.gradle b/build.gradle index 6612f60a..991fb051 100644 --- a/build.gradle +++ b/build.gradle @@ -4,16 +4,17 @@ buildscript { mavenCentral() maven { url 'https://maven.google.com' } maven { url 'https://maven.fabric.io/public' } + google() } dependencies { - classpath 'com.android.tools.build:gradle:3.0.0' - classpath 'io.fabric.tools:gradle:1.24.3' + classpath 'com.android.tools.build:gradle:3.2.0' classpath 'com.fernandocejas.frodo:frodo-plugin:0.8.3' } } allprojects { repositories { + google() jcenter() mavenCentral() maven { url 'https://maven.google.com' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0cc6b858..a5783a94 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Sep 30 14:00:35 BST 2017 +#Sun Sep 30 20:57:42 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip diff --git a/settings.gradle b/settings.gradle index a977a130..3cc36ec2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,2 @@ -rootProject.name = 'Piwigo Android' +rootProject.name = 'Piwigo-Android' include ':app'