Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
flavorDimensions += "version"
productFlavors {
freeVersion {
dimension "version"
applicationId "com.phpbg.easysync.trial"
resValue "string", "flavored_app_name", "Easy Sync Trial"

}
paidVersion {
dimension "version"
resValue "string", "flavored_app_name", "Easy Sync"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:label="@string/flavored_app_name"
android:localeConfig="@xml/locales_config"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
Expand Down
25 changes: 25 additions & 0 deletions app/src/main/java/com/phpbg/easysync/MyApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,36 @@
package com.phpbg.easysync

import android.app.Application
import android.content.Context
import android.os.StrictMode
import java.lang.System.currentTimeMillis
import kotlin.math.floor
import kotlin.math.max

const val TRIAL_DURATION_DAYS = 30

class MyApp : Application() {
init {
if (BuildConfig.DEBUG)
StrictMode.enableDefaults()
}

companion object {
fun isTrial(): Boolean {
@Suppress("KotlinConstantConditions")
return (BuildConfig.FLAVOR == "freeVersion")
}

fun getTrialRemainingDays(context: Context): Int {
val installed = context
.packageManager
.getPackageInfo(context.packageName, 0).firstInstallTime
val now = currentTimeMillis()
return max(0, TRIAL_DURATION_DAYS- floor((now-installed)/(24*3600*1000).toFloat()).toInt())
}

fun isTrialExpired(context: Context): Boolean {
return isTrial() && getTrialRemainingDays(context) == 0
}
}
}
3 changes: 2 additions & 1 deletion app/src/main/java/com/phpbg/easysync/Notifications.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@
package com.phpbg.easysync

enum class Notifications(val id: Int) {
MISSING_PERMISSIONS(1)
MISSING_PERMISSIONS(1),
TRIAL_EXPIRED(2)
}
52 changes: 50 additions & 2 deletions app/src/main/java/com/phpbg/easysync/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

package com.phpbg.easysync.ui

import android.content.ActivityNotFoundException
import android.content.Intent
import android.content.res.Configuration
import android.net.Uri
Expand All @@ -47,6 +48,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Cancel
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Help
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.Schedule
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Warning
Expand All @@ -58,15 +60,18 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.IntState
import androidx.compose.runtime.State
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
Expand Down Expand Up @@ -126,7 +131,9 @@ class MainActivity : ComponentActivity() {
showDavStatus = viewModel.showDavStatus,
isDavLoading = viewModel.isDavLoading,
isDavConnected = viewModel.isDavConnected,
hasOptionalPermissions = hasOptionalPermissions
isTrial = viewModel.isTrial,
hasOptionalPermissions = hasOptionalPermissions,
trialRemainingDays = viewModel.trialRemainingDays
)
}
}
Expand All @@ -148,7 +155,9 @@ private fun Main(
showDavStatus: State<Boolean>,
isDavLoading: State<Boolean>,
isDavConnected: State<Boolean>,
isTrial: State<Boolean>,
hasOptionalPermissions: State<Boolean>,
trialRemainingDays: IntState,
) {
val mContext = LocalContext.current
val syncEnabled = workerState == null || workerState != WorkInfo.State.RUNNING
Expand All @@ -163,7 +172,7 @@ private fun Main(
.padding(16.dp)
.verticalScroll(rememberScrollState())
) {
Title(text = stringResource(R.string.app_name))
Title(text = stringResource(R.string.flavored_app_name))

val davSettingsHandler = fun(_: Int) {
val myIntent = Intent(mContext, DavSettingsActivity::class.java)
Expand Down Expand Up @@ -247,6 +256,23 @@ private fun Main(
},
)

if (isTrial.value) {
val msg = if (trialRemainingDays.intValue == 0) stringResource(R.string.home_trial_over) else pluralStringResource(R.plurals.home_trial_days_left, trialRemainingDays.intValue, trialRemainingDays.intValue)
StatusTitleClickable(
title = null,
actionTitle = msg,
statusColor = Color.Gray,
statusIcon = Icons.Default.Info,
clickHandler = {
try {
mContext.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.phpbg.easysync")))
} catch (e: ActivityNotFoundException) {
mContext.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=com.phpbg.easysync")))
}
},
)
}

Spacer(modifier = Modifier.height(16.dp))

val syncedPercent = if (localCount > 0 && syncedCount >= 0) {
Expand Down Expand Up @@ -354,7 +380,29 @@ private fun MainPreview() {
showDavStatus = remember { mutableStateOf(true) },
isDavLoading = remember { mutableStateOf(false) },
isDavConnected = remember { mutableStateOf(true) },
isTrial = remember { mutableStateOf(false) },
hasOptionalPermissions = remember { mutableStateOf(false) },
trialRemainingDays = remember { mutableIntStateOf(0) }
)
}
}

@Preview(name = "Trial Mode", showBackground = false)
@Composable
private fun MainPreviewTrial() {
MyApplicationTheme {
Main(
fullSyncNowHandler = {},
workerState = WorkInfo.State.RUNNING,
syncedCount = 10000,
localCount = 100,
jobCount = -1,
showDavStatus = remember { mutableStateOf(true) },
isDavLoading = remember { mutableStateOf(false) },
isDavConnected = remember { mutableStateOf(true) },
isTrial = remember { mutableStateOf(true) },
hasOptionalPermissions = remember { mutableStateOf(false) },
trialRemainingDays = remember { mutableIntStateOf(28) }
)
}
}
8 changes: 8 additions & 0 deletions app/src/main/java/com/phpbg/easysync/ui/MainViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ import android.os.Handler
import android.os.Looper
import android.provider.MediaStore
import android.util.Log
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.map
import androidx.lifecycle.viewModelScope
import androidx.work.WorkInfo
import com.phpbg.easysync.MyApp
import com.phpbg.easysync.dav.CollectionPath
import com.phpbg.easysync.dav.MisconfigurationException
import com.phpbg.easysync.dav.WebDavService
Expand Down Expand Up @@ -85,6 +87,9 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
val isDavConnected = mutableStateOf(false)
val isDavLoading = mutableStateOf(false)

val isTrial = mutableStateOf(false)
val trialRemainingDays = mutableIntStateOf(0)

val workInfosList = FullSyncWorker.getLiveData(this.getApplication()).map { x ->
if (x.isEmpty()) {
return@map null
Expand Down Expand Up @@ -120,6 +125,9 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
viewModelScope.launch {
loadDav()
}

isTrial.value = MyApp.isTrial()
trialRemainingDays.intValue = MyApp.getTrialRemainingDays(getApplication())
}

private fun loadImages() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import com.phpbg.easysync.MyApp
import com.phpbg.easysync.mediastore.MediaStoreService
import com.phpbg.easysync.mediastore.URIS

Expand All @@ -45,6 +46,9 @@ private const val TAG = "FileDetectWorker"
class FileDetectWorker(appContext: Context, workerParams: WorkerParameters) :
CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
if (MyApp.isTrialExpired(this.applicationContext)) {
return Result.success()
}
try {
_doWork()
} catch (e: Exception) {
Expand Down
22 changes: 19 additions & 3 deletions app/src/main/java/com/phpbg/easysync/worker/FullSyncWorker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import com.phpbg.easysync.MyApp.Companion.isTrialExpired
import com.phpbg.easysync.Notifications
import com.phpbg.easysync.R
import com.phpbg.easysync.dav.MisconfigurationException
Expand All @@ -57,6 +58,10 @@ class FullSyncWorker(context: Context, parameters: WorkerParameters) :
NotificationManager

override suspend fun doWork(): Result {
if (isTrialExpired(this.applicationContext)) {
showTrialExpiredNotification()
return Result.success()
}
val immediate = inputData.getBoolean(IMMEDIATE_KEY, false)
return try {
val syncService = SyncService.getInstance(this.applicationContext)
Expand All @@ -83,17 +88,28 @@ class FullSyncWorker(context: Context, parameters: WorkerParameters) :
}
}

private fun showTrialExpiredNotification() {
val title = applicationContext.getString(R.string.notification_trial_over_title)
val text = applicationContext.getString(R.string.notification_trial_over_text)
val notificationId = Notifications.TRIAL_EXPIRED
showNotification(title, text, notificationId)
}

private fun showMissingPermissionsNotification() {
val id = applicationContext.getString(R.string.notification_channel_id)
val title = applicationContext.getString(R.string.notification_missing_permissions_title)
val text = applicationContext.getString(R.string.notification_missing_permissions_text)
val notificationId = Notifications.MISSING_PERMISSIONS
showNotification(title, text, notificationId)
}

private fun showNotification(title: String, text: String, notificationId: Notifications) {
val id = applicationContext.getString(R.string.notification_channel_id)

val intent = Intent(this.applicationContext, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent = PendingIntent.getActivity(this.applicationContext, 0, intent, PendingIntent.FLAG_IMMUTABLE)


createChannel(id)
val notification = Notification.Builder(applicationContext, id)
.setContentTitle(title)
Expand All @@ -105,7 +121,7 @@ class FullSyncWorker(context: Context, parameters: WorkerParameters) :
.setContentIntent(pendingIntent)
.build()

notificationManager.notify(Notifications.MISSING_PERMISSIONS.id, notification)
notificationManager.notify(notificationId.id, notification)
}

private fun createChannel(channelId: String) {
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<resources>
<string name="notification_missing_permissions_text">Bitte erteilen Sie Berechtigungen, um die Synchronisation zu ermöglichen</string>
<string name="notification_missing_permissions_title">Synchronisation fehlgeschlagen</string>
<string name="notification_trial_over_title">Synchronisation gestoppt</string>
<string name="notification_trial_over_text">Bitte kaufen Sie die Vollversion</string>
<string name="dav_settings_activity_title">Einstellungen</string>
<string name="dav_settings_hide_password">Passwort ausblenden</string>
<string name="dav_settings_password">Passwort</string>
Expand All @@ -25,6 +27,11 @@
<string name="home_permissions_action_fix">Beheben…</string>
<string name="home_sync_running">läuft</string>
<string name="home_sync_syncing">synchronisiert</string>
<string name="home_trial_over">Die Testversion ist abgelaufen, bitte kaufen Sie die Vollversion</string>
<plurals name="home_trial_days_left">
<item quantity="one">Testversion: %d Tag verbleibend</item>
<item quantity="other">Testversion: %d Tage verbleibend</item>
</plurals>
<string name="permissions_activity_title">Berechtigungen</string>
<string name="permissions_files_text">Um Ihre Dateien zu synchronisieren, benötigen wir vollen Zugriff auf Ihre Dateien. Gehen Sie zu den Einstellungen, um die Berechtigung zu aktivieren</string>
<string name="permissions_files_button">Dateieinstellungen</string>
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<resources>
<string name="notification_missing_permissions_text">Veuillez accorder les permissions pour permettre la synchronisation</string>
<string name="notification_missing_permissions_title">Synchronisation KO</string>
<string name="notification_trial_over_title">Synchronisation interrompue</string>
<string name="notification_trial_over_text">Veuillez acheter la version complète</string>
<string name="dav_settings_activity_title">Paramètres</string>
<string name="dav_settings_username">Nom d\'utilisateur</string>
<string name="dav_settings_password">Mot de passe</string>
Expand All @@ -23,6 +25,11 @@
<string name="home_permissions_action_fix">Corriger…</string>
<string name="home_sync_running">attente</string>
<string name="home_sync_syncing">en cours</string>
<string name="home_trial_over">La période d\'essai est terminée, veuillez acheter la version complète</string>
<plurals name="home_trial_days_left">
<item quantity="one">Essai gratuit : %d jour restant</item>
<item quantity="other">Essai gratuit : %d jours restants</item>
</plurals>
<string name="dav_settings_title">Paramètres DAV</string>
<string name="dav_settings_url_insecure">Cette URL n\'est pas sécurisée. Vos données pourront être interceptées. Vous devriez utiliser HTTPS.</string>
<string name="permissions_activity_title">Permissions</string>
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/res/values-ru/strings.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<resources>
<string name="notification_missing_permissions_text">Пожалуйста предоставьте разрешения для синхронизации.</string>
<string name="notification_missing_permissions_title">Синхронизация неуспешна</string>
<string name="notification_trial_over_title">Синхронизация остановлена</string>
<string name="notification_trial_over_text">Пожалуйста, купите полную версию, чтобы разрешить синхронизацию</string>
<string name="dav_settings_activity_title">Настройки</string>
<string name="dav_settings_hide_password">Скрыть пароль</string>
<string name="dav_settings_password">Пароль</string>
Expand All @@ -24,6 +26,13 @@
<string name="home_permissions_action_fix">Исправить…</string>
<string name="home_sync_running">выполняется</string>
<string name="home_sync_syncing">синхронизация</string>
<string name="home_trial_over">Испытательный период завершен, пожалуйста, купите полную версию</string>
<plurals name="home_trial_days_left">
<item quantity="one">Испытание: %d день остался</item>
<item quantity="few">Испытание: %d дня осталось</item>
<item quantity="many">Испытание: %d дней осталось</item>
<item quantity="other">Испытание: %d дней осталось</item>
</plurals>
<string name="permissions_activity_title">Разрешения</string>
<string name="permissions_files_text">Для синхронизации ваших файлов нам необходим полный доступ к вашим файлам. Зайдите в настройки, чтобы включить разрешение</string>
<string name="permissions_files_button">Настройки файлов</string>
Expand Down
8 changes: 7 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<resources>
<string name="app_name" translatable="false">Easy Sync</string>
<string name="notification_channel_id" translatable="false">1001</string>
<string name="notification_missing_permissions_text">Please grant permissions to allow synchronization</string>
<string name="notification_missing_permissions_title">Synchronization failed</string>
<string name="notification_trial_over_title">Synchronization stopped</string>
<string name="notification_trial_over_text">Please buy the full version to allow synchronization</string>
<string name="dav_settings_activity_title">Settings</string>
<string name="dav_settings_hide_password">Hide password</string>
<string name="dav_settings_password">Password</string>
Expand All @@ -26,6 +27,11 @@
<string name="home_permissions_action_fix">Fix…</string>
<string name="home_sync_running">running</string>
<string name="home_sync_syncing">syncing</string>
<string name="home_trial_over">Trial is over, please buy the full version</string>
<plurals name="home_trial_days_left">
<item quantity="one">Trial: %d day remaining</item>
<item quantity="other">Trial: %d days remaining</item>
</plurals>
<string name="permissions_activity_title">Permissions</string>
<string name="permissions_files_text">In order to synchronize your files we need full access to your files. Go to settings to enable the permission</string>
<string name="permissions_files_button">File settings</string>
Expand Down