Skip to content

Commit 2a60650

Browse files
jbsessionThomasSessiondependabot[bot]SessionHero01Bilb
authored
Permissions - Improvement and manage allowed media [SES-4564] (#1544)
* ADded data for non originating subscriptions * Tweaking state to remove labels from VM state to help with all the screen variations we have * WIP * BAse Non Originating screen * Fixing broken strings * Non originating UI * Non originating UI * Bump org.mockito:mockito-core from 5.19.0 to 5.20.0 (#1533) * Initial implementation of google play billing (#1503) * [Automated] Update translations from Crowdin * Bump io.github.webrtc-sdk:android from 137.7151.01 to 137.7151.04 (#1513) Bumps [io.github.webrtc-sdk:android](https://github.com/webrtc-sdk/android) from 137.7151.01 to 137.7151.04. - [Release notes](https://github.com/webrtc-sdk/android/releases) - [Changelog](https://github.com/webrtc-sdk/android/blob/v137.7151.04/CHANGES.md) - [Commits](webrtc-sdk/android@v137.7151.01...v137.7151.04) --- updated-dependencies: - dependency-name: io.github.webrtc-sdk:android dependency-version: 137.7151.04 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: SessionHero01 <[email protected]> * Bump cameraCamera2Version from 1.4.2 to 1.5.0 (#1514) Bumps `cameraCamera2Version` from 1.4.2 to 1.5.0. Updates `androidx.camera:camera-camera2` from 1.4.2 to 1.5.0 Updates `androidx.camera:camera-lifecycle` from 1.4.2 to 1.5.0 Updates `androidx.camera:camera-view` from 1.4.2 to 1.5.0 --- updated-dependencies: - dependency-name: androidx.camera:camera-camera2 dependency-version: 1.5.0 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: androidx.camera:camera-lifecycle dependency-version: 1.5.0 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: androidx.camera:camera-view dependency-version: 1.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: SessionHero01 <[email protected]> * Bump androidxHiltVersion from 1.2.0 to 1.3.0 (#1532) Bumps `androidxHiltVersion` from 1.2.0 to 1.3.0. Updates `androidx.hilt:hilt-navigation-compose` from 1.2.0 to 1.3.0 Updates `androidx.hilt:hilt-work` from 1.2.0 to 1.3.0 Updates `androidx.hilt:hilt-compiler` from 1.2.0 to 1.3.0 --- updated-dependencies: - dependency-name: androidx.hilt:hilt-navigation-compose dependency-version: 1.3.0 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: androidx.hilt:hilt-work dependency-version: 1.3.0 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: androidx.hilt:hilt-compiler dependency-version: 1.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: SessionHero01 <[email protected]> * [Automated] Update translations from Crowdin * Bump com.google.gms.google-services from 4.4.2 to 4.4.3 (#1534) Bumps com.google.gms.google-services from 4.4.2 to 4.4.3. --- updated-dependencies: - dependency-name: com.google.gms.google-services dependency-version: 4.4.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: SessionHero01 <[email protected]> * Temp string replacement * Updated full perission check, added function for adding more media * [Automated] Update translations from Crowdin * Added plus menu to add to allowed media * udpated condition * removed deprecated method * SES-4569 : 'Follow Setting' button doesn't follow theming (#1531) * Use textColorPrimary for light theme for Follow Setting button/text * Added to accentText to themes * Added accentText for the test theme --------- Co-authored-by: ThomasSession <[email protected]> * Fixed menu button redrawing --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: ThomasSession <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: SessionHero01 <[email protected]> Co-authored-by: ThomasSession <[email protected]> Co-authored-by: Bilb <[email protected]>
1 parent 9105cdc commit 2a60650

File tree

40 files changed

+874
-200
lines changed

40 files changed

+874
-200
lines changed

app/build.gradle.kts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ val getGitHash = providers
4848

4949
val firebaseEnabledVariants = listOf("play", "fdroid")
5050
val nonPlayVariants = listOf("fdroid", "website") + if (huaweiEnabled) listOf("huawei") else emptyList()
51-
val nonDebugBuildTypes = listOf("release", "qa", "automaticQa")
51+
val nonDebugBuildTypes = listOf("release", "releaseWithDebugMenu", "qa", "automaticQa")
5252

5353
fun VariantDimension.devNetDefaultOn(defaultOn: Boolean) {
5454
val fqEnumClass = "org.session.libsession.utilities.Environment"
@@ -169,6 +169,12 @@ android {
169169
setAuthorityPostfix("")
170170
}
171171

172+
create("releaseWithDebugMenu") {
173+
initWith(getByName("release"))
174+
175+
matchingFallbacks += "release"
176+
}
177+
172178
create("qa") {
173179
initWith(getByName("release"))
174180

@@ -473,6 +479,9 @@ dependencies {
473479

474480
implementation(libs.androidx.biometric)
475481

482+
playImplementation(libs.android.billing)
483+
playImplementation(libs.android.billing.ktx)
484+
476485
debugImplementation(libs.sqlite.web.viewer)
477486
}
478487

app/src/firebaseCommon/kotlin/org/thoughtcrime/securesms/notifications/FirebasePushService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class FirebasePushService : FirebaseMessagingService() {
2424
}
2525

2626
override fun onMessageReceived(message: RemoteMessage) {
27-
Log.d(TAG, "Received a firebase push notification: $message - Priority received: ${message.priority} (Priority expected: ${message.originalPriority}) - Sent time: ${dateUtils.getLocaleFormattedDate(message.sentTime, "HH:mm:ss.SSS")}")
27+
Log.d(TAG, "Received a firebase push notification: $message - Priority received: ${message.priority} (Priority expected: ${message.originalPriority}) - Sent time: ${DateUtils.getLocaleFormattedDate(message.sentTime, "HH:mm:ss.SSS")}")
2828
pushReceiver.onPushDataReceived(message.data)
2929
}
3030
}

app/src/main/java/org/session/libsession/utilities/StringSubKeys.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,12 @@ object StringSubstitutionConstants {
5050
const val APP_PRO_KEY: StringSubKey = "app_pro"
5151
const val PRO_KEY: StringSubKey = "pro"
5252
const val CURRENT_PLAN_KEY: StringSubKey = "current_plan"
53-
const val SELECTED_PLAN_KEY: StringSubKey = "selected_plan"
53+
const val SELECTED_PLAN_KEY: StringSubKey = "selected_plan"
5454
const val PLATFORM_STORE_KEY: StringSubKey = "platform_store"
5555
const val PLATFORM_ACCOUNT_KEY: StringSubKey = "platform_account"
5656
const val MONTHLY_PRICE_KEY: StringSubKey = "monthly_price"
5757
const val PRICE_KEY: StringSubKey = "price"
5858
const val PERCENT_KEY: StringSubKey = "percent"
59-
59+
const val DEVICE_TYPE_KEY: StringSubKey = "device_type"
6060
const val SESSION_FOUNDATION_KEY: StringSubKey = "session_foundation"
6161
}

app/src/main/java/org/thoughtcrime/securesms/conversation/v2/settings/notification/NotificationSettingsViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ class NotificationSettingsViewModel @AssistedInject constructor(
195195
}
196196

197197
private fun formatTime(timestamp: Long): String{
198-
return dateUtils.formatTime(timestamp, "HH:mm dd/MM/yy")
198+
return DateUtils.formatTime(timestamp, "HH:mm dd/MM/yy")
199199
}
200200

201201
private fun shouldEnableSetButton(): Boolean {

app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/AttachmentManager.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import android.content.ActivityNotFoundException;
2525
import android.content.Context;
2626
import android.content.Intent;
27+
import android.content.pm.PackageManager;
2728
import android.database.Cursor;
2829
import android.net.Uri;
2930
import android.os.AsyncTask;
@@ -34,6 +35,9 @@
3435
import android.widget.Toast;
3536
import androidx.annotation.NonNull;
3637
import androidx.annotation.Nullable;
38+
import androidx.core.app.ActivityCompat;
39+
import androidx.core.content.ContextCompat;
40+
3741
import com.bumptech.glide.RequestManager;
3842
import com.squareup.phrase.Phrase;
3943
import java.io.IOException;
@@ -266,6 +270,7 @@ public static void selectDocument(Activity activity, int requestCode) {
266270
}
267271

268272
public static void selectGallery(Activity activity, int requestCode, @NonNull Address recipient, @NonNull String body) {
273+
269274
Context c = activity.getApplicationContext();
270275
Runnable openGallery = () ->
271276
activity.startActivityForResult(
@@ -275,8 +280,14 @@ public static void selectGallery(Activity activity, int requestCode, @NonNull Ad
275280

276281
// Android 14+ : if we already have partial OR full access, skip asking
277282
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
278-
if (Permissions.hasAll(activity, Manifest.permission.READ_MEDIA_IMAGES) ||
279-
Permissions.hasAll(activity, Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)) {
283+
boolean hasAllPermissions = Permissions.hasAll(activity,
284+
Manifest.permission.READ_MEDIA_IMAGES,
285+
Manifest.permission.READ_MEDIA_VIDEO);
286+
287+
boolean hasPartial = Permissions.hasAll(activity,
288+
Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED);
289+
290+
if (hasAllPermissions || hasPartial) {
280291
openGallery.run();
281292
return;
282293
}
@@ -338,6 +349,32 @@ public static void selectGallery(Activity activity, int requestCode, @NonNull Ad
338349
.execute();
339350
}
340351

352+
public static boolean hasFullAccess(Activity activity) {
353+
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
354+
Permissions.hasAll(activity,
355+
Manifest.permission.READ_MEDIA_IMAGES,
356+
Manifest.permission.READ_MEDIA_VIDEO);
357+
}
358+
359+
public static void managePhotoAccess(@NonNull Activity activity, @Nullable Runnable onAnyResult) {
360+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { // API 34+
361+
Permissions.with(activity)
362+
.request(
363+
Manifest.permission.READ_MEDIA_IMAGES,
364+
Manifest.permission.READ_MEDIA_VIDEO,
365+
Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
366+
).onAnyResult(() -> {
367+
if (onAnyResult != null) onAnyResult.run();
368+
})
369+
.execute();
370+
} else {
371+
// older Android: no partial selector, send to App settings
372+
Intent i = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
373+
.setData(Uri.fromParts("package", activity.getPackageName(), null));
374+
activity.startActivity(i);
375+
}
376+
}
377+
341378
public static void selectAudio(Activity activity, int requestCode) {
342379
selectMediaType(activity, "audio/*", null, requestCode);
343380
}

app/src/main/java/org/thoughtcrime/securesms/debugmenu/DebugMenu.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,20 @@ fun DebugMenu(
235235
"Session Pro",
236236
verticalArrangement = Arrangement.spacedBy(0.dp)) {
237237
Spacer(modifier = Modifier.height(LocalDimensions.current.xsSpacing))
238+
239+
Text(text = "Purchase a plan")
240+
Spacer(modifier = Modifier.height(LocalDimensions.current.smallSpacing))
241+
242+
DropDown(
243+
selected = null,
244+
modifier = modifier,
245+
values = uiState.debugProPlans,
246+
onValueSelected = { sendCommand(DebugMenuViewModel.Commands.PurchaseDebugPlan(it)) },
247+
labeler = { it?.label ?: "Select a plan to buy" }
248+
)
249+
250+
Spacer(modifier = Modifier.height(LocalDimensions.current.xsSpacing))
251+
238252
DebugSwitchRow(
239253
text = "Set current user as Pro",
240254
checked = uiState.forceCurrentUserAsPro,
@@ -735,7 +749,8 @@ fun PreviewDebugMenu() {
735749
messageProFeature = setOf(ProStatusManager.MessageProFeature.AnimatedAvatar),
736750
dbInspectorState = DebugMenuViewModel.DatabaseInspectorState.STARTED,
737751
debugSubscriptionStatuses = setOf(DebugMenuViewModel.DebugSubscriptionStatus.AUTO_GOOGLE),
738-
selectedDebugSubscriptionStatus = DebugMenuViewModel.DebugSubscriptionStatus.AUTO_GOOGLE
752+
selectedDebugSubscriptionStatus = DebugMenuViewModel.DebugSubscriptionStatus.AUTO_GOOGLE,
753+
debugProPlans = emptyList(),
739754
),
740755
sendCommand = {},
741756
onClose = {}

app/src/main/java/org/thoughtcrime/securesms/debugmenu/DebugMenuViewModel.kt

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import org.thoughtcrime.securesms.database.RecipientSettingsDatabase
3838
import org.thoughtcrime.securesms.database.model.ThreadRecord
3939
import org.thoughtcrime.securesms.dependencies.ConfigFactory
4040
import org.thoughtcrime.securesms.pro.ProStatusManager
41+
import org.thoughtcrime.securesms.pro.subscription.SubscriptionManager
4142
import org.thoughtcrime.securesms.repository.ConversationRepository
4243
import org.thoughtcrime.securesms.tokenpage.TokenPageNotificationManager
4344
import org.thoughtcrime.securesms.util.ClearDataUtils
@@ -58,6 +59,7 @@ class DebugMenuViewModel @Inject constructor(
5859
private val attachmentDatabase: AttachmentDatabase,
5960
private val conversationRepository: ConversationRepository,
6061
private val databaseInspector: DatabaseInspector,
62+
subscriptionManagers: Set<@JvmSuppressWildcards SubscriptionManager>,
6163
) : ViewModel() {
6264
private val TAG = "DebugMenu"
6365

@@ -85,12 +87,14 @@ class DebugMenuViewModel @Inject constructor(
8587
debugSubscriptionStatuses = setOf(
8688
DebugSubscriptionStatus.AUTO_GOOGLE,
8789
DebugSubscriptionStatus.EXPIRING_GOOGLE,
88-
DebugSubscriptionStatus.EXPIRED_GOOGLE, //todo PRO uncomment below once we know how to differentiate store providers
89-
// DebugSubscriptionStatus.AUTO_APPLE,
90-
// DebugSubscriptionStatus.EXPIRING_APPLE,
91-
// DebugSubscriptionStatus.EXPIRED_APPLE,
90+
DebugSubscriptionStatus.AUTO_APPLE,
91+
DebugSubscriptionStatus.EXPIRING_APPLE,
92+
DebugSubscriptionStatus.EXPIRED,
9293
),
9394
selectedDebugSubscriptionStatus = textSecurePreferences.getDebugSubscriptionType() ?: DebugSubscriptionStatus.AUTO_GOOGLE,
95+
debugProPlans = subscriptionManagers.asSequence()
96+
.flatMap { it.availablePlans.asSequence().map { plan -> DebugProPlan(it, plan) } }
97+
.toList(),
9498
)
9599
)
96100
val uiState: StateFlow<UIState>
@@ -296,6 +300,10 @@ class DebugMenuViewModel @Inject constructor(
296300
it.copy(selectedDebugSubscriptionStatus = command.status)
297301
}
298302
}
303+
304+
is Commands.PurchaseDebugPlan -> {
305+
command.plan.apply { manager.purchasePlan(plan) }
306+
}
299307
}
300308
}
301309

@@ -401,6 +409,7 @@ class DebugMenuViewModel @Inject constructor(
401409
val dbInspectorState: DatabaseInspectorState,
402410
val debugSubscriptionStatuses: Set<DebugSubscriptionStatus>,
403411
val selectedDebugSubscriptionStatus: DebugSubscriptionStatus,
412+
val debugProPlans: List<DebugProPlan>,
404413
)
405414

406415
enum class DatabaseInspectorState {
@@ -412,10 +421,9 @@ class DebugMenuViewModel @Inject constructor(
412421
enum class DebugSubscriptionStatus(val label: String) {
413422
AUTO_GOOGLE("Auto Renewing (Google, 3 months)"),
414423
EXPIRING_GOOGLE("Expiring/Cancelled (Google, 12 months)"),
415-
EXPIRED_GOOGLE("Expired (Google)"),
416424
AUTO_APPLE("Auto Renewing (Apple, 1 months)"),
417425
EXPIRING_APPLE("Expiring/Cancelled (Apple, 1 months)"),
418-
EXPIRED_APPLE("Expired (Apple)")
426+
EXPIRED("Expired"),
419427
}
420428

421429
sealed class Commands {
@@ -442,5 +450,6 @@ class DebugMenuViewModel @Inject constructor(
442450
data class GenerateContacts(val prefix: String, val count: Int): Commands()
443451
data object ToggleDatabaseInspector : Commands()
444452
data class SetDebugSubscriptionStatus(val status: DebugSubscriptionStatus) : Commands()
453+
data class PurchaseDebugPlan(val plan: DebugProPlan) : Commands()
445454
}
446455
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.thoughtcrime.securesms.debugmenu
2+
3+
import org.thoughtcrime.securesms.pro.subscription.ProSubscriptionDuration
4+
import org.thoughtcrime.securesms.pro.subscription.SubscriptionManager
5+
6+
data class DebugProPlan(
7+
val manager: SubscriptionManager,
8+
val plan: ProSubscriptionDuration
9+
) {
10+
val label: String get() = "${manager.id}-${plan.name}"
11+
}

app/src/main/java/org/thoughtcrime/securesms/dependencies/OnAppStartupComponents.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.notifications.BackgroundPollManager
2222
import org.thoughtcrime.securesms.notifications.PushRegistrationHandler
2323
import org.thoughtcrime.securesms.pro.ProStatusManager
2424
import org.thoughtcrime.securesms.pro.subscription.SubscriptionCoordinator
25+
import org.thoughtcrime.securesms.pro.subscription.SubscriptionManager
2526
import org.thoughtcrime.securesms.service.ExpiringMessageManager
2627
import org.thoughtcrime.securesms.tokenpage.TokenDataManager
2728
import org.thoughtcrime.securesms.util.AppVisibilityManager
@@ -68,6 +69,7 @@ class OnAppStartupComponents private constructor(
6869
subscriptionCoordinator: SubscriptionCoordinator,
6970
avatarUploadManager: AvatarUploadManager,
7071
configToDatabaseSync: ConfigToDatabaseSync,
72+
subscriptionManagers: Set<@JvmSuppressWildcards SubscriptionManager>,
7173
): this(
7274
components = listOf(
7375
configUploader,
@@ -99,6 +101,6 @@ class OnAppStartupComponents private constructor(
99101
subscriptionCoordinator,
100102
avatarUploadManager,
101103
configToDatabaseSync,
102-
)
104+
) + subscriptionManagers
103105
)
104106
}

app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ import android.view.ViewGroup.MarginLayoutParams
1212
import android.widget.Toast
1313
import androidx.activity.viewModels
1414
import androidx.compose.foundation.clickable
15+
import androidx.compose.foundation.interaction.MutableInteractionSource
1516
import androidx.compose.runtime.collectAsState
1617
import androidx.compose.runtime.getValue
18+
import androidx.compose.runtime.remember
1719
import androidx.compose.ui.Modifier
1820
import androidx.compose.ui.platform.ViewCompositionStrategy
1921
import androidx.core.view.isVisible
@@ -216,7 +218,11 @@ class HomeActivity : ScreenLockActionBarActivity(),
216218
Avatar(
217219
size = LocalDimensions.current.iconMediumAvatar,
218220
data = avatarUtils.getUIDataFromRecipient(recipient),
219-
modifier = Modifier.clickable(onClick = ::openSettings)
221+
modifier = Modifier.clickable(
222+
interactionSource = remember { MutableInteractionSource() },
223+
indication = null,
224+
onClick = ::openSettings
225+
)
220226
)
221227
}
222228

0 commit comments

Comments
 (0)