- App.tsx: full navigation (Auth stack + Main tabs with 5 screens) - Auth: LoginScreen, RegisterScreen, ForgotPasswordScreen - HomeScreen: dashboard with IoT metrics, weather widget, alerts, quick actions, sensors - MapScreen: interactive map with layer toggles (6 layers) - MarketplaceScreen: categories (6), products (5), search - ChatScreen: AI chat with quick prompts (4), bot responses - ProfileScreen: user info, stats, menu (9 items), logout - AlertsScreen: alert list with severity, acknowledge - SensorsScreen: sensor list with type filters (6 types), search - ZonesScreen: zone cards with stats - SettingsScreen: language picker (FR/EN/ES/DE), privacy, about - Stores: iotStore (sensors, zones, alerts), notificationStore, uiStore + i18n - Hooks: useSensors, useAlerts, useNotifications, useLocation - Components: Card, Button, LoadingSpinner, ErrorBoundary, Header - Services: iotService, notificationService (with axios API client) - Utils: formatters (temp, AQI, noise, dates), validators (email, password, IBAN) - Theme: colors.ts with full design system (Blue Ocean palette) - Ditto: fixed MongoDB connection, new JWT secrets, official gateway image
58 lines
1.6 KiB
Swift
58 lines
1.6 KiB
Swift
// Copyright 2016-present 650 Industries. All rights reserved.
|
|
|
|
extension UIImagePickerController {
|
|
func fixCannotMoveEditingBox() {
|
|
if let cropView = cropView,
|
|
let scrollView = scrollView,
|
|
scrollView.contentOffset.y == 0 {
|
|
let top = cropView.frame.minY + self.view.safeAreaInsets.top
|
|
let bottom = scrollView.frame.height - cropView.frame.height - top
|
|
scrollView.contentInset = UIEdgeInsets(top: top, left: 0, bottom: bottom, right: 0)
|
|
|
|
var offset: CGFloat = 0
|
|
if scrollView.contentSize.height > scrollView.contentSize.width {
|
|
offset = 0.5 * (scrollView.contentSize.height - scrollView.contentSize.width)
|
|
}
|
|
scrollView.contentOffset = CGPoint(x: 0, y: -top + offset)
|
|
}
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
|
|
self?.fixCannotMoveEditingBox()
|
|
}
|
|
}
|
|
|
|
var cropView: UIView? {
|
|
return findCropView(from: self.view)
|
|
}
|
|
|
|
var scrollView: UIScrollView? {
|
|
return findScrollView(from: self.view)
|
|
}
|
|
|
|
func findCropView(from view: UIView) -> UIView? {
|
|
let width = UIScreen.main.bounds.width
|
|
let size = view.bounds.size
|
|
if width == size.height, width == size.height {
|
|
return view
|
|
}
|
|
for view in view.subviews {
|
|
if let cropView = findCropView(from: view) {
|
|
return cropView
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func findScrollView(from view: UIView) -> UIScrollView? {
|
|
if let scrollView = view as? UIScrollView {
|
|
return scrollView
|
|
}
|
|
for view in view.subviews {
|
|
if let scrollView = findScrollView(from: view) {
|
|
return scrollView
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
}
|