Skip to content

Commit

Permalink
Merge branch 'dev' into fix-context-menu-on-ios
Browse files Browse the repository at this point in the history
  • Loading branch information
lgmarchi authored Dec 13, 2024
2 parents 17e046b + 2ae2301 commit ed3b376
Show file tree
Hide file tree
Showing 18 changed files with 221 additions and 64 deletions.
1 change: 1 addition & 0 deletions android/app/capacitor.build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies {
implementation project(':capacitor-keyboard')
implementation project(':capacitor-screen-orientation')
implementation project(':capacitor-splash-screen')
implementation project(':capacitor-status-bar')
}


Expand Down
3 changes: 3 additions & 0 deletions android/capacitor.settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ project(':capacitor-screen-orientation').projectDir = new File('../node_modules/

include ':capacitor-splash-screen'
project(':capacitor-splash-screen').projectDir = new File('../node_modules/@capacitor/splash-screen/android')

include ':capacitor-status-bar'
project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android')
4 changes: 4 additions & 0 deletions ios/App/App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; };
50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
56524E4F2CE8119000C237C2 /* PluginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56524E4E2CE8119000C237C2 /* PluginViewController.swift */; };
567DF60B2D0784C1003BA7AC /* PluginSafeAreasColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 567DF60A2D0784C1003BA7AC /* PluginSafeAreasColor.swift */; };
A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */; };
/* End PBXBuildFile section */

