Răsfoiți Sursa

Merge pull request #11545 from nextcloud/nmc/1915-in_app_review

Nmc/1915 in app review
Andy Scherzinger 2 ani în urmă
părinte
comite
cb08234df7

+ 1 - 0
app/build.gradle

@@ -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'
 

+ 36 - 0
app/src/generic/java/com/nextcloud/android/appReview/InAppReviewHelperImpl.kt

@@ -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) {
+    }
+}

+ 140 - 0
app/src/gplay/java/com/nextcloud/android/appReview/InAppReviewHelperImpl.kt

@@ -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
+    }
+}

+ 35 - 0
app/src/huawei/java/com/nextcloud/android/appReview/InAppReviewHelperImpl.kt

@@ -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) {
+    }
+}

+ 30 - 0
app/src/main/java/com/nextcloud/appReview/AppReviewShownModel.kt

@@ -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?
+)

+ 48 - 0
app/src/main/java/com/nextcloud/appReview/InAppReviewHelper.kt

@@ -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)
+}

+ 39 - 0
app/src/main/java/com/nextcloud/appReview/InAppReviewModule.kt

@@ -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)
+    }
+}

+ 2 - 0
app/src/main/java/com/nextcloud/client/di/AppComponent.java

@@ -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,

+ 7 - 0
app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java

@@ -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();
 }

+ 19 - 0
app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java

@@ -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);
+    }
 }

+ 79 - 0
app/src/main/java/com/nextcloud/utils/Extensions.kt

@@ -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))
+}

+ 7 - 0
app/src/main/java/com/owncloud/android/MainApp.java

@@ -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));
 

+ 6 - 0
app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -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");
     }

+ 2 - 5
app/src/main/java/com/owncloud/android/ui/asynctasks/GallerySearchTask.java

@@ -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;
         }
     }
-}
+}
+

+ 36 - 0
app/src/qa/java/com/nextcloud/android/appReview/InAppReviewHelperImpl.kt

@@ -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) {
+    }
+}

+ 34 - 0
app/src/test/java/com/nextcloud/android/utils/ExtensionsTest.kt

@@ -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")
+    }
+}

+ 36 - 0
app/src/versionDev/java/com/nextcloud/android/appReview/InAppReviewHelperImpl.kt

@@ -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) {
+    }
+}