Compare commits

...

6 Commits

9 changed files with 59 additions and 14 deletions
+1
View File
@@ -11,6 +11,7 @@ apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
dependencies {
implementation project(':capacitor-app')
implementation project(':capacitor-filesystem')
implementation project(':capacitor-keyboard')
implementation project(':capacitor-local-notifications')
implementation project(':capacitor-share')
implementation project(':capacitor-status-bar')
+3
View File
@@ -8,6 +8,9 @@ project(':capacitor-app').projectDir = new File('../node_modules/@capacitor/app/
include ':capacitor-filesystem'
project(':capacitor-filesystem').projectDir = new File('../node_modules/@capacitor/filesystem/android')
include ':capacitor-keyboard'
project(':capacitor-keyboard').projectDir = new File('../node_modules/@capacitor/keyboard/android')
include ':capacitor-local-notifications'
project(':capacitor-local-notifications').projectDir = new File('../node_modules/@capacitor/local-notifications/android')
+6 -1
View File
@@ -19,7 +19,12 @@ const config: CapacitorConfig = {
backgroundColor: '#14161f',
contentInset: 'never',
scheme: 'Ditto'
}
},
plugins: {
Keyboard: {
resizeOnFullScreen: true,
},
},
};
export default config;
+2
View File
@@ -14,6 +14,7 @@ let package = Package(
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "8.2.0"),
.package(name: "CapacitorApp", path: "../../../node_modules/@capacitor/app"),
.package(name: "CapacitorFilesystem", path: "../../../node_modules/@capacitor/filesystem"),
.package(name: "CapacitorKeyboard", path: "../../../node_modules/@capacitor/keyboard"),
.package(name: "CapacitorLocalNotifications", path: "../../../node_modules/@capacitor/local-notifications"),
.package(name: "CapacitorShare", path: "../../../node_modules/@capacitor/share"),
.package(name: "CapacitorStatusBar", path: "../../../node_modules/@capacitor/status-bar")
@@ -26,6 +27,7 @@ let package = Package(
.product(name: "Cordova", package: "capacitor-swift-pm"),
.product(name: "CapacitorApp", package: "CapacitorApp"),
.product(name: "CapacitorFilesystem", package: "CapacitorFilesystem"),
.product(name: "CapacitorKeyboard", package: "CapacitorKeyboard"),
.product(name: "CapacitorLocalNotifications", package: "CapacitorLocalNotifications"),
.product(name: "CapacitorShare", package: "CapacitorShare"),
.product(name: "CapacitorStatusBar", package: "CapacitorStatusBar")
+10
View File
@@ -11,6 +11,7 @@
"@capacitor/app": "^8.0.0",
"@capacitor/core": "^8.1.0",
"@capacitor/filesystem": "^8.1.2",
"@capacitor/keyboard": "^8.0.2",
"@capacitor/local-notifications": "^8.0.1",
"@capacitor/share": "^8.0.1",
"@capacitor/status-bar": "^8.0.0",
@@ -379,6 +380,15 @@
"@capacitor/core": "^8.2.0"
}
},
"node_modules/@capacitor/keyboard": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@capacitor/keyboard/-/keyboard-8.0.2.tgz",
"integrity": "sha512-he6xKmTBp5AhVrWJeEi6RYkJ25FjLLdNruBU2wafpITk3Nb7UdzOj96x3K6etFuEj8/rtn9WXBTs1o2XA86A1A==",
"license": "MIT",
"peerDependencies": {
"@capacitor/core": ">=8.0.0"
}
},
"node_modules/@capacitor/local-notifications": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/@capacitor/local-notifications/-/local-notifications-8.0.1.tgz",
+1
View File
@@ -18,6 +18,7 @@
"@capacitor/app": "^8.0.0",
"@capacitor/core": "^8.1.0",
"@capacitor/filesystem": "^8.1.2",
"@capacitor/keyboard": "^8.0.2",
"@capacitor/local-notifications": "^8.0.1",
"@capacitor/share": "^8.0.1",
"@capacitor/status-bar": "^8.0.0",
+2 -2
View File
@@ -40,8 +40,8 @@ export function MobileBottomNav() {
setSearchOpen((v) => !v);
}, []);
// Keep the nav visible while search is open regardless of scroll
const isHidden = hidden && !searchOpen;
// Hide the nav when search sheet is open so it doesn't compete for space
const isHidden = hidden || searchOpen;
const displayName = metadata?.name || metadata?.display_name;
const isOnProfile = user && location.pathname === profileUrl;
+31 -11
View File
@@ -101,6 +101,28 @@ export function MobileSearchSheet({ open, onClose }: MobileSearchSheetProps) {
const wikipediaIndex = hasWikipedia ? nextMobileIdx++ : -1;
const archiveIndex = hasArchive ? nextMobileIdx++ : -1;
// Lock body scroll while the search sheet is open.
// overflow:hidden alone is unreliable on mobile Safari, so we also
// block touchmove on the document (except inside the results scroller).
useEffect(() => {
if (!open) return;
const prevOverflow = document.body.style.overflow;
document.body.style.overflow = 'hidden';
const preventScroll = (e: TouchEvent) => {
// Allow scrolling inside the results list
const target = e.target as HTMLElement;
if (target.closest?.('[data-mobile-search-results]')) return;
e.preventDefault();
};
document.addEventListener('touchmove', preventScroll, { passive: false });
return () => {
document.body.style.overflow = prevOverflow;
document.removeEventListener('touchmove', preventScroll);
};
}, [open]);
// Focus input when opened
useEffect(() => {
if (open) {
@@ -224,8 +246,8 @@ export function MobileSearchSheet({ open, onClose }: MobileSearchSheetProps) {
onClick={handleClose}
/>
{/* Bottom sheet — sits above the bottom nav bar */}
<div className="fixed left-0 right-0 z-[49] sidebar:hidden animate-in slide-in-from-bottom-4 duration-200 bottom-mobile-nav">
{/* Bottom sheet — sits at the bottom of the screen with safe area clearance */}
<div className="fixed left-0 right-0 bottom-0 z-[49] sidebar:hidden animate-in slide-in-from-bottom-4 duration-200 pb-6">
{/* Results list — reversed so closest to input = most relevant */}
{hasResults && (
@@ -293,7 +315,7 @@ export function MobileSearchSheet({ open, onClose }: MobileSearchSheetProps) {
)}
{/* Input bar */}
<div className="flex items-center px-6 py-3">
<div className="flex items-center px-6 py-3 safe-area-bottom">
<div className="flex items-center gap-2 flex-1 bg-secondary rounded-full px-4 py-2.5">
{isFetching ? (
<svg
@@ -321,14 +343,12 @@ export function MobileSearchSheet({ open, onClose }: MobileSearchSheetProps) {
autoCapitalize="off"
spellCheck={false}
/>
{query.length > 0 && (
<button
onClick={() => setQuery('')}
className="size-5 shrink-0 flex items-center justify-center rounded-full bg-muted text-muted-foreground hover:bg-muted/80 transition-colors"
>
<X strokeWidth={4} className="size-3" />
</button>
)}
<button
onClick={handleClose}
className="size-5 shrink-0 flex items-center justify-center rounded-full bg-muted text-muted-foreground hover:bg-muted/80 transition-colors"
>
<X strokeWidth={4} className="size-3" />
</button>
</div>
</div>
</div>
+3
View File
@@ -22,9 +22,12 @@ import '@fontsource-variable/inter';
// (class changes for builtin themes, style-content changes for custom themes).
import { Capacitor } from '@capacitor/core';
import { StatusBar, Style } from '@capacitor/status-bar';
import { Keyboard } from '@capacitor/keyboard';
import { getBackgroundThemeMode, getBackgroundHex } from '@/lib/colorUtils';
if (Capacitor.isNativePlatform()) {
// Hide the iOS keyboard accessory bar (prev/next/done toolbar above the keyboard)
Keyboard.setAccessoryBarVisible({ isVisible: false }).catch(() => {});
/**
* Read --background from the computed style of <html>, convert the HSL
* value to a hex color, and update the native status bar to match.