Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
2c8f392
feat(share): take the shares of other apps through ShareActivity
mahibi Oct 30, 2026
b7aaed7
refactor(launch): make the conversation list the launcher and remove …
mahibi Oct 30, 2026
4f9d29e
feat(launch): show the androidx splash screen when the app is started
mahibi Oct 30, 2026
15a28bd
fix(lock): route a deep link once the app is unlocked
mahibi Oct 30, 2026
7a00a88
fix(deeplink): only rewrite implicit view intents to open a chat
mahibi Nov 2, 2026
1f10ff3
fix(shortcuts): open the conversation of a shortcut once the app is u…
mahibi Nov 2, 2026
049e756
fix(share): recognise the uris of every provider of the own app
mahibi Nov 2, 2026
842f42a
fix(account): relaunch the list for the new default account with a pl…
mahibi Nov 2, 2026
e82165a
fix(account): keep the account of the list when it is recreated
mahibi Nov 2, 2026
71dac12
fix(deeplink): don't make the account of a deep link active before it…
mahibi Nov 2, 2026
f8da88d
style(share): fix the ktlint findings of the shared uri check
mahibi Nov 2, 2026
f16e7d0
fix(launch): don't stack conversation lists on a task a notification …
mahibi Nov 2, 2026
937aa2a
fix(lock): keep the app locked until it is unlocked
mahibi Nov 2, 2026
f9e43b4
fix(share): don't copy the copies of shared files again
mahibi Nov 2, 2026
990f3fd
fix(account): show the list of the conversation's account after leavi…
mahibi Nov 2, 2026
435f9ba
fix(tasks): find the tasks of the app before Android 10
mahibi Nov 2, 2026
556c3c2
fix(deeplink): don't pass on the link of a task relaunched from the r…
mahibi Nov 2, 2026
d01aa07
fix(shortcuts): open the conversation of exactly the account of a sho…
mahibi Nov 2, 2026
85e913c
fix(share): stop copying the shared files when the share is left
mahibi Nov 2, 2026
c9515c1
fix(share): remove the copies of a share that is left or done
mahibi Nov 2, 2026
7e4aeee
fix(contacts): show an error when the chat with a contact can't be cr…
mahibi Nov 2, 2026
5e556cc
fix(list): set up the push registration once per start of the app
mahibi Nov 2, 2026
98a90a0
fix(contacts): only open the chat of a contact row of Talk
mahibi Nov 2, 2026
fd42bfe
fix(list): ignore a new intent of a list that wasn't set up
mahibi Nov 2, 2026
a2b5236
fix(share): keep the copies of shared files out of the cache
mahibi Nov 2, 2026
9e67f17
refactor(notifications): use isStartedThrough for the conversation li…
mahibi Nov 2, 2026
c56d87e
refactor(contacts): create the chat with a contact through ContactsRe…
mahibi Nov 2, 2026
8e7c218
refactor(list): leave the login without an account to BaseActivity
mahibi Nov 2, 2026
08c027f
refactor(list): move the setup once per process out of onCreate
mahibi Nov 2, 2026
955243b
fix(chat): only open a chat with a valid room token
mahibi Nov 2, 2026
b36f983
fix(shortcuts): open the conversation of a shortcut also when the app…
mahibi Nov 2, 2026
d7e35ff
fix(chat): don't crash when a chat without a room token is closed
mahibi Nov 2, 2026
c562083
fix(lock): leave the app with Back on the lock screen
mahibi Nov 2, 2026
b854977
fix(shortcuts): open the conversation of a shortcut once it is in the…
mahibi Nov 2, 2026
f075803
refactor(lock): remove the unused opt-out of the lock check
mahibi Nov 2, 2026
e544e6c
fix(share): leave a share that is left while its files are copied
mahibi Nov 2, 2026
ef9f4b0
fix(shortcuts): give the shortcuts of earlier versions a working intent
mahibi Nov 2, 2026
97e92c9
fix(shortcuts): open note to self through the list like the other sho…
mahibi Nov 2, 2026
0ab595d
perf(tasks): remove the tasks left in the recents off the main thread
mahibi Nov 2, 2026
a3f3803
refactor(lock): keep screens from opening above the lock screen in on…
mahibi Nov 2, 2026
46078ac
fix(share): keep the copies of a preview the system recreates
mahibi Nov 2, 2026
46d45a4
fix(share): pass on the files of a share that also has a text
mahibi Nov 2, 2026
0b1e00d
fix(list): drop the uri of a view intent when the list keeps its account
mahibi Nov 2, 2026
02cdceb
docs: wrap the comments of the shortcut update and ShareActivity at 1…
mahibi Nov 2, 2026
cfe1f45
refactor(list): name the account switch of the shown list apart from …
mahibi Nov 2, 2026
53c3515
fix(lock): close the lock screen when it isn't needed anymore
mahibi Nov 2, 2026
cc388d3
fix(deeplink): open a link without a user name with the current account
mahibi Nov 2, 2026
3644be1
fix(share): preselect the conversation of a direct share target reliably
mahibi Nov 2, 2026
4a8609d
fix(chat): keep the shared files of a chat recreated before its room …
mahibi Nov 2, 2026
fd85ea6
fix(call): keep a share list when a call ends
mahibi Nov 2, 2026
676922a
fix(share): give the fallback intent of a direct share shortcut an ac…
mahibi Nov 2, 2026
c7a03da
refactor(list): take the conversation of a shortcut in a function of …
mahibi Nov 2, 2026
ab8cc61
refactor(list): leave onCreate in one place when the list isn't shown
mahibi Nov 2, 2026
0fafa5b
fix(share): read the authority of a shared file's uri that names the …
mahibi Nov 2, 2026
5f2496a
perf(share): ask WorkManager once for the uploads of the shares to re…
mahibi Nov 2, 2026
a634809
docs: shorten the comments of the account intent, the shortcut update…
mahibi Nov 2, 2026
aa5f124
fix(shortcuts): don't open the conversation of a shortcut again from …
mahibi Nov 2, 2026
eb67fc7
fix(list): don't drop a new intent for a switch to the default account
mahibi Nov 2, 2026
152573a
fix(lock): don't lock again right after unlocking
mahibi Nov 2, 2026
de4c67f
fix(share): remove copies only for a share of ShareActivity
mahibi Nov 2, 2026
43f4a74
refactor: tell a task relaunched from the recents in one place
mahibi Nov 2, 2026
50b1e66
fix(share): keep the copies of shared files out of backups also from …
mahibi Nov 2, 2026
f75f699
fix(shortcuts): open the conversation of a shortcut once the sync ends
mahibi Nov 2, 2026
66f4722
fix(chat): replace the chat by the chat of an audio message of anothe…
mahibi Nov 2, 2026
961b68b
refactor(call): tell a share task as AppTasks does
mahibi Nov 2, 2026
c43b624
refactor(shortcuts): don't focus the message input for the note to se…
mahibi Nov 3, 2026
9eb9693
refactor(list): rename pendingDirectShareToken to pendingShortcutToken
mahibi Nov 3, 2026
95ca9f1
fix(upload): keep the access to picked files until their upload is done
mahibi Nov 3, 2026
e7736b8
fix(deeplink): show the splash screen of a link with the app icon
mahibi Nov 3, 2026
581f64f
fix(lock): leave the app when the screen lock of the device is left w…
mahibi Nov 3, 2026
3e661aa
fix(deeplink): ask before joining the call of a voice room opened by …
mahibi Nov 3, 2026
3a8a74e
fix(test): read the default account of LoginIT from the conversation …
mahibi Nov 3, 2026
a3554c8
fix(build): keep the test libraries out of the app
mahibi Nov 3, 2026
b399c71
fix(lint): mark origActivity of a recent task as available before API 29
mahibi Nov 3, 2026
5135a16
fix(lint): check for a retry of an upload through Result.retry()
mahibi Nov 3, 2026
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
5 changes: 3 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ dependencies {
}
implementation("androidx.media3:media3-session:1.11.1")
kapt("org.jetbrains.kotlin:kotlin-metadata-jvm:$kotlinVersion")
implementation("androidx.room:room-testing-android:$roomVersion")
androidTestImplementation("androidx.room:room-testing-android:$roomVersion")
implementation("androidx.compose.foundation:foundation-layout:1.12.1")
spotbugsPlugins("com.h3xstream.findsecbugs:findsecbugs-plugin:1.14.0")
spotbugsPlugins("com.mebigfatguy.fb-contrib:fb-contrib:7.7.4")
Expand All @@ -209,7 +209,7 @@ dependencies {
implementation("androidx.preference:preference-ktx:1.2.1")
implementation("androidx.datastore:datastore-core:1.3.0")
implementation("androidx.datastore:datastore-preferences:1.3.0")
implementation("androidx.test.ext:junit-ktx:1.3.0")
androidTestImplementation("androidx.test.ext:junit-ktx:1.3.0")

implementation(fileTree(mapOf("include" to listOf("*"), "dir" to "libs")))

Expand Down Expand Up @@ -329,6 +329,7 @@ dependencies {
}

implementation("androidx.core:core-ktx:1.19.1")
implementation("androidx.core:core-splashscreen:1.2.0")
implementation("androidx.sharetarget:sharetarget:1.2.0")
implementation("androidx.activity:activity-ktx:1.13.0")
implementation("com.github.nextcloud.android-common:ui:0.34.0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.activities
package com.nextcloud.talk.account

import androidx.test.espresso.intent.rule.IntentsTestRule
import com.nextcloud.talk.users.UserManager
Expand All @@ -15,10 +15,10 @@ import org.junit.Assert.assertNotNull
import org.junit.Rule
import org.junit.Test

class MainActivityTest {
class ServerSelectionActivityTest {
@get:Rule
val activityRule: IntentsTestRule<MainActivity> = IntentsTestRule(
MainActivity::class.java,
val activityRule: IntentsTestRule<ServerSelectionActivity> = IntentsTestRule(
ServerSelectionActivity::class.java,
true,
false
)
Expand Down
8 changes: 6 additions & 2 deletions app/src/androidTest/java/com/nextcloud/talk/ui/LoginIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@
import android.os.Bundle;

import com.nextcloud.talk.R;
import com.nextcloud.talk.activities.MainActivity;
import com.nextcloud.talk.conversationlist.ConversationsListActivity;
import com.nextcloud.talk.utils.AppTasks;

import org.junit.Ignore;
import org.junit.Test;

import java.util.Objects;

import androidx.test.core.app.ActivityScenario;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.espresso.NoMatchingViewException;
import androidx.test.espresso.web.webdriver.DriverAtoms;
import androidx.test.espresso.web.webdriver.Locator;
Expand All @@ -44,7 +46,9 @@ public class LoginIT {
@Test
public void login() throws InterruptedException {

ActivityScenario<MainActivity> activityScenario = ActivityScenario.launch(MainActivity.class);
// started like by the launcher, without an account
ActivityScenario<ConversationsListActivity> activityScenario = ActivityScenario.launch(
AppTasks.INSTANCE.createLauncherIntent(ApplicationProvider.getApplicationContext()));

Bundle arguments = androidx.test.platform.app.InstrumentationRegistry.getArguments();

Expand Down
2 changes: 1 addition & 1 deletion app/src/gplay/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
android:label="@string/nc_app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:supportsRtl="true"
android:theme="@style/AppTheme.Launcher"
android:theme="@style/AppTheme"
tools:replace="label, icon, theme, name, allowBackup"
tools:ignore="UnusedAttribute, ExportedService">

Expand Down
65 changes: 47 additions & 18 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,15 @@
<application
android:name=".application.NextcloudTalkApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_config"
android:icon="@mipmap/ic_launcher"
android:label="@string/nc_app_name"
android:largeHeap="true"
android:networkSecurityConfig="@xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
android:theme="@style/AppTheme.Launcher"
android:theme="@style/AppTheme"
android:taskAffinity=""
tools:ignore="UnusedAttribute"
tools:replace="label, icon, theme, name, allowBackup">
Expand All @@ -106,16 +107,14 @@
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>

<!-- Entry point for the intents of other apps that open a conversation. It shows nothing and passes them on to
the conversation list in the app's task, so it is kept out of the recents. -->
<activity
android:name=".activities.MainActivity"
android:name=".activities.DeepLinkActivity"
android:excludeFromRecents="true"
android:exported="true"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

android:noHistory="true"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
Expand All @@ -125,10 +124,6 @@
<data android:scheme="file" />
</intent-filter>

<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />

<!-- Custom URI scheme for opening conversations from external apps/launchers -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
Expand Down Expand Up @@ -167,16 +162,27 @@
<activity
android:name=".conversationlist.ConversationsListActivity"
android:exported="true"
android:theme="@style/AppTheme.DisplayCutout">

<meta-data
android:name="android.service.chooser.chooser_target_service"
android:value="androidx.sharetarget.ChooserTargetServiceCompat" />
android:theme="@style/Theme.App.Starting">

<intent-filter>
<action android:name="com.nextcloud.intent.OPEN_ECOSYSTEM_APP" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

<!-- Entry point for the content other apps share. It copies the shared files and opens the conversation list
to pick the conversation, in a task that is kept out of the recents. It handles all configuration
changes itself: it only shows a progress indicator, and being recreated would copy the files again. -->
<activity
android:name=".conversationlist.ShareActivity"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize|keyboard|keyboardHidden|navigation|touchscreen|uiMode|locale|layoutDirection|fontScale|fontWeightAdjustment|density|colorMode|mcc|mnc"
android:excludeFromRecents="true"
android:exported="true"
android:theme="@style/AppTheme.Translucent">

<meta-data
android:name="android.service.chooser.chooser_target_service"
android:value="androidx.sharetarget.ChooserTargetServiceCompat" />

<intent-filter>
<action android:name="android.intent.action.SEND" />
Expand All @@ -191,6 +197,29 @@
</intent-filter>
</activity>

<!-- Entry point for in-app intents of the conversation list. Not exported, so it can trust the account and
conversation of intents started through it. -->
<activity-alias
android:name=".conversationlist.InternalConversationsListActivity"
android:exported="false"
android:targetActivity=".conversationlist.ConversationsListActivity" />

<!-- The launcher activity: the conversation list, under the name home-screen icons and pinned shortcuts of
earlier versions refer to. -->
<activity-alias
android:name=".activities.MainActivity"
android:exported="true"
android:targetActivity=".conversationlist.ConversationsListActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity-alias>

<activity
android:name=".chat.ChatActivity"
android:theme="@style/AppTheme.DisplayCutout" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ class AccountVerificationActivity : BaseActivity() {
ApplicationWideMessageHolder.getInstance().messageType =
ApplicationWideMessageHolder.MessageType.ACCOUNT_WAS_IMPORTED
}
val intent = Intent(context, ConversationsListActivity::class.java)
val intent = ConversationsListActivity.createIntent(context)
intent.putExtra(BundleKeys.KEY_INTERNAL_USER_ID, userToSetAsActive.id)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.account.data.LoginRepository
import com.nextcloud.talk.account.viewmodels.BrowserLoginActivityViewModel
import com.nextcloud.talk.activities.BaseActivity
import com.nextcloud.talk.activities.MainActivity
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
import com.nextcloud.talk.databinding.ActivityWebViewLoginBinding
import com.nextcloud.talk.utils.AppTasks
import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_BASE_URL
import kotlinx.coroutines.launch
Expand All @@ -49,9 +49,7 @@ class BrowserLoginActivity : BaseActivity() {
private var reauthorizeAccount = false
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
val intent = Intent(context, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent)
startActivity(AppTasks.createRestartIntent(context))
}
}

Expand Down Expand Up @@ -187,9 +185,7 @@ class BrowserLoginActivity : BaseActivity() {
}

private fun restartApp() {
val intent = Intent(context, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent)
startActivity(AppTasks.createRestartIntent(context))
}

public override fun onDestroy() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package com.nextcloud.talk.account
import android.Manifest
import android.accounts.Account
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.os.Bundle
Expand Down Expand Up @@ -520,5 +521,18 @@ class ServerSelectionActivity : BaseActivity() {
private val TAG = ServerSelectionActivity::class.java.simpleName
const val MIN_SERVER_MAJOR_VERSION = 13
private const val QR_URI = "com.blikoon.qrcodescanner.got_qr_scan_relult"

/**
* Creates the intent that starts the login: the web login on the server of a branded client, or else the
* selection of the server.
*/
fun createLoginIntent(context: Context): Intent {
val brandedServerUrl = context.getString(R.string.weblogin_url)
return if (brandedServerUrl.isNotEmpty()) {
Intent(context, BrowserLoginActivity::class.java).putExtra(BundleKeys.KEY_BASE_URL, brandedServerUrl)
} else {
Intent(context, ServerSelectionActivity::class.java)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ class SwitchAccountActivity : BaseActivity() {
if (userManager.setUserAsActive(user)) {
DirectShareHelper.removeAllShareTargetShortcuts(this@SwitchAccountActivity)
cookieManager.cookieStore.removeAll()
val intent = ConversationsListActivity.createAccountSwitchIntent(this@SwitchAccountActivity, user.id!!)
startActivity(intent)
val context = this@SwitchAccountActivity
startActivity(ConversationsListActivity.createInPlaceAccountSwitchIntent(context, user.id!!))
finish()
}
}
Expand Down

This file was deleted.

Loading
Loading