From 93250bd07db4714e0340e55883ad1285acf2ecde Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Tue, 6 Jan 2026 21:50:28 +0100 Subject: [PATCH] Improve feed gestures --- .../ui/launcher/scaffold/FeedComponent.kt | 50 ++++++++++++++++--- docs/docs/user-guide/integrations/feed.md | 2 +- docs/docs/user-guide/sidebar.ts | 4 ++ .../de/mm20/launcher2/feed/FeedConnection.kt | 19 +++++++ .../mm20/launcher2/feed/ServiceConnection.kt | 18 ------- 5 files changed, 66 insertions(+), 27 deletions(-) delete mode 100644 services/feed/src/main/java/de/mm20/launcher2/feed/ServiceConnection.kt diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/scaffold/FeedComponent.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/scaffold/FeedComponent.kt index 4936048ba..f53a82f76 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/scaffold/FeedComponent.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/scaffold/FeedComponent.kt @@ -2,7 +2,6 @@ package de.mm20.launcher2.ui.launcher.scaffold import android.annotation.SuppressLint import android.content.Context -import android.util.Log import androidx.activity.compose.LocalActivity import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.layout.Arrangement @@ -19,6 +18,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -34,7 +34,6 @@ import de.mm20.launcher2.feed.FeedService import de.mm20.launcher2.preferences.feed.FeedSettings import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.ktx.toIntOffset -import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject @@ -47,6 +46,8 @@ internal class FeedComponent( override val permanent: Boolean = true + private var state = mutableIntStateOf(0) + @Composable override fun Component( modifier: Modifier, @@ -79,18 +80,30 @@ internal class FeedComponent( } } - val enableScroll = state.currentComponent == this && progress > 0f && progress < 1f + val componentState = this.state.intValue - LaunchedEffect(enableScroll) { - if (enableScroll) { + LaunchedEffect(state.currentComponent == this && componentState < 2) { + if (state.currentComponent == this@FeedComponent && componentState < 2) { feedConnection?.startScroll() - } else { + } + } + + LaunchedEffect(componentState == 2 && progress > 0.5f) { + if (componentState == 2 && progress > 0.5f) { feedConnection?.endScroll() } } - LaunchedEffect(progress) { - feedConnection?.onScroll(progress) + LaunchedEffect(componentState == 0) { + if (componentState == 0) { + feedConnection?.closeFeed() + } + } + + LaunchedEffect(state.currentComponent == this, progress) { + if (state.currentComponent == this@FeedComponent) { + feedConnection?.onScroll(progress) + } } LaunchedEffect(feedProgress.floatValue) { @@ -142,4 +155,25 @@ internal class FeedComponent( .alpha(1f - state.currentProgress) } + override suspend fun onPreActivate(state: LauncherScaffoldState) { + super.onPreActivate(state) + this.state.intValue = 2 + } + + override suspend fun onActivate(state: LauncherScaffoldState) { + super.onActivate(state) + this.state.intValue = 3 + } + + override suspend fun onDismiss(state: LauncherScaffoldState) { + super.onDismiss(state) + this.state.intValue = 0 + } + + override suspend fun onPreDismiss(state: LauncherScaffoldState) { + super.onPreDismiss(state) + this.state.intValue = 1 + } + + } \ No newline at end of file diff --git a/docs/docs/user-guide/integrations/feed.md b/docs/docs/user-guide/integrations/feed.md index 6f1a36097..bf602d1ec 100644 --- a/docs/docs/user-guide/integrations/feed.md +++ b/docs/docs/user-guide/integrations/feed.md @@ -1,6 +1,6 @@ # Feed -The feed is a personalized content page that lives to the left of your home screen, that can be +The feed is a personalized content page that lives to the left of your home screen, which can be opened without leaving the launcher. Traditionally, launchers show the Google Discover feed here, but there are other alternatives. diff --git a/docs/docs/user-guide/sidebar.ts b/docs/docs/user-guide/sidebar.ts index 338884bef..613711373 100644 --- a/docs/docs/user-guide/sidebar.ts +++ b/docs/docs/user-guide/sidebar.ts @@ -54,6 +54,10 @@ export const UserGuideSidebar: DefaultTheme.SidebarItem[] = [ text: 'Weather', link: '/docs/user-guide/integrations/weather', }, + { + text: 'Feed', + link: '/docs/user-guide/integrations/feed', + }, ], }, { diff --git a/services/feed/src/main/java/de/mm20/launcher2/feed/FeedConnection.kt b/services/feed/src/main/java/de/mm20/launcher2/feed/FeedConnection.kt index f4f23d0f9..bfc80297a 100644 --- a/services/feed/src/main/java/de/mm20/launcher2/feed/FeedConnection.kt +++ b/services/feed/src/main/java/de/mm20/launcher2/feed/FeedConnection.kt @@ -29,6 +29,9 @@ interface FeedConnection { fun startScroll() fun endScroll() fun onScroll(progress: Float) + + fun openFeed() + fun closeFeed() } internal class FeedConnectionImpl( @@ -77,6 +80,22 @@ internal class FeedConnectionImpl( } } + override fun openFeed() { + try { + overlay?.openOverlay(Flags) + } catch (e: RemoteException) { + CrashReporter.logException(e) + } + } + + override fun closeFeed() { + try { + overlay?.closeOverlay(Flags) + } catch (e: RemoteException) { + CrashReporter.logException(e) + } + } + fun start() { activity.lifecycle.addObserver(this) val service = activity.packageManager.resolveService(serviceIntent, 0) diff --git a/services/feed/src/main/java/de/mm20/launcher2/feed/ServiceConnection.kt b/services/feed/src/main/java/de/mm20/launcher2/feed/ServiceConnection.kt deleted file mode 100644 index 9733edbca..000000000 --- a/services/feed/src/main/java/de/mm20/launcher2/feed/ServiceConnection.kt +++ /dev/null @@ -1,18 +0,0 @@ -package de.mm20.launcher2.feed - -import amirz.aidlbridge.IBridgeCallback -import android.content.ComponentName -import android.content.ServiceConnection -import android.os.IBinder - -class ServiceConnection: IBridgeCallback.Stub(), ServiceConnection { - override fun onServiceConnected( - name: ComponentName?, - service: IBinder? - ) { - - } - - override fun onServiceDisconnected(name: ComponentName?) { - } -} \ No newline at end of file