mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 12:28:42 +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-app')
|
||||||
implementation project(':capacitor-keyboard')
|
implementation project(':capacitor-keyboard')
|
||||||
implementation project(':capacitor-status-bar')
|
implementation project(':capacitor-status-bar')
|
||||||
implementation project(':capawesome-capacitor-android-edge-to-edge-support')
|
|
||||||
implementation project(':capgo-inappbrowser')
|
implementation project(':capgo-inappbrowser')
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package app.affine.pro
|
package app.affine.pro
|
||||||
|
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
|
import android.os.Bundle
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.updateMargins
|
import androidx.core.view.updateMargins
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import app.affine.pro.ai.AIActivity
|
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() {
|
override fun load() {
|
||||||
super.load()
|
super.load()
|
||||||
AuthInitializer.initialize(bridge)
|
AuthInitializer.initialize(bridge)
|
||||||
@@ -96,6 +109,10 @@ class MainActivity : BridgeActivity(), AIButtonPlugin.Callback, AffineThemePlugi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getSystemNaviBarHeight(): Int {
|
||||||
|
return naviHeight
|
||||||
|
}
|
||||||
|
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
webService.update(bridge)
|
webService.update(bridge)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package app.affine.pro.plugin
|
package app.affine.pro.plugin
|
||||||
|
|
||||||
|
import com.getcapacitor.JSObject
|
||||||
import com.getcapacitor.Plugin
|
import com.getcapacitor.Plugin
|
||||||
import com.getcapacitor.PluginCall
|
import com.getcapacitor.PluginCall
|
||||||
import com.getcapacitor.PluginMethod
|
import com.getcapacitor.PluginMethod
|
||||||
@@ -11,6 +12,7 @@ class AffineThemePlugin : Plugin() {
|
|||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
fun onThemeChanged(darkMode: Boolean)
|
fun onThemeChanged(darkMode: Boolean)
|
||||||
|
fun getSystemNaviBarHeight(): Int
|
||||||
}
|
}
|
||||||
|
|
||||||
@PluginMethod
|
@PluginMethod
|
||||||
@@ -20,4 +22,10 @@ class AffineThemePlugin : Plugin() {
|
|||||||
(bridge.activity as? Callback)?.onThemeChanged(darkMode)
|
(bridge.activity as? Callback)?.onThemeChanged(darkMode)
|
||||||
call.resolve()
|
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
|
* @suppress
|
||||||
* */
|
* */
|
||||||
object NoPointer
|
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
|
* @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 {
|
public interface DocStoragePoolInterface {
|
||||||
|
|
||||||
suspend fun `clearClocks`(`universalId`: kotlin.String)
|
suspend fun `clearClocks`(`universalId`: kotlin.String)
|
||||||
|
|||||||
@@ -11,8 +11,5 @@ project(':capacitor-keyboard').projectDir = new File('../../../../../node_module
|
|||||||
include ':capacitor-status-bar'
|
include ':capacitor-status-bar'
|
||||||
project(':capacitor-status-bar').projectDir = new File('../../../../../node_modules/@capacitor/status-bar/android')
|
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'
|
include ':capgo-inappbrowser'
|
||||||
project(':capgo-inappbrowser').projectDir = new File('../../../../../node_modules/@capgo/inappbrowser/android')
|
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,
|
keystoreAliasPassword: process.env.AFFINE_ANDROID_KEYSTORE_ALIAS_PASSWORD,
|
||||||
releaseType: 'AAB',
|
releaseType: 'AAB',
|
||||||
},
|
},
|
||||||
|
adjustMarginsForEdgeToEdge: 'force',
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
cleartext: true,
|
cleartext: true,
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
"@capacitor/core": "^7.0.0",
|
"@capacitor/core": "^7.0.0",
|
||||||
"@capacitor/keyboard": "^7.0.0",
|
"@capacitor/keyboard": "^7.0.0",
|
||||||
"@capacitor/status-bar": "^7.0.0",
|
"@capacitor/status-bar": "^7.0.0",
|
||||||
"@capawesome/capacitor-android-edge-to-edge-support": "^7.0.0",
|
|
||||||
"@capgo/inappbrowser": "^7.1.0",
|
"@capgo/inappbrowser": "^7.1.0",
|
||||||
"@sentry/react": "^9.2.0",
|
"@sentry/react": "^9.2.0",
|
||||||
"@toeverything/infra": "workspace:*",
|
"@toeverything/infra": "workspace:*",
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ import {
|
|||||||
import { App as CapacitorApp } from '@capacitor/app';
|
import { App as CapacitorApp } from '@capacitor/app';
|
||||||
import { Keyboard } from '@capacitor/keyboard';
|
import { Keyboard } from '@capacitor/keyboard';
|
||||||
import { StatusBar, Style } from '@capacitor/status-bar';
|
import { StatusBar, Style } from '@capacitor/status-bar';
|
||||||
import { EdgeToEdge } from '@capawesome/capacitor-android-edge-to-edge-support';
|
|
||||||
import { InAppBrowser } from '@capgo/inappbrowser';
|
import { InAppBrowser } from '@capgo/inappbrowser';
|
||||||
import { Framework, FrameworkRoot, getCurrentStore } from '@toeverything/infra';
|
import { Framework, FrameworkRoot, getCurrentStore } from '@toeverything/infra';
|
||||||
import { OpClient } from '@toeverything/infra/op';
|
import { OpClient } from '@toeverything/infra/op';
|
||||||
@@ -329,9 +328,6 @@ const ThemeProvider = () => {
|
|||||||
? Style.Light
|
? Style.Light
|
||||||
: Style.Default,
|
: Style.Default,
|
||||||
}).catch(console.error);
|
}).catch(console.error);
|
||||||
EdgeToEdge.setBackgroundColor({
|
|
||||||
color: resolvedTheme === 'dark' ? '#000000' : '#F5F5F5',
|
|
||||||
}).catch(console.error);
|
|
||||||
AffineTheme.onThemeChanged({
|
AffineTheme.onThemeChanged({
|
||||||
darkMode: resolvedTheme === 'dark',
|
darkMode: resolvedTheme === 'dark',
|
||||||
}).catch(console.error);
|
}).catch(console.error);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
export interface AffineThemePlugin {
|
export interface AffineThemePlugin {
|
||||||
onThemeChanged(options: { darkMode: boolean }): Promise<void>;
|
onThemeChanged(options: { darkMode: boolean }): Promise<void>;
|
||||||
|
getSystemNaviBarHeight(): Promise<{ height: number }>;
|
||||||
}
|
}
|
||||||
|
|||||||
10
yarn.lock
10
yarn.lock
@@ -260,7 +260,6 @@ __metadata:
|
|||||||
"@capacitor/core": "npm:^7.0.0"
|
"@capacitor/core": "npm:^7.0.0"
|
||||||
"@capacitor/keyboard": "npm:^7.0.0"
|
"@capacitor/keyboard": "npm:^7.0.0"
|
||||||
"@capacitor/status-bar": "npm:^7.0.0"
|
"@capacitor/status-bar": "npm:^7.0.0"
|
||||||
"@capawesome/capacitor-android-edge-to-edge-support": "npm:^7.0.0"
|
|
||||||
"@capgo/inappbrowser": "npm:^7.1.0"
|
"@capgo/inappbrowser": "npm:^7.1.0"
|
||||||
"@sentry/react": "npm:^9.2.0"
|
"@sentry/react": "npm:^9.2.0"
|
||||||
"@toeverything/infra": "workspace:*"
|
"@toeverything/infra": "workspace:*"
|
||||||
@@ -4527,15 +4526,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@capawesome/capacitor-android-edge-to-edge-support@npm:^7.0.0":
|
|
||||||
version: 7.2.1
|
|
||||||
resolution: "@capawesome/capacitor-android-edge-to-edge-support@npm:7.2.1"
|
|
||||||
peerDependencies:
|
|
||||||
"@capacitor/core": ">=7.0.0"
|
|
||||||
checksum: 10/6d84de3a7e8bc6dcd11809b00a295cc7269963e695b73ca036fbc7a60688cdbf8835a6e811709aeeb0cf15c8c1ac10f0ff597dee673a7597864aadafb879ca2e
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@capgo/inappbrowser@npm:^7.1.0":
|
"@capgo/inappbrowser@npm:^7.1.0":
|
||||||
version: 7.9.3
|
version: 7.9.3
|
||||||
resolution: "@capgo/inappbrowser@npm:7.9.3"
|
resolution: "@capgo/inappbrowser@npm:7.9.3"
|
||||||
|
|||||||
Reference in New Issue
Block a user