Skip to content

Commit 4b2c91e

Browse files
committed
ecosystem link handling
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
1 parent 24e7455 commit 4b2c91e

File tree

8 files changed

+87
-69
lines changed

8 files changed

+87
-69
lines changed

app/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,8 +504,9 @@ dependencies {
504504
"gplayImplementation"(libs.bundles.gplay)
505505
// endregion
506506

507-
// region UI
507+
// region common
508508
implementation(libs.ui)
509+
implementation(libs.common.core)
509510
// endregion
510511

511512
// region Image loading

app/src/main/AndroidManifest.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,13 @@
147147
android:exported="true"
148148
android:launchMode="singleTop"
149149
android:theme="@style/Theme.ownCloud.Launcher">
150+
151+
<intent-filter>
152+
<action android:name="com.nextcloud.intent.OPEN_ECOSYSTEM_APP" />
153+
<category android:name="android.intent.category.DEFAULT" />
154+
</intent-filter>
155+
156+
150157
<intent-filter>
151158
<action android:name="android.intent.action.SEARCH" />
152159
</intent-filter>

app/src/main/java/com/nextcloud/utils/LinkHelper.kt

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -10,53 +10,17 @@ package com.nextcloud.utils
1010
import android.content.ActivityNotFoundException
1111
import android.content.Context
1212
import android.content.Intent
13-
import android.net.Uri
1413
import androidx.core.net.toUri
15-
import com.nextcloud.client.account.User
1614
import com.owncloud.android.lib.common.utils.Log_OC
17-
import com.owncloud.android.ui.activity.FileDisplayActivity
1815
import java.util.Locale
19-
import java.util.Optional
20-
import kotlin.jvm.optionals.getOrNull
2116

2217
object LinkHelper {
23-
const val APP_NEXTCLOUD_NOTES = "it.niedermann.owncloud.notes"
24-
const val APP_NEXTCLOUD_TALK = "com.nextcloud.talk2"
2518
private const val TAG = "LinkHelper"
2619

2720
fun isHttpOrHttpsLink(link: String?): Boolean = link?.lowercase(Locale.getDefault())?.let {
2821
it.startsWith("http://") || it.startsWith("https://")
2922
} == true
3023

31-
/**
32-
* Open specified app and, if not installed redirect to corresponding download.
33-
*
34-
* @param packageName of app to be opened
35-
* @param user to pass in intent
36-
*/
37-
fun openAppOrStore(packageName: String, user: Optional<User>, context: Context) {
38-
openAppOrStore(packageName, user.getOrNull(), context)
39-
}
40-
41-
/**
42-
* Open specified app and, if not installed redirect to corresponding download.
43-
*
44-
* @param packageName of app to be opened
45-
* @param user to pass in intent
46-
*/
47-
fun openAppOrStore(packageName: String, user: User?, context: Context) {
48-
val intent = context.packageManager.getLaunchIntentForPackage(packageName)
49-
if (intent != null) {
50-
// app installed - open directly
51-
// TODO handle null user?
52-
intent.putExtra(FileDisplayActivity.KEY_ACCOUNT, user.hashCode())
53-
context.startActivity(intent)
54-
} else {
55-
// app not found - open market (Google Play Store, F-Droid, etc.)
56-
openAppStore(packageName, false, context)
57-
}
58-
}
59-
6024
/**
6125
* Open app store page of specified app or search for specified string. Will attempt to open browser when no app
6226
* store is available.
@@ -69,7 +33,7 @@ object LinkHelper {
6933
val intent = Intent(Intent.ACTION_VIEW, "market://$suffix".toUri())
7034
try {
7135
context.startActivity(intent)
72-
} catch (activityNotFoundException1: ActivityNotFoundException) {
36+
} catch (_: ActivityNotFoundException) {
7337
// all is lost: open google play store web page for app
7438
if (!search) {
7539
suffix = "apps/$suffix"
@@ -82,32 +46,6 @@ object LinkHelper {
8246
// region Validation
8347
private const val HTTP = "http"
8448
private const val HTTPS = "https"
85-
private const val FILE = "file"
86-
private const val CONTENT = "content"
87-
88-
/**
89-
* Validates if a string can be converted to a valid URI
90-
*/
91-
@Suppress("TooGenericExceptionCaught", "ReturnCount")
92-
fun validateAndGetURI(uriString: String?): Uri? {
93-
if (uriString.isNullOrBlank()) {
94-
Log_OC.w(TAG, "Given uriString is null or blank")
95-
return null
96-
}
97-
98-
return try {
99-
val uri = uriString.toUri()
100-
if (uri.scheme == null) {
101-
return null
102-
}
103-
104-
val validSchemes = listOf(HTTP, HTTPS, FILE, CONTENT)
105-
if (uri.scheme in validSchemes) uri else null
106-
} catch (e: Exception) {
107-
Log_OC.e(TAG, "Invalid URI string: $uriString -- $e")
108-
null
109-
}
110-
}
11149

11250
/**
11351
* Validates if a URL string is valid

app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
import com.google.android.material.button.MaterialButton;
5050
import com.google.android.material.navigation.NavigationView;
5151
import com.google.android.material.progressindicator.LinearProgressIndicator;
52+
import com.nextcloud.android.common.core.utils.ecosystem.EcosystemApp;
53+
import com.nextcloud.android.common.core.utils.ecosystem.EcosystemManager;
5254
import com.nextcloud.android.common.ui.theme.utils.ColorRole;
5355
import com.nextcloud.client.account.User;
5456
import com.nextcloud.client.di.Injectable;
@@ -205,6 +207,8 @@ public abstract class DrawerActivity extends ToolbarActivity
205207

206208
private BottomNavigationView bottomNavigationView;
207209

210+
private EcosystemManager ecosystemManager;
211+
208212
@Inject
209213
AppPreferences preferences;
210214

@@ -429,8 +433,13 @@ private void showTopBanner(ConstraintLayout banner) {
429433
LinearLayout moreView = banner.findViewById(R.id.drawer_ecosystem_more);
430434
LinearLayout assistantView = banner.findViewById(R.id.drawer_ecosystem_assistant);
431435

432-
notesView.setOnClickListener(v -> LinkHelper.INSTANCE.openAppOrStore(LinkHelper.APP_NEXTCLOUD_NOTES, getUser(), this));
433-
talkView.setOnClickListener(v -> LinkHelper.INSTANCE.openAppOrStore(LinkHelper.APP_NEXTCLOUD_TALK, getUser(), this));
436+
final var optionalUser = getUser();
437+
if (optionalUser.isPresent()) {
438+
final var accountName = optionalUser.get().getAccountName();
439+
notesView.setOnClickListener(v -> ecosystemManager.openApp(EcosystemApp.NOTES, accountName));
440+
talkView.setOnClickListener(v -> ecosystemManager.openApp(EcosystemApp.TALK, accountName));
441+
}
442+
434443
moreView.setOnClickListener(v -> LinkHelper.INSTANCE.openAppStore("Nextcloud", true, this));
435444
assistantView.setOnClickListener(v -> {
436445
DrawerActivity.menuItemId = Menu.NONE;
@@ -727,6 +736,10 @@ private void launchActivityForSearch(SearchEvent searchEvent, int menuItemId) {
727736
startActivity(intent);
728737
}
729738

739+
public EcosystemManager getEcosystemManager() {
740+
return ecosystemManager;
741+
}
742+
730743
/**
731744
* sets the new/current account and restarts. In case the given account equals the actual/current account the call
732745
* will be ignored.
@@ -1136,6 +1149,7 @@ protected void onCreate(Bundle savedInstanceState) {
11361149

11371150
externalLinksProvider = new ExternalLinksProvider(getContentResolver());
11381151
arbitraryDataProvider = new ArbitraryDataProviderImpl(this);
1152+
ecosystemManager = new EcosystemManager(this);
11391153
}
11401154

11411155
@Override

app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
5252
import com.google.android.material.appbar.AppBarLayout
5353
import com.google.android.material.dialog.MaterialAlertDialogBuilder
5454
import com.google.android.material.snackbar.Snackbar
55+
import com.nextcloud.android.common.core.utils.ecosystem.AccountReceiverCallback
5556
import com.nextcloud.appReview.InAppReviewHelper
5657
import com.nextcloud.client.account.User
5758
import com.nextcloud.client.appinfo.AppInfo
@@ -547,6 +548,7 @@ class FileDisplayActivity :
547548
handleCommonIntents(intent)
548549
handleSpecialIntents(intent)
549550
handleRestartIntent(intent)
551+
handleEcosystemIntent(intent)
550552
}
551553

552554
private fun handleSpecialIntents(intent: Intent) {
@@ -3073,6 +3075,26 @@ class FileDisplayActivity :
30733075
})
30743076
}
30753077

3078+
private fun handleEcosystemIntent(intent: Intent?) {
3079+
ecosystemManager.receiveAccount(
3080+
intent,
3081+
object : AccountReceiverCallback {
3082+
override fun onAccountReceived(accountName: String) {
3083+
val user = accountManager.getUser(accountName)
3084+
if (user.isPresent) {
3085+
accountClicked(user.get())
3086+
} else {
3087+
Log_OC.e(TAG, "user is not present")
3088+
}
3089+
}
3090+
3091+
override fun onAccountError(reason: String) {
3092+
Log_OC.w(TAG, "handleEcosystemIntent: $reason")
3093+
}
3094+
}
3095+
)
3096+
}
3097+
30763098
// region MetadataSyncJob
30773099
private fun startMetadataSyncForRoot() {
30783100
backgroundJobManager.startMetadataSyncJob(OCFile.ROOT_PATH)

app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@
2626

2727
import com.elyeproj.loaderviewlibrary.LoaderImageView;
2828
import com.google.android.material.chip.Chip;
29+
import com.nextcloud.android.common.core.utils.ecosystem.EcosystemApp;
2930
import com.nextcloud.android.common.ui.theme.utils.ColorRole;
3031
import com.nextcloud.client.account.User;
3132
import com.nextcloud.client.database.entity.OfflineOperationEntity;
3233
import com.nextcloud.client.jobs.upload.FileUploadHelper;
3334
import com.nextcloud.client.preferences.AppPreferences;
3435
import com.nextcloud.model.OfflineOperationType;
35-
import com.nextcloud.utils.LinkHelper;
3636
import com.nextcloud.utils.extensions.OCFileExtensionsKt;
3737
import com.nextcloud.utils.extensions.ViewExtensionsKt;
3838
import com.nextcloud.utils.mdm.MDMConfig;
@@ -55,6 +55,7 @@
5555
import com.owncloud.android.lib.resources.status.OCCapability;
5656
import com.owncloud.android.lib.resources.tags.Tag;
5757
import com.owncloud.android.ui.activity.ComponentsGetter;
58+
import com.owncloud.android.ui.activity.DrawerActivity;
5859
import com.owncloud.android.ui.activity.FileDisplayActivity;
5960
import com.owncloud.android.ui.adapter.helper.OCFileListAdapterDataProvider;
6061
import com.owncloud.android.ui.adapter.helper.OCFileListAdapterHelper;
@@ -449,7 +450,12 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi
449450
listHeaderOpenInBinding.openInButton.setText(String.format(activity.getString(R.string.open_in_app),
450451
activity.getString(R.string.ecosystem_apps_display_notes)));
451452

452-
listHeaderOpenInBinding.openInButton.setOnClickListener(v -> LinkHelper.INSTANCE.openAppOrStore(LinkHelper.APP_NEXTCLOUD_NOTES, user, activity));
453+
if (activity instanceof DrawerActivity drawerActivity) {
454+
final var ecosystemManager = drawerActivity.getEcosystemManager();
455+
if (ecosystemManager != null) {
456+
listHeaderOpenInBinding.openInButton.setOnClickListener(v -> ecosystemManager.openApp(EcosystemApp.NOTES, user.getAccountName()));
457+
}
458+
}
453459
}
454460

455461
} else {

gradle/libs.versions.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# SPDX-License-Identifier: AGPL-3.0-or-later
33

44
[versions]
5-
androidCommonLibraryVersion = "0.31.0"
5+
androidCommonLibraryVersion = "c7da76323d"
66
androidGifDrawableVersion = "1.2.30"
77
androidImageCropperVersion = "4.7.0"
88
androidLibraryVersion = "c112fd86c76f429db250e6abca711348e5534c0a"
@@ -232,6 +232,7 @@ prism4j-bundler = { module = "io.noties:prism4j-bundler", version.ref = "prismVe
232232

233233
# Nextcloud libraries
234234
ui = { module = "com.github.nextcloud.android-common:ui", version.ref = "androidCommonLibraryVersion" }
235+
common-core = { module = "com.github.nextcloud.android-common:core", version.ref = "androidCommonLibraryVersion" }
235236
qrcodescanner = { module = "com.github.nextcloud-deps:qrcodescanner", version.ref = "qrcodescannerVersion" }
236237

237238
# Worker

gradle/verification-metadata.xml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,11 @@
14491449
<sha256 value="11c8654511c3926c5e8f32b909d7d5e6785a7282b5d01e1f6071ec3afa36e3a0" origin="Generated by Gradle" reason="Artifact is not signed"/>
14501450
</artifact>
14511451
</component>
1452+
<component group="androidx.compose" name="compose-bom" version="2026.01.00">
1453+
<artifact name="compose-bom-2026.01.00.pom">
1454+
<sha256 value="9bc8c321324e7492f74ce7de4b6a2a12f8f37cafc4a7a2a882ab75da972779ce" origin="Generated by Gradle" reason="Artifact is not signed"/>
1455+
</artifact>
1456+
</component>
14521457
<component group="androidx.compose.animation" name="animation" version="1.10.0">
14531458
<artifact name="animation-1.10.0.module">
14541459
<sha256 value="2158c1b57ce292ac2fd0d1541ece2cd08bbfbbd80aa6417a0668076693855458" origin="Generated by Gradle"/>
@@ -20760,6 +20765,14 @@
2076020765
<sha256 value="3fc98a0ab817e61f711b15cc6be5fd145f58aea4840f6b7985c73557f9cc0810" origin="Generated by Gradle"/>
2076120766
</artifact>
2076220767
</component>
20768+
<component group="com.github.nextcloud.android-common" name="core" version="c7da76323d">
20769+
<artifact name="core-c7da76323d.aar">
20770+
<sha256 value="1fa9233ff3bc96416c7408db4ba1ba30f9b320e2868597e7de32563e8eb6feff" origin="Generated by Gradle" reason="Artifact is not signed"/>
20771+
</artifact>
20772+
<artifact name="core-c7da76323d.module">
20773+
<sha256 value="bdbb738048b801f8da697844997ca6169909b8b239f71b70b7cddbe522668de1" origin="Generated by Gradle" reason="Artifact is not signed"/>
20774+
</artifact>
20775+
</component>
2076320776
<component group="com.github.nextcloud.android-common" name="core" version="df2f116806">
2076420777
<artifact name="core-df2f116806.aar">
2076520778
<sha256 value="38011f3adff2f68c6c99cb121a5def63cc44a66e393373203687b59c5fb82ce8" origin="Generated by Gradle"/>
@@ -20940,6 +20953,14 @@
2094020953
<sha256 value="3d947236ced64bd6071adb8a610d7640b5dd469e4dac933306d0e01268131a27" origin="Generated by Gradle"/>
2094120954
</artifact>
2094220955
</component>
20956+
<component group="com.github.nextcloud.android-common" name="material-color-utilities" version="c7da76323d">
20957+
<artifact name="material-color-utilities-c7da76323d.jar">
20958+
<sha256 value="61568a8c8f0466aea4fec621653ca8d2c08c9c687ffd6e364f909a2d19185992" origin="Generated by Gradle" reason="Artifact is not signed"/>
20959+
</artifact>
20960+
<artifact name="material-color-utilities-c7da76323d.module">
20961+
<sha256 value="815aaf811e7efd48171f25ec57aea023b8f74b21db5a4c3abc82b815e0c91d37" origin="Generated by Gradle" reason="Artifact is not signed"/>
20962+
</artifact>
20963+
</component>
2094320964
<component group="com.github.nextcloud.android-common" name="material-color-utilities" version="df2f116806">
2094420965
<artifact name="material-color-utilities-df2f116806.jar">
2094520966
<sha256 value="56547ff6e6201d788fe85b11ca8d9185104f95ae001412d903fb1cf700ffddca" origin="Generated by Gradle"/>
@@ -21116,6 +21137,14 @@
2111621137
<sha256 value="2154d71ba506b1de2e2645cc42accdbfaec67162c713e118a2bc4ecb5cd2196f" origin="Generated by Gradle"/>
2111721138
</artifact>
2111821139
</component>
21140+
<component group="com.github.nextcloud.android-common" name="ui" version="c7da76323d">
21141+
<artifact name="ui-c7da76323d.aar">
21142+
<sha256 value="041d67ffbb102dfa828719e35f1d416997706793c2674b9da4f135b3667c002c" origin="Generated by Gradle" reason="Artifact is not signed"/>
21143+
</artifact>
21144+
<artifact name="ui-c7da76323d.module">
21145+
<sha256 value="26d0b02f74a82ec0f512e14006fd674d6773b65147e56b232cddba111b6d656c" origin="Generated by Gradle" reason="Artifact is not signed"/>
21146+
</artifact>
21147+
</component>
2111921148
<component group="com.github.nextcloud.android-common" name="ui" version="df2f116806">
2112021149
<artifact name="ui-df2f116806.aar">
2112121150
<sha256 value="9eaf161c0535e87fec9585d97b5d5244229c7fdbde348bfebf7747f5bcd3f952" origin="Generated by Gradle"/>

0 commit comments

Comments
 (0)