Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v253.241203.0 Add iOS in-app ratings & minor features&bugfixes #8075

Merged
merged 6 commits into from
Dec 3, 2024
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
4 changes: 2 additions & 2 deletions app-android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ android {
applicationId "de.tutao.tutanota"
minSdkVersion 26
targetSdkVersion 34
versionCode 396419
versionName "253.241129.0"
versionCode 396420
versionName "253.241203.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

// https://issuetracker.google.com/issues/181593646
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.io.IOException
import de.tutao.tutashared.SystemUtils


class AndroidMobileSystemFacade(
private val fileFacade: AndroidFileFacade,
Expand Down Expand Up @@ -168,4 +170,12 @@ class AndroidMobileSystemFacade(
override suspend fun openMailApp(query: String) {
Log.e(TAG, "Trying to open Tuta Mail from Tuta Mail")
}

override suspend fun getInstallationDate(): String {
return SystemUtils.getInstallationDate(activity.packageManager, activity.packageName)
}

override suspend fun requestInAppRating() {
TODO("Not yet implemented")
}
}
4 changes: 2 additions & 2 deletions app-android/calendar/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ android {
applicationId = "de.tutao.calendar"
minSdk = 26
targetSdk = 34
versionCode = 58
versionName = "253.241129.0"
versionCode = 59
versionName = "253.241203.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import androidx.core.content.ContextCompat.startActivity
import androidx.core.content.FileProvider
import androidx.fragment.app.FragmentActivity
import de.tutao.tutashared.CredentialAuthenticationException
import de.tutao.tutashared.SystemUtils
import de.tutao.tutashared.atLeastTiramisu
import de.tutao.tutashared.credentials.AuthenticationPrompt
import de.tutao.tutashared.data.AppDatabase
Expand Down Expand Up @@ -195,4 +196,12 @@ class AndroidMobileSystemFacade(
tryToLaunchStore()
}
}

override suspend fun getInstallationDate(): String {
return SystemUtils.getInstallationDate(activity.packageManager, activity.packageName)
}

override suspend fun requestInAppRating() {
TODO("Not yet implemented")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package de.tutao.tutashared

import android.content.pm.PackageManager
import java.io.File

sealed class SystemUtils {
companion object {
/**
* Returns the installation time of a package in UNIX Epoch time.
* Adapted from https://stackoverflow.com/a/2832419
*/
@JvmStatic
fun getInstallationDate(pm: PackageManager, packageName: String): String {
val appInfo = pm.getApplicationInfo(packageName, 0)
val appFile = appInfo.sourceDir
val installedTime = File(appFile).lastModified() //Epoch Time
return installedTime.toString()
}
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,14 @@ interface MobileSystemFacade {
suspend fun openMailApp(
query: String,
): Unit
/**
* Returns the date and time the app was installed as a string with milliseconds in UNIX epoch.
*/
suspend fun getInstallationDate(
): String
/**
* Requests the system in-app rating dialog to be displayed
*/
suspend fun requestInAppRating(
): Unit
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ class MobileSystemFacadeReceiveDispatcher(
)
return json.encodeToString(result)
}
"getInstallationDate" -> {
val result: String = this.facade.getInstallationDate(
)
return json.encodeToString(result)
}
"requestInAppRating" -> {
val result: Unit = this.facade.requestInAppRating(
)
return json.encodeToString(result)
}
else -> throw Error("unknown method for MobileSystemFacade: $method")
}
}
Expand Down
4 changes: 2 additions & 2 deletions app-ios/TutanotaNotificationExtension/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleShortVersionString</key>
<string>253.241129.0</string>
<string>253.241203.0</string>
<key>CFBundleVersion</key>
<string>253.241129.0</string>
<string>253.241203.0</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,14 @@ public protocol MobileSystemFacade {
func openMailApp(
_ query: String
) async throws -> Void
/**
* Returns the date and time the app was installed as a string with milliseconds in UNIX epoch.
*/
func getInstallationDate(
) async throws -> String
/**
* Requests the system in-app rating dialog to be displayed
*/
func requestInAppRating(
) async throws -> Void
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ public class MobileSystemFacadeReceiveDispatcher {
query
)
return "null"
case "getInstallationDate":
let result = try await self.facade.getInstallationDate(
)
return toJson(result)
case "requestInAppRating":
try await self.facade.requestInAppRating(
)
return "null"
default:
fatalError("licc messed up! \(method)")
}
Expand Down
4 changes: 2 additions & 2 deletions app-ios/calendar/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>253.241129.0</string>
<string>253.241203.0</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
Expand All @@ -33,7 +33,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>253.241129.0</string>
<string>253.241203.0</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
Expand Down
11 changes: 11 additions & 0 deletions app-ios/calendar/Sources/IosMobileSystemFacade.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Contacts
import Foundation
import StoreKit
import TutanotaSharedFramework

private let APP_LOCK_METHOD = "AppLockMethod"
Expand Down Expand Up @@ -93,4 +94,14 @@ class IosMobileSystemFacade: MobileSystemFacade {
DispatchQueue.main.async { UIApplication.shared.open(URL(string: "https://itunes.apple.com/us/app/id922429609")!) }
}
}
func getInstallationDate() async throws -> String {
let documentsURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let creationDate = try FileManager.default.attributesOfItem(atPath: documentsURL.path)[FileAttributeKey.creationDate] as! Date
let creationTimeInMilliseconds = Int(creationDate.timeIntervalSince1970 * 1000)
return String(creationTimeInMilliseconds)
}
func requestInAppRating() async throws {
let windowScene = await UIApplication.shared.connectedScenes.first as! UIWindowScene
await SKStoreReviewController.requestReview(in: windowScene)
}
}
4 changes: 2 additions & 2 deletions app-ios/tutanota/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>253.241129.0</string>
<string>253.241203.0</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
Expand All @@ -34,7 +34,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>253.241129.0</string>
<string>253.241203.0</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
Expand Down
14 changes: 14 additions & 0 deletions app-ios/tutanota/Sources/IosMobileSystemFacade.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Contacts
import Foundation
import StoreKit
import TutanotaSharedFramework

private let APP_LOCK_METHOD = "AppLockMethod"
Expand Down Expand Up @@ -78,4 +79,17 @@ class IosMobileSystemFacade: MobileSystemFacade {
}

func openMailApp(_ query: String) async throws { TUTSLog("Tried to open Mail App from Mail App") }
func getInstallationDate() async throws -> String {
let documentsURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let creationDate = try FileManager.default.attributesOfItem(atPath: documentsURL.path)[FileAttributeKey.creationDate] as! Date
let creationTimeInMilliseconds = Int(creationDate.timeIntervalSince1970 * 1000)
return String(creationTimeInMilliseconds)
}
func requestInAppRating() async throws {
// TODO: Replace `SKStoreReviewController.requestReview()` with StoreKit's/SwiftUI's `requestReview()`
// as `SKStoreReviewController.requestReview()` will be removed in iOS 19 (release roughly September 2025)
// This will require migrating from UIKit to Swift UI
let windowScene = await UIApplication.shared.connectedScenes.first as! UIWindowScene
await SKStoreReviewController.requestReview(in: windowScene)
}
}
3 changes: 2 additions & 1 deletion buildSrc/RollupConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const allowedImports = {
date: ["polyfill-helpers", "common-min", "common"],
"date-gui": ["polyfill-helpers", "common-min", "common", "boot", "gui-base", "main", "sharing", "date", "contacts"],
"mail-view": ["polyfill-helpers", "common-min", "common", "boot", "gui-base", "main"],
"mail-editor": ["polyfill-helpers", "common-min", "common", "boot", "gui-base", "main", "mail-view", "sanitizer", "sharing"],
"mail-editor": ["polyfill-helpers", "common-min", "common", "boot", "gui-base", "main", "mail-view", "sanitizer", "sharing", "date-gui"],
search: ["polyfill-helpers", "common-min", "common", "boot", "gui-base", "main", "mail-view", "calendar-view", "contacts", "date", "date-gui", "sharing"],
// ContactMergeView needs HtmlEditor even though ContactEditor doesn't?
contacts: ["polyfill-helpers", "common-min", "common", "boot", "gui-base", "main", "mail-view", "date", "date-gui", "mail-editor"],
Expand Down Expand Up @@ -174,6 +174,7 @@ export function getChunkName(moduleId, { getModuleInfo }) {
isIn("src/calendar-app/calendar/export") ||
isIn("src/common/misc/DateParser") ||
isIn("src/common/misc/CyberMondayUtils") ||
isIn("src/common/ratings") ||
isIn("src/calendar-app/calendar/model") ||
isIn("src/calendar-app/calendar/gui") ||
isIn("src/common/calendar/import")
Expand Down
10 changes: 10 additions & 0 deletions ipc-schema/facades/MobileSystemFacade.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@
}
],
"ret": "void"
},
"getInstallationDate": {
"doc": "Returns the date and time the app was installed as a string with milliseconds in UNIX epoch.",
"arg": [],
"ret": "string"
},
"requestInAppRating": {
"doc": "Requests the system in-app rating dialog to be displayed",
"arg": [],
"ret": "void"
}
}
}
Loading
Loading