Expand All @@ -29,6 +30,7 @@
504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
56524E4E2CE8119000C237C2 /* PluginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginViewController.swift; sourceTree = "<group>"; };
567DF60A2D0784C1003BA7AC /* PluginSafeAreasColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PluginSafeAreasColor.swift; path = App/PluginSafeAreasColor.swift; sourceTree = "<group>"; };
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -57,6 +59,7 @@
504EC2FB1FED79650016851F = {
isa = PBXGroup;
children = (
567DF60A2D0784C1003BA7AC /* PluginSafeAreasColor.swift */,
56524E4E2CE8119000C237C2 /* PluginViewController.swift */,
504EC3061FED79650016851F /* App */,
504EC3051FED79650016851F /* Products */,
Expand Down Expand Up @@ -213,6 +216,7 @@
buildActionMask = 2147483647;
files = (
504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
567DF60B2D0784C1003BA7AC /* PluginSafeAreasColor.swift in Sources */,
56524E4F2CE8119000C237C2 /* PluginViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
72 changes: 72 additions & 0 deletions ios/App/App/PluginSafeAreasColor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import Capacitor
import UIKit

@objc(SafeAreasColorPlugin)
public class SafeAreasColorPlugin: CAPPlugin, CAPBridgedPlugin {
public let identifier = "SafeAreasColorPlugin"
public let jsName = "SafeAreasColor"
public let pluginMethods: [CAPPluginMethod] = [
CAPPluginMethod(name: "changeSafeAreasColorOniOS", returnType: CAPPluginReturnPromise)
]

@objc func changeSafeAreasColorOniOS(_ call: CAPPluginCall) {
let value = call.getString("color") ?? ""
guard let uiColor = UIColor(hex: value) else {
call.reject("Invalid color format")
return
}

DispatchQueue.main.async {
if #available(iOS 16.0, *) {
// Find the active window in iOS 13 or later
if let window = UIApplication.shared.connectedScenes
.compactMap({ $0 as? UIWindowScene })
.flatMap({ $0.windows })
.first(where: { $0.isKeyWindow }) {

window.backgroundColor = uiColor // Set the background color
call.resolve(["value": "Color set successfully"])
} else {
call.reject("No active window found")
}
} else {
call.reject("Earlier versions than iOS 16 are not supported")
}
}

call.resolve(["value": value])
}
}

extension UIColor {
convenience init?(hex: String) {
var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()

if hexSanitized.hasPrefix("#") {
hexSanitized.remove(at: hexSanitized.startIndex)
}

var rgb: UInt64 = 0
guard Scanner(string: hexSanitized).scanHexInt64(&rgb) else { return nil }

let length = hexSanitized.count
switch length {
case 6: // RGB
self.init(
red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0,
green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0,
blue: CGFloat(rgb & 0x0000FF) / 255.0,
alpha: 1.0
)
case 8: // RGBA
self.init(
red: CGFloat((rgb & 0xFF000000) >> 24) / 255.0,
green: CGFloat((rgb & 0x00FF0000) >> 16) / 255.0,
blue: CGFloat((rgb & 0x0000FF00) >> 8) / 255.0,
alpha: CGFloat(rgb & 0x000000FF) / 255.0
)
default:
return nil
}
}
}
14 changes: 8 additions & 6 deletions ios/App/PluginViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import UIKit
import Capacitor

class PluginViewController: CAPBridgeViewController {
override open func capacitorDidLoad() {
bridge?.registerPluginInstance(SafeAreasColorPlugin())
}

override open func viewDidLoad() {
super.viewDidLoad()

Expand Down Expand Up @@ -35,17 +39,15 @@ class PluginViewController: CAPBridgeViewController {
var leftPadding: CGFloat = 0
var rightPadding: CGFloat = 0

if #available(iOS 13.0, *) {
if #available(iOS 16.0, *) {
let window = view.window ?? UIApplication.shared.windows.first { $0.isKeyWindow }
topPadding = window?.safeAreaInsets.top ?? 0
bottomPadding = window?.safeAreaInsets.bottom ?? 0
leftPadding = window?.safeAreaInsets.left ?? 0
rightPadding = window?.safeAreaInsets.right ?? 0
} else {
topPadding = UIApplication.shared.statusBarFrame.height
}

webView.frame.origin = CGPoint(x: leftPadding, y: topPadding)
webView.frame.size = CGSize(width: UIScreen.main.bounds.width - leftPadding - rightPadding, height: UIScreen.main.bounds.height - topPadding - bottomPadding)
webView.frame.origin = CGPoint(x: leftPadding, y: topPadding)
webView.frame.size = CGSize(width: UIScreen.main.bounds.width - leftPadding - rightPadding, height: UIScreen.main.bounds.height - topPadding - bottomPadding)
}
}
}
1 change: 1 addition & 0 deletions ios/App/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def capacitor_pods
pod 'CapacitorKeyboard', :path => '../../node_modules/@capacitor/keyboard'
pod 'CapacitorScreenOrientation', :path => '../../node_modules/@capacitor/screen-orientation'
pod 'CapacitorSplashScreen', :path => '../../node_modules/@capacitor/splash-screen'
pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
end

target 'App' do
Expand Down
12 changes: 9 additions & 3 deletions ios/App/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ PODS:
- Capacitor
- CapacitorScreenOrientation (6.0.3):
- Capacitor
- CapacitorSplashScreen (6.0.2):
- CapacitorSplashScreen (6.0.3):
- Capacitor
- CapacitorStatusBar (6.0.2):
- Capacitor

DEPENDENCIES:
Expand All @@ -27,6 +29,7 @@ DEPENDENCIES:
- "CapacitorKeyboard (from `../../node_modules/@capacitor/keyboard`)"
- "CapacitorScreenOrientation (from `../../node_modules/@capacitor/screen-orientation`)"
- "CapacitorSplashScreen (from `../../node_modules/@capacitor/splash-screen`)"
- "CapacitorStatusBar (from `../../node_modules/@capacitor/status-bar`)"

EXTERNAL SOURCES:
Capacitor:
Expand All @@ -47,6 +50,8 @@ EXTERNAL SOURCES:
:path: "../../node_modules/@capacitor/screen-orientation"
CapacitorSplashScreen:
:path: "../../node_modules/@capacitor/splash-screen"
CapacitorStatusBar:
:path: "../../node_modules/@capacitor/status-bar"

SPEC CHECKSUMS:
Capacitor: 1f3c7b9802d958cd8c4eb63895fff85dff2e1eea
Expand All @@ -57,8 +62,9 @@ SPEC CHECKSUMS:
CapacitorFilesystem: c832a3f6d4870c3872688e782ae8e33665e6ecbf
CapacitorKeyboard: 460c6f9ec5e52c84f2742d5ce2e67bbc7ab0ebb0
CapacitorScreenOrientation: 3bb823f5d265190301cdc5d58a568a287d98972a
CapacitorSplashScreen: 250df9ef8014fac5c7c1fd231f0f8b1d8f0b5624
CapacitorSplashScreen: 68893659d77b5f82d753b3a70475082845e3039c
CapacitorStatusBar: 3b9ac7d0684770522c532d1158a1434512ab1477

PODFILE CHECKSUM: 0bfaa008b5f31bb57606a8c6259197a6af507ba4
PODFILE CHECKSUM: 97c46b79f9ec807c302bf24e1511e3e277306740

COCOAPODS: 1.16.2
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@capacitor/keyboard": "^6.0.3",
"@capacitor/screen-orientation": "^6.0.3",
"@capacitor/splash-screen": "^6.0.2",
"@capacitor/status-bar": "^6.0.2",
"@dicebear/collection": "^9.0.1",
"@dicebear/core": "^9.0.1",
"@dicebear/identicon": "^9.0.1",
Expand Down
6 changes: 5 additions & 1 deletion src/lib/enums/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export const enum EmojiFont {
Fluent = "Fluent",
}

export const enum Route {
export enum Route {
Home = "/",
Chat = "/chat",
Files = "/files",
Expand All @@ -101,6 +101,10 @@ export const enum Route {
Pre = "/pre",
}

export function getRoute(value: string): Route {
return value.startsWith("/settings") ? Route.Settings : Object.values(Route).find(route => route === value) || Route.Home
}

export const enum FilesItemKind {
File,
Folder,
Expand Down
67 changes: 46 additions & 21 deletions src/lib/layouts/BottomNavBarMobile.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script lang="ts">
import { Keyboard } from "@capacitor/keyboard"
import { page } from "$app/stores"
import { Button, Icon, Text } from "$lib/elements"
import { Appearance, CommunitySettingsRoute, Route, SettingsRoute } from "$lib/enums"
import { VoiceRTCInstance } from "$lib/media/Voice"
Expand All @@ -9,7 +11,7 @@
import { checkMobile, isAndroidOriOS } from "$lib/utils/Mobile"
import { createEventDispatcher, onDestroy, onMount } from "svelte"
import { get } from "svelte/store"
import { Keyboard } from "@capacitor/keyboard"
import { afterNavigate, onNavigate } from "$app/navigation"
import type { PluginListenerHandle } from "@capacitor/core"
export let routes: NavRoute[] = []
Expand Down Expand Up @@ -58,7 +60,6 @@
// Avoid keyboard when navigate to chat preview list
}
}
dispatch("navigate", route.to.toString())
}
Expand All @@ -69,18 +70,50 @@
if (route.to === Route.Settings) return true
}
UIStore.state.sidebarOpen.subscribe(open => {
showBottomNavBar = checkIfCanShowBottomNavBar(open, null, false)
})
onNavigate(async e => {
const routeId = e.to?.route.id
showBottomNavBar = checkIfCanShowBottomNavBar(get(UIStore.state.sidebarOpen), routeId, false)
})
function checkIfCanShowBottomNavBar(sidebarOpen: boolean, routeId: string | null | undefined, isMobileKeyboardOpened: boolean): boolean {
let currentRoute = routeId ?? $page.route.id
if (isAndroidOriOS() && !isMobileKeyboardOpened) {
if (currentRoute === "/chat" && sidebarOpen) {
return true
}
if (currentRoute === "/friends") {
return true
}
if (currentRoute?.includes("/settings")) {
return true
}
if (currentRoute === "/files") {
return true
}
}
return false
}
$: showBottomNavBar = checkIfCanShowBottomNavBar(get(UIStore.state.sidebarOpen), null, false)
let mobileKeyboardListener01: PluginListenerHandle | undefined
let mobileKeyboardListener02: PluginListenerHandle | undefined
$: isKeyboardOpened = false
onMount(async () => {
mobileKeyboardListener01 = await Keyboard.addListener("keyboardWillShow", () => {
isKeyboardOpened = true
})
mobileKeyboardListener02 = await Keyboard.addListener("keyboardWillHide", () => {
isKeyboardOpened = false
})
if (isAndroidOriOS()) {
mobileKeyboardListener01 = await Keyboard.addListener("keyboardWillShow", () => {
showBottomNavBar = checkIfCanShowBottomNavBar(get(UIStore.state.sidebarOpen), null, true)
})
mobileKeyboardListener02 = await Keyboard.addListener("keyboardWillHide", () => {
showBottomNavBar = checkIfCanShowBottomNavBar(get(UIStore.state.sidebarOpen), null, false)
})
}
})
// Clean up subscriptions when component is destroyed
Expand All @@ -99,10 +132,8 @@
$: settings = SettingsStore.state
</script>

{#if !isKeyboardOpened}
<div class="content"></div>

<div class="navigation {vertical ? 'vertical' : 'horizontal'} {icons ? 'icons' : ''}">
{#if showBottomNavBar}
<div id="bottom-nav-bar-mobile" class="navigation {vertical ? 'vertical' : 'horizontal'} {icons ? 'icons' : ''}">
{#each routes as route}
<div class="navigation-control {!icons ? 'fill' : ''}">
<Button
Expand All @@ -125,12 +156,6 @@
{/if}

<style lang="scss">
.content {
height: 60px;
pointer-events: none;
background: transparent;
border: none;
}
.navigation {
display: inline-flex;
gap: var(--gap);
Expand All @@ -141,7 +166,7 @@
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
z-index: 1000;
position: fixed;
position: sticky;
bottom: 0;
left: 0;
right: 0;
Expand Down
11 changes: 11 additions & 0 deletions src/lib/plugins/safeAreaColorAndroid.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { log } from "$lib/utils/Logger"
import { registerPlugin } from "@capacitor/core"
import { StatusBar, Style } from "@capacitor/status-bar"

interface ISafeAreaColorPlugin {
setStatusBarColor(options: { color: string }): Promise<{ value: string }>
Expand All @@ -11,6 +12,16 @@ const SafeAreaColorPlugin = registerPlugin<ISafeAreaColorPlugin>("SafeAreaColorP
async function setStatusBarColor(color: string) {
try {
log.info("Calling native android function to change status bar color")
if (color.toLowerCase() === "white") {
color = "#FFFFFF"
log.info(`Converted color "white" to hexadecimal: ${color}`)
await StatusBar.setStyle({ style: Style.Light })
log.debug("Change status bar style to light")
} else {
await StatusBar.setStyle({ style: Style.Dark })
log.debug("Change status bar style to dark")
}

await SafeAreaColorPlugin.setStatusBarColor({ color })
} catch (error) {
log.error("Error setting status bar color:", error)
Expand Down
Loading

0 comments on commit ed3b376

Please sign in to comment.