mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 20:38:52 +00:00
fix(android): fix edge-to-edge (#12453)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added the ability to retrieve the system navigation bar height on Android devices. - **Bug Fixes** - Removed duplicate internal code to improve stability. - **Chores** - Removed the dependency on the edge-to-edge support package and related configuration and code. - Updated configuration to adjust margins for edge-to-edge layouts. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -12,7 +12,6 @@ dependencies {
|
||||
implementation project(':capacitor-app')
|
||||
implementation project(':capacitor-keyboard')
|
||||
implementation project(':capacitor-status-bar')
|
||||
implementation project(':capawesome-capacitor-android-edge-to-edge-support')
|
||||
implementation project(':capgo-inappbrowser')
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package app.affine.pro
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.updateMargins
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import app.affine.pro.ai.AIActivity
|
||||
@@ -64,6 +67,16 @@ class MainActivity : BridgeActivity(), AIButtonPlugin.Callback, AffineThemePlugi
|
||||
}
|
||||
}
|
||||
|
||||
private var naviHeight = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(window.decorView) { v, insets ->
|
||||
naviHeight = insets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom
|
||||
ViewCompat.onApplyWindowInsets(v, insets)
|
||||
}
|
||||
}
|
||||
|
||||
override fun load() {
|
||||
super.load()
|
||||
AuthInitializer.initialize(bridge)
|
||||
@@ -96,6 +109,10 @@ class MainActivity : BridgeActivity(), AIButtonPlugin.Callback, AffineThemePlugi
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSystemNaviBarHeight(): Int {
|
||||
return naviHeight
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
lifecycleScope.launch {
|
||||
webService.update(bridge)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.affine.pro.plugin
|
||||
|
||||
import com.getcapacitor.JSObject
|
||||
import com.getcapacitor.Plugin
|
||||
import com.getcapacitor.PluginCall
|
||||
import com.getcapacitor.PluginMethod
|
||||
@@ -11,6 +12,7 @@ class AffineThemePlugin : Plugin() {
|
||||
|
||||
interface Callback {
|
||||
fun onThemeChanged(darkMode: Boolean)
|
||||
fun getSystemNaviBarHeight(): Int
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
@@ -20,4 +22,10 @@ class AffineThemePlugin : Plugin() {
|
||||
(bridge.activity as? Callback)?.onThemeChanged(darkMode)
|
||||
call.resolve()
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
fun getSystemNaviBarHeight(call: PluginCall) {
|
||||
val height = (bridge.activity as? Callback)?.getSystemNaviBarHeight() ?: 0
|
||||
call.resolve(JSObject().put("height", height))
|
||||
}
|
||||
}
|
||||
@@ -1303,6 +1303,70 @@ inline fun <T : Disposable?, R> T.use(block: (T) -> R) =
|
||||
* @suppress
|
||||
* */
|
||||
object NoPointer
|
||||
/**
|
||||
* The cleaner interface for Object finalization code to run.
|
||||
* This is the entry point to any implementation that we're using.
|
||||
*
|
||||
* The cleaner registers objects and returns cleanables, so now we are
|
||||
* defining a `UniffiCleaner` with a `UniffiClenaer.Cleanable` to abstract the
|
||||
* different implmentations available at compile time.
|
||||
*
|
||||
* @suppress
|
||||
*/
|
||||
interface UniffiCleaner {
|
||||
interface Cleanable {
|
||||
fun clean()
|
||||
}
|
||||
|
||||
fun register(value: Any, cleanUpTask: Runnable): UniffiCleaner.Cleanable
|
||||
|
||||
companion object
|
||||
}
|
||||
|
||||
// The fallback Jna cleaner, which is available for both Android, and the JVM.
|
||||
private class UniffiJnaCleaner : UniffiCleaner {
|
||||
private val cleaner = com.sun.jna.internal.Cleaner.getCleaner()
|
||||
|
||||
override fun register(value: Any, cleanUpTask: Runnable): UniffiCleaner.Cleanable =
|
||||
UniffiJnaCleanable(cleaner.register(value, cleanUpTask))
|
||||
}
|
||||
|
||||
private class UniffiJnaCleanable(
|
||||
private val cleanable: com.sun.jna.internal.Cleaner.Cleanable,
|
||||
) : UniffiCleaner.Cleanable {
|
||||
override fun clean() = cleanable.clean()
|
||||
}
|
||||
|
||||
|
||||
// We decide at uniffi binding generation time whether we were
|
||||
// using Android or not.
|
||||
// There are further runtime checks to chose the correct implementation
|
||||
// of the cleaner.
|
||||
private fun UniffiCleaner.Companion.create(): UniffiCleaner =
|
||||
try {
|
||||
// For safety's sake: if the library hasn't been run in android_cleaner = true
|
||||
// mode, but is being run on Android, then we still need to think about
|
||||
// Android API versions.
|
||||
// So we check if java.lang.ref.Cleaner is there, and use that…
|
||||
java.lang.Class.forName("java.lang.ref.Cleaner")
|
||||
JavaLangRefCleaner()
|
||||
} catch (e: ClassNotFoundException) {
|
||||
// … otherwise, fallback to the JNA cleaner.
|
||||
UniffiJnaCleaner()
|
||||
}
|
||||
|
||||
private class JavaLangRefCleaner : UniffiCleaner {
|
||||
val cleaner = java.lang.ref.Cleaner.create()
|
||||
|
||||
override fun register(value: Any, cleanUpTask: Runnable): UniffiCleaner.Cleanable =
|
||||
JavaLangRefCleanable(cleaner.register(value, cleanUpTask))
|
||||
}
|
||||
|
||||
private class JavaLangRefCleanable(
|
||||
val cleanable: java.lang.ref.Cleaner.Cleanable
|
||||
) : UniffiCleaner.Cleanable {
|
||||
override fun clean() = cleanable.clean()
|
||||
}
|
||||
|
||||
/**
|
||||
* @suppress
|
||||
@@ -1529,70 +1593,6 @@ public object FfiConverterString: FfiConverter<String, RustBuffer.ByValue> {
|
||||
//
|
||||
|
||||
|
||||
/**
|
||||
* The cleaner interface for Object finalization code to run.
|
||||
* This is the entry point to any implementation that we're using.
|
||||
*
|
||||
* The cleaner registers objects and returns cleanables, so now we are
|
||||
* defining a `UniffiCleaner` with a `UniffiClenaer.Cleanable` to abstract the
|
||||
* different implmentations available at compile time.
|
||||
*
|
||||
* @suppress
|
||||
*/
|
||||
interface UniffiCleaner {
|
||||
interface Cleanable {
|
||||
fun clean()
|
||||
}
|
||||
|
||||
fun register(value: Any, cleanUpTask: Runnable): UniffiCleaner.Cleanable
|
||||
|
||||
companion object
|
||||
}
|
||||
|
||||
// The fallback Jna cleaner, which is available for both Android, and the JVM.
|
||||
private class UniffiJnaCleaner : UniffiCleaner {
|
||||
private val cleaner = com.sun.jna.internal.Cleaner.getCleaner()
|
||||
|
||||
override fun register(value: Any, cleanUpTask: Runnable): UniffiCleaner.Cleanable =
|
||||
UniffiJnaCleanable(cleaner.register(value, cleanUpTask))
|
||||
}
|
||||
|
||||
private class UniffiJnaCleanable(
|
||||
private val cleanable: com.sun.jna.internal.Cleaner.Cleanable,
|
||||
) : UniffiCleaner.Cleanable {
|
||||
override fun clean() = cleanable.clean()
|
||||
}
|
||||
|
||||
|
||||
// We decide at uniffi binding generation time whether we were
|
||||
// using Android or not.
|
||||
// There are further runtime checks to chose the correct implementation
|
||||
// of the cleaner.
|
||||
private fun UniffiCleaner.Companion.create(): UniffiCleaner =
|
||||
try {
|
||||
// For safety's sake: if the library hasn't been run in android_cleaner = true
|
||||
// mode, but is being run on Android, then we still need to think about
|
||||
// Android API versions.
|
||||
// So we check if java.lang.ref.Cleaner is there, and use that…
|
||||
java.lang.Class.forName("java.lang.ref.Cleaner")
|
||||
JavaLangRefCleaner()
|
||||
} catch (e: ClassNotFoundException) {
|
||||
// … otherwise, fallback to the JNA cleaner.
|
||||
UniffiJnaCleaner()
|
||||
}
|
||||
|
||||
private class JavaLangRefCleaner : UniffiCleaner {
|
||||
val cleaner = java.lang.ref.Cleaner.create()
|
||||
|
||||
override fun register(value: Any, cleanUpTask: Runnable): UniffiCleaner.Cleanable =
|
||||
JavaLangRefCleanable(cleaner.register(value, cleanUpTask))
|
||||
}
|
||||
|
||||
private class JavaLangRefCleanable(
|
||||
val cleanable: java.lang.ref.Cleaner.Cleanable
|
||||
) : UniffiCleaner.Cleanable {
|
||||
override fun clean() = cleanable.clean()
|
||||
}
|
||||
public interface DocStoragePoolInterface {
|
||||
|
||||
suspend fun `clearClocks`(`universalId`: kotlin.String)
|
||||
|
||||
@@ -11,8 +11,5 @@ project(':capacitor-keyboard').projectDir = new File('../../../../../node_module
|
||||
include ':capacitor-status-bar'
|
||||
project(':capacitor-status-bar').projectDir = new File('../../../../../node_modules/@capacitor/status-bar/android')
|
||||
|
||||
include ':capawesome-capacitor-android-edge-to-edge-support'
|
||||
project(':capawesome-capacitor-android-edge-to-edge-support').projectDir = new File('../../../../../node_modules/@capawesome/capacitor-android-edge-to-edge-support/android')
|
||||
|
||||
include ':capgo-inappbrowser'
|
||||
project(':capgo-inappbrowser').projectDir = new File('../../../../../node_modules/@capgo/inappbrowser/android')
|
||||
|
||||
@@ -25,6 +25,7 @@ const config: CapacitorConfig & AppConfig = {
|
||||
keystoreAliasPassword: process.env.AFFINE_ANDROID_KEYSTORE_ALIAS_PASSWORD,
|
||||
releaseType: 'AAB',
|
||||
},
|
||||
adjustMarginsForEdgeToEdge: 'force',
|
||||
},
|
||||
server: {
|
||||
cleartext: true,
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
"@capacitor/core": "^7.0.0",
|
||||
"@capacitor/keyboard": "^7.0.0",
|
||||
"@capacitor/status-bar": "^7.0.0",
|
||||
"@capawesome/capacitor-android-edge-to-edge-support": "^7.0.0",
|
||||
"@capgo/inappbrowser": "^7.1.0",
|
||||
"@sentry/react": "^9.2.0",
|
||||
"@toeverything/infra": "workspace:*",
|
||||
|
||||
@@ -40,7 +40,6 @@ import {
|
||||
import { App as CapacitorApp } from '@capacitor/app';
|
||||
import { Keyboard } from '@capacitor/keyboard';
|
||||
import { StatusBar, Style } from '@capacitor/status-bar';
|
||||
import { EdgeToEdge } from '@capawesome/capacitor-android-edge-to-edge-support';
|
||||
import { InAppBrowser } from '@capgo/inappbrowser';
|
||||
import { Framework, FrameworkRoot, getCurrentStore } from '@toeverything/infra';
|
||||
import { OpClient } from '@toeverything/infra/op';
|
||||
@@ -329,9 +328,6 @@ const ThemeProvider = () => {
|
||||
? Style.Light
|
||||
: Style.Default,
|
||||
}).catch(console.error);
|
||||
EdgeToEdge.setBackgroundColor({
|
||||
color: resolvedTheme === 'dark' ? '#000000' : '#F5F5F5',
|
||||
}).catch(console.error);
|
||||
AffineTheme.onThemeChanged({
|
||||
darkMode: resolvedTheme === 'dark',
|
||||
}).catch(console.error);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export interface AffineThemePlugin {
|
||||
onThemeChanged(options: { darkMode: boolean }): Promise<void>;
|
||||
getSystemNaviBarHeight(): Promise<{ height: number }>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user