mirror of https://github.com/nextcloud/android
Merge pull request #11545 from nextcloud/nmc/1915-in_app_review
Nmc/1915 in app review
This commit is contained in:
commit
cb08234df7
|
@ -366,6 +366,7 @@ dependencies {
|
|||
|
||||
// upon each update first test: new registration, receive push
|
||||
gplayImplementation "com.google.firebase:firebase-messaging:23.1.2"
|
||||
gplayImplementation 'com.google.android.play:review-ktx:2.0.0'
|
||||
|
||||
implementation 'com.github.nextcloud.android-common:ui:0.10.0'
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2023 Tobias Kaminsky
|
||||
* Copyright (C) 2023 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.android.appReview
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.nextcloud.appReview.InAppReviewHelper
|
||||
import com.nextcloud.client.preferences.AppPreferences
|
||||
|
||||
class InAppReviewHelperImpl(appPreferences: AppPreferences) :
|
||||
InAppReviewHelper {
|
||||
override fun resetAndIncrementAppRestartCounter() {
|
||||
}
|
||||
|
||||
override fun showInAppReview(activity: AppCompatActivity) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2023 Tobias Kaminsky
|
||||
* Copyright (C) 2023 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.android.appReview
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.gms.tasks.Task
|
||||
import com.google.android.play.core.review.ReviewException
|
||||
import com.google.android.play.core.review.ReviewInfo
|
||||
import com.google.android.play.core.review.ReviewManager
|
||||
import com.google.android.play.core.review.ReviewManagerFactory
|
||||
import com.google.android.play.core.review.model.ReviewErrorCode
|
||||
import com.nextcloud.appReview.AppReviewShownModel
|
||||
import com.nextcloud.appReview.InAppReviewHelper
|
||||
import com.nextcloud.client.preferences.AppPreferences
|
||||
import com.nextcloud.utils.getFormattedStringDate
|
||||
import com.nextcloud.utils.isCurrentYear
|
||||
import com.owncloud.android.lib.common.utils.Log_OC
|
||||
|
||||
// Reference: https://developer.android.com/guide/playcore/in-app-review
|
||||
/**
|
||||
* This class responsible to handle & manage in-app review related methods
|
||||
*/
|
||||
class InAppReviewHelperImpl(val appPreferences: AppPreferences) : InAppReviewHelper {
|
||||
|
||||
override fun resetAndIncrementAppRestartCounter() {
|
||||
val appReviewShownModel = appPreferences.inAppReviewData
|
||||
val currentTimeMills = System.currentTimeMillis()
|
||||
|
||||
if (appReviewShownModel != null) {
|
||||
if (currentTimeMills.isCurrentYear(appReviewShownModel.firstShowYear)) {
|
||||
appReviewShownModel.appRestartCount += 1
|
||||
appPreferences.setInAppReviewData(appReviewShownModel)
|
||||
} else {
|
||||
resetReviewShownModel()
|
||||
}
|
||||
} else {
|
||||
resetReviewShownModel()
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetReviewShownModel() {
|
||||
val appReviewShownModel = AppReviewShownModel(
|
||||
System.currentTimeMillis().getFormattedStringDate(YEAR_FORMAT),
|
||||
1,
|
||||
0,
|
||||
null
|
||||
)
|
||||
appPreferences.setInAppReviewData(appReviewShownModel)
|
||||
}
|
||||
|
||||
override fun showInAppReview(activity: AppCompatActivity) {
|
||||
val appReviewShownModel = appPreferences.inAppReviewData
|
||||
val currentTimeMills = System.currentTimeMillis()
|
||||
|
||||
appReviewShownModel?.let {
|
||||
if (it.appRestartCount >= MIN_APP_RESTARTS_REQ &&
|
||||
currentTimeMills.isCurrentYear(it.firstShowYear) &&
|
||||
it.reviewShownCount < MAX_DISPLAY_PER_YEAR
|
||||
) {
|
||||
doAppReview(activity)
|
||||
} else {
|
||||
Log_OC.d(
|
||||
TAG,
|
||||
"Yearly limit has been reached or minimum app restarts are not completed: $appReviewShownModel"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun doAppReview(activity: AppCompatActivity) {
|
||||
val manager = ReviewManagerFactory.create(activity)
|
||||
val request: Task<ReviewInfo> = manager.requestReviewFlow()
|
||||
request.addOnCompleteListener { task ->
|
||||
if (task.isSuccessful) {
|
||||
// We can get the ReviewInfo object
|
||||
val reviewInfo: ReviewInfo = task.result!!
|
||||
launchAppReviewFlow(manager, activity, reviewInfo)
|
||||
} else {
|
||||
// There was some problem, log or handle the error code.
|
||||
@ReviewErrorCode val reviewErrorCode = (task.exception as ReviewException).errorCode
|
||||
Log_OC.e(TAG, "Failed to get ReviewInfo: $reviewErrorCode")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchAppReviewFlow(
|
||||
manager: ReviewManager,
|
||||
activity: AppCompatActivity,
|
||||
reviewInfo: ReviewInfo
|
||||
) {
|
||||
val flow = manager.launchReviewFlow(activity, reviewInfo)
|
||||
flow.addOnCompleteListener { _ ->
|
||||
// The flow has finished. The API does not indicate whether the user
|
||||
// reviewed or not, or even whether the review dialog was shown. Thus, no
|
||||
// matter the result, we continue our app flow.
|
||||
// Scenarios in which the flow won't shown:
|
||||
// 1. Showing dialog to frequently
|
||||
// 2. If quota is reached can be checked in official documentation
|
||||
// 3. Flow won't be shown if user has already reviewed the app. User has to delete the review from play store to show the review dialog again
|
||||
// Link for more info: https://stackoverflow.com/a/63342266
|
||||
Log_OC.d(TAG, "App Review flow is completed")
|
||||
}
|
||||
|
||||
// on successful showing review dialog increment the count and capture the date
|
||||
val appReviewShownModel = appPreferences.inAppReviewData
|
||||
appReviewShownModel?.let {
|
||||
it.appRestartCount = 0
|
||||
it.reviewShownCount += 1
|
||||
it.lastReviewShownDate = System.currentTimeMillis().getFormattedStringDate(DATE_TIME_FORMAT)
|
||||
appPreferences.setInAppReviewData(it)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = InAppReviewHelperImpl::class.java.simpleName
|
||||
const val YEAR_FORMAT = "yyyy"
|
||||
const val DATE_TIME_FORMAT = "dd-MM-yyyy HH:mm:ss"
|
||||
const val MIN_APP_RESTARTS_REQ = 10 // minimum app restarts required to ask the review
|
||||
const val MAX_DISPLAY_PER_YEAR = 15 // maximum times to ask review in a year
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2023 Tobias Kaminsky
|
||||
* Copyright (C) 2023 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.android.appReview
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.nextcloud.appReview.InAppReviewHelper
|
||||
import com.nextcloud.client.preferences.AppPreferences
|
||||
|
||||
class InAppReviewHelperImpl(appPreferences: AppPreferences) :
|
||||
InAppReviewHelper {
|
||||
override fun resetAndIncrementAppRestartCounter() {
|
||||
}
|
||||
|
||||
override fun showInAppReview(activity: AppCompatActivity) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2023 Tobias Kaminsky
|
||||
* Copyright (C) 2023 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.appReview
|
||||
|
||||
data class AppReviewShownModel(
|
||||
var firstShowYear: String?,
|
||||
var appRestartCount: Int,
|
||||
var reviewShownCount: Int,
|
||||
var lastReviewShownDate: String?
|
||||
)
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2023 Tobias Kaminsky
|
||||
* Copyright (C) 2023 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.appReview
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
interface InAppReviewHelper {
|
||||
|
||||
/**
|
||||
* method to be called from Application onCreate() method to work properly
|
||||
* since we have to capture the app restarts Application is the best place to do that
|
||||
* this method will do the following:
|
||||
* 1. Reset the @see AppReviewModel with the current year (yyyy),
|
||||
* if the app is launched first time or if the year has changed.
|
||||
* 2. If the year is same then it will only increment the appRestartCount
|
||||
*/
|
||||
fun resetAndIncrementAppRestartCounter()
|
||||
|
||||
/**
|
||||
* method to be called from Activity onResume() method
|
||||
* this method will check the following conditions:
|
||||
* 1. if the minimum app restarts happened
|
||||
* 2. if the year is current
|
||||
* 3. if maximum review dialog is shown or not
|
||||
* once all the conditions satisfies it will trigger In-App Review manager to show the flow
|
||||
*/
|
||||
fun showInAppReview(activity: AppCompatActivity)
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2023 Tobias Kaminsky
|
||||
* Copyright (C) 2023 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.appReview
|
||||
|
||||
import com.nextcloud.android.appReview.InAppReviewHelperImpl
|
||||
import com.nextcloud.client.preferences.AppPreferences
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
class InAppReviewModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
internal fun providesInAppReviewHelper(appPreferences: AppPreferences): InAppReviewHelper {
|
||||
return InAppReviewHelperImpl(appPreferences)
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ package com.nextcloud.client.di;
|
|||
|
||||
import android.app.Application;
|
||||
|
||||
import com.nextcloud.appReview.InAppReviewModule;
|
||||
import com.nextcloud.client.appinfo.AppInfoModule;
|
||||
import com.nextcloud.client.database.DatabaseModule;
|
||||
import com.nextcloud.client.device.DeviceModule;
|
||||
|
@ -53,6 +54,7 @@ import dagger.android.support.AndroidSupportInjectionModule;
|
|||
ViewModelModule.class,
|
||||
JobsModule.class,
|
||||
IntegrationsModule.class,
|
||||
InAppReviewModule.class,
|
||||
ThemeModule.class,
|
||||
DatabaseModule.class,
|
||||
DispatcherModule.class,
|
||||
|
|
|
@ -20,9 +20,11 @@
|
|||
|
||||
package com.nextcloud.client.preferences;
|
||||
|
||||
import com.nextcloud.appReview.AppReviewShownModel;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
import com.owncloud.android.utils.FileSortOrder;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
|
@ -377,4 +379,9 @@ public interface AppPreferences {
|
|||
boolean isStoragePermissionRequested();
|
||||
|
||||
void setStoragePermissionRequested(boolean value);
|
||||
|
||||
void setInAppReviewData(@NonNull AppReviewShownModel appReviewShownModel);
|
||||
|
||||
@Nullable
|
||||
AppReviewShownModel getInAppReviewData();
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ import android.annotation.SuppressLint;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.nextcloud.appReview.AppReviewShownModel;
|
||||
import com.nextcloud.client.account.User;
|
||||
import com.nextcloud.client.account.UserAccountManager;
|
||||
import com.nextcloud.client.account.UserAccountManagerImpl;
|
||||
|
@ -39,6 +41,7 @@ import com.owncloud.android.utils.FileSortOrder;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
|
@ -92,11 +95,13 @@ public final class AppPreferencesImpl implements AppPreferences {
|
|||
private static final String PREF__PIN_BRUTE_FORCE_COUNT = "pin_brute_force_count";
|
||||
private static final String PREF__UID_PID = "uid_pid";
|
||||
|
||||
private static final String PREF__CALENDAR_AUTOMATIC_BACKUP = "calendar_automatic_backup";
|
||||
private static final String PREF__CALENDAR_LAST_BACKUP = "calendar_last_backup";
|
||||
|
||||
private static final String PREF__PDF_ZOOM_TIP_SHOWN = "pdf_zoom_tip_shown";
|
||||
|
||||
private static final String PREF__STORAGE_PERMISSION_REQUESTED = "storage_permission_requested";
|
||||
private static final String PREF__IN_APP_REVIEW_DATA = "in_app_review_data";
|
||||
|
||||
private final Context context;
|
||||
private final SharedPreferences preferences;
|
||||
|
@ -710,4 +715,18 @@ public final class AppPreferencesImpl implements AppPreferences {
|
|||
public int computeBruteForceDelay(int count) {
|
||||
return (int) Math.min(count / 3d, 10);
|
||||
}
|
||||
@Override
|
||||
public void setInAppReviewData(@NonNull AppReviewShownModel appReviewShownModel) {
|
||||
Gson gson = new Gson();
|
||||
String json = gson.toJson(appReviewShownModel);
|
||||
preferences.edit().putString(PREF__IN_APP_REVIEW_DATA, json).apply();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AppReviewShownModel getInAppReviewData() {
|
||||
Gson gson = new Gson();
|
||||
String json = preferences.getString(PREF__IN_APP_REVIEW_DATA, "");
|
||||
return gson.fromJson(json, AppReviewShownModel.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2023 Tobias Kaminsky
|
||||
* Copyright (C) 2023 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.utils
|
||||
|
||||
import android.text.Selection
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.Spanned
|
||||
import android.text.TextPaint
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.style.ClickableSpan
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
fun TextView.makeLinks(vararg links: Pair<String, View.OnClickListener>) {
|
||||
val spannableString = SpannableString(this.text)
|
||||
var startIndexOfLink = -1
|
||||
for (link in links) {
|
||||
val clickableSpan = object : ClickableSpan() {
|
||||
override fun updateDrawState(textPaint: TextPaint) {
|
||||
// use this to change the link color
|
||||
textPaint.color = textPaint.linkColor
|
||||
// toggle below value to enable/disable
|
||||
// the underline shown below the clickable text
|
||||
// textPaint.isUnderlineText = true
|
||||
}
|
||||
|
||||
override fun onClick(view: View) {
|
||||
Selection.setSelection((view as TextView).text as Spannable, 0)
|
||||
view.invalidate()
|
||||
link.second.onClick(view)
|
||||
}
|
||||
}
|
||||
startIndexOfLink = this.text.toString().indexOf(link.first, startIndexOfLink + 1)
|
||||
spannableString.setSpan(
|
||||
clickableSpan,
|
||||
startIndexOfLink,
|
||||
startIndexOfLink + link.first.length,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
}
|
||||
this.movementMethod =
|
||||
LinkMovementMethod.getInstance() // without LinkMovementMethod, link can not click
|
||||
this.setText(spannableString, TextView.BufferType.SPANNABLE)
|
||||
}
|
||||
|
||||
fun Long.isCurrentYear(yearToCompare: String?): Boolean {
|
||||
val simpleDateFormat = SimpleDateFormat("yyyy", Locale.getDefault())
|
||||
val currentYear = simpleDateFormat.format(Date(this))
|
||||
return currentYear == yearToCompare
|
||||
}
|
||||
|
||||
fun Long.getFormattedStringDate(format: String): String {
|
||||
val simpleDateFormat = SimpleDateFormat(format, Locale.getDefault())
|
||||
return simpleDateFormat.format(Date(this))
|
||||
}
|
|
@ -40,6 +40,7 @@ import android.os.StrictMode;
|
|||
import android.text.TextUtils;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.nextcloud.appReview.InAppReviewHelper;
|
||||
import com.nextcloud.client.account.User;
|
||||
import com.nextcloud.client.account.UserAccountManager;
|
||||
import com.nextcloud.client.appinfo.AppInfo;
|
||||
|
@ -177,6 +178,9 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
|
|||
@Inject
|
||||
MigrationsManager migrationsManager;
|
||||
|
||||
@Inject
|
||||
InAppReviewHelper inAppReviewHelper;
|
||||
|
||||
@Inject
|
||||
PassCodeManager passCodeManager;
|
||||
|
||||
|
@ -293,6 +297,9 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
|
|||
|
||||
registerActivityLifecycleCallbacks(new ActivityInjector());
|
||||
|
||||
//update the app restart count when app is launched by the user
|
||||
inAppReviewHelper.resetAndIncrementAppRestartCounter();
|
||||
|
||||
int startedMigrationsCount = migrationsManager.startMigration();
|
||||
logger.i(TAG, String.format(Locale.US, "Started %d migrations", startedMigrationsCount));
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ import android.view.WindowManager;
|
|||
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.nextcloud.appReview.InAppReviewHelper;
|
||||
import com.nextcloud.client.account.User;
|
||||
import com.nextcloud.client.appinfo.AppInfo;
|
||||
import com.nextcloud.client.core.AsyncRunner;
|
||||
|
@ -241,6 +242,9 @@ public class FileDisplayActivity extends FileActivity
|
|||
@Inject
|
||||
ConnectivityService connectivityService;
|
||||
|
||||
@Inject
|
||||
InAppReviewHelper inAppReviewHelper;
|
||||
|
||||
@Inject
|
||||
FastScrollUtils fastScrollUtils;
|
||||
@Inject AsyncRunner asyncRunner;
|
||||
|
@ -1173,6 +1177,8 @@ public class FileDisplayActivity extends FileActivity
|
|||
if (ocFileListFragment instanceof GalleryFragment) {
|
||||
updateActionBarTitleAndHomeButtonByString(getString(R.string.drawer_item_gallery));
|
||||
}
|
||||
//show in-app review dialog to user
|
||||
inAppReviewHelper.showInAppReview(this);
|
||||
|
||||
Log_OC.v(TAG, "onResume() end");
|
||||
}
|
||||
|
|
|
@ -34,20 +34,16 @@ import com.owncloud.android.lib.resources.files.model.RemoteFile;
|
|||
import com.owncloud.android.lib.resources.status.OCCapability;
|
||||
import com.owncloud.android.operations.RefreshFolderOperation;
|
||||
import com.owncloud.android.ui.fragment.GalleryFragment;
|
||||
import com.owncloud.android.ui.fragment.SearchType;
|
||||
import com.owncloud.android.utils.FileStorageUtils;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
public class GallerySearchTask extends AsyncTask<Void, Void, GallerySearchTask.Result> {
|
||||
|
||||
private final User user;
|
||||
|
@ -220,4 +216,5 @@ public class GallerySearchTask extends AsyncTask<Void, Void, GallerySearchTask.R
|
|||
this.lastTimestamp = lastTimestamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2023 Tobias Kaminsky
|
||||
* Copyright (C) 2023 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.android.appReview
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.nextcloud.appReview.InAppReviewHelper
|
||||
import com.nextcloud.client.preferences.AppPreferences
|
||||
|
||||
class InAppReviewHelperImpl(appPreferences: AppPreferences) :
|
||||
InAppReviewHelper {
|
||||
override fun resetAndIncrementAppRestartCounter() {
|
||||
}
|
||||
|
||||
override fun showInAppReview(activity: AppCompatActivity) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.nextcloud.android.utils
|
||||
|
||||
import com.nextcloud.utils.getFormattedStringDate
|
||||
import com.nextcloud.utils.isCurrentYear
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class ExtensionsTest {
|
||||
|
||||
@Test
|
||||
fun isCurrentYear_checkForAllConditions() {
|
||||
assertFalse(System.currentTimeMillis().isCurrentYear(""))
|
||||
assertFalse(System.currentTimeMillis().isCurrentYear(null))
|
||||
|
||||
val year2022TimeMills = 1652892268000L
|
||||
assertTrue(year2022TimeMills.isCurrentYear("2022"))
|
||||
|
||||
assertFalse(year2022TimeMills.isCurrentYear("2021"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getFormattedStringDate_checkForAllConditions() {
|
||||
val year2022TimeMills = 1652892268000L
|
||||
val actualYearValue = year2022TimeMills.getFormattedStringDate("yyyy")
|
||||
assertTrue(actualYearValue == "2022")
|
||||
assertFalse(actualYearValue == "2021")
|
||||
assertFalse(actualYearValue == "")
|
||||
|
||||
val actualYearNewValue = year2022TimeMills.getFormattedStringDate("")
|
||||
assertTrue(actualYearNewValue == "")
|
||||
assertFalse(actualYearNewValue == "2022")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2023 Tobias Kaminsky
|
||||
* Copyright (C) 2023 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.android.appReview
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.nextcloud.appReview.InAppReviewHelper
|
||||
import com.nextcloud.client.preferences.AppPreferences
|
||||
|
||||
class InAppReviewHelperImpl(appPreferences: AppPreferences) :
|
||||
InAppReviewHelper {
|
||||
override fun resetAndIncrementAppRestartCounter() {
|
||||
}
|
||||
|
||||
override fun showInAppReview(activity: AppCompatActivity) {
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue