Skip to content

Commit

Permalink
Merge branch 'main' into textInput-Reader-Accessibility
Browse files Browse the repository at this point in the history
  • Loading branch information
Umair-Manzoor-47 authored Feb 20, 2025
2 parents 5a329c0 + 0e27c2f commit 4827a68
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 12 deletions.
29 changes: 29 additions & 0 deletions modules/ensemble/lib/framework/bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ abstract class BindingSource {
String binding, DataContext dataContext) {
RegExp variableNameRegex = RegExp('^[0-9a-z_]+', caseSensitive: false);

// Check for device bindings (both patterns)
String deviceExpr = 'ensemble.device.';
if (binding.startsWith(deviceExpr)) {
// For ensemble.device.property pattern
String property = binding.substring(deviceExpr.length);
return DeviceBindingSource(property);
} else if (binding.startsWith('device.')) {
// For device.property pattern
String property = binding.substring('device.'.length);
return DeviceBindingSource(property);
}

// bindable storage
String storageExpr = 'ensemble.storage.';
String userExpr = 'ensemble.user.';
Expand Down Expand Up @@ -121,6 +133,18 @@ abstract class BindingSource {
String variable = expression.substring(2, expression.length - 1).trim();
RegExp variableNameRegex = RegExp('^[0-9a-z_]+', caseSensitive: false);

// Check for device bindings (both patterns)
String deviceExpr = 'ensemble.device.';
if (variable.startsWith(deviceExpr)) {
// For ensemble.device.property pattern
String property = variable.substring(deviceExpr.length);
return DeviceBindingSource(property);
} else if (variable.startsWith('device.')) {
// For device.property pattern
String property = variable.substring('device.'.length);
return DeviceBindingSource(property);
}

// storage bindable
String storageExpr = 'ensemble.storage.';
String userExpr = 'ensemble.user.';
Expand Down Expand Up @@ -202,6 +226,11 @@ class StorageBindingSource extends BindingSource {
StorageBindingSource(super.modelId);
}

/// bindable source backed by device
class DeviceBindingSource extends BindingSource {
DeviceBindingSource(super.modelId);
}

/// TODO: consolidate this with StorageBindingSource
class SystemStorageBindingSource extends BindingSource {
SystemStorageBindingSource(super.modelId, {required this.storagePrefix});
Expand Down
14 changes: 9 additions & 5 deletions modules/ensemble/lib/framework/data_context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,19 @@ class DataContext implements Context {
_contextMap['auth'] = GetIt.instance<AuthContextManager>();
}

_addLegacyDataContext();
_addLegacyDataContext(buildContext);
}

// For backward compatibility
void _addLegacyDataContext() {

// device is a common name. If user already uses that, don't override it
// This is now in ensemble.device.*
void _addLegacyDataContext(BuildContext? newBuildContext) {
if (_contextMap['device'] == null) {
_contextMap['device'] = Device();
_contextMap['device'] = Device(newBuildContext);
} else {
// If device exists, update its context
final device = _contextMap['device'];
device.updateContext(newBuildContext);
}
}

Expand Down Expand Up @@ -468,7 +472,7 @@ class NativeInvokable extends ActionInvokable {
'user': () => UserInfo(),
'formatter': () => Formatter(),
'utils': () => _EnsembleUtils(),
'device': () => Device(),
'device': () => Device(buildContext),
'version': () => _cache['version'],
};
}
Expand Down
55 changes: 48 additions & 7 deletions modules/ensemble/lib/framework/device.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:core';
import 'dart:io';
import 'dart:developer';
Expand All @@ -14,24 +15,64 @@ import 'package:ensemble_ts_interpreter/invokables/invokable.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:get_it/get_it.dart';
import 'package:intl/intl.dart';

/// get device information as well as requesting device permissions
class Device
with
Invokable,
MediaQueryCapability,
LocationCapability,
DeviceInfoCapability {
DeviceInfoCapability,
WidgetsBindingObserver {
static final Device _instance = Device._internal();
static late BuildContext context;

Device._internal();
Device._internal() {
WidgetsBinding.instance.addObserver(this);
}

factory Device() {
factory Device([BuildContext? buildContext]) {
if (buildContext != null) {
context = buildContext;
}
return _instance;
}

// method to update context
void updateContext(BuildContext? newContext) {
if (newContext != null) {
context = newContext;
}
}

@override
void didChangeMetrics() {
WidgetsBinding.instance
.addPostFrameCallback((_) => _handleMediaQueryChange());
}

void _handleMediaQueryChange() {
final newData = MediaQuery.of(context);

// Compare with existing static data
if (MediaQueryCapability.data?.orientation != newData.orientation ||
MediaQueryCapability.data?.size != newData.size) {
MediaQueryCapability.data = newData;

// Dispatch individual property changes
ScreenController().dispatchDeviceChanges(context, 'width', screenWidth);
ScreenController().dispatchDeviceChanges(context, 'height', screenHeight);
ScreenController()
.dispatchDeviceChanges(context, 'orientation', screenOrientation);
ScreenController()
.dispatchDeviceChanges(context, 'safeAreaTop', safeAreaTop);
ScreenController()
.dispatchDeviceChanges(context, 'safeAreaBottom', safeAreaBottom);
}
}

@override
Map<String, Function> getters() {
return {
Expand All @@ -42,6 +83,7 @@ class Device
// Media Query
"width": () => screenWidth,
"height": () => screenHeight,
"orientation": () => screenOrientation,
"safeAreaTop": () => safeAreaTop,
"safeAreaBottom": () => safeAreaBottom,

Expand Down Expand Up @@ -73,9 +115,7 @@ class Device
}

@override
Map<String, Function> setters() {
return {};
}
Map<String, Function> setters() => {};

void openAppSettings([String? target]) {
final settingType =
Expand All @@ -96,6 +136,7 @@ mixin MediaQueryCapability {

int get screenWidth => _getData().size.width.toInt();
int get screenHeight => _getData().size.height.toInt();
String get screenOrientation => _getData().orientation.toString();
int get safeAreaTop => _getData().padding.top.toInt();
int get safeAreaBottom => _getData().padding.bottom.toInt();
}
Expand Down
10 changes: 10 additions & 0 deletions modules/ensemble/lib/screen_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,16 @@ class ScreenController {
}
}

void dispatchDeviceChanges(
BuildContext context, String property, dynamic value) {
ScopeManager? scopeManager = getScopeManager(context);

if (scopeManager != null) {
scopeManager
.dispatch(ModelChangeEvent(DeviceBindingSource(property), value));
}
}

void dispatchSystemStorageChanges(
BuildContext context, String key, dynamic value,
{required String storagePrefix}) {
Expand Down

0 comments on commit 4827a68

Please sign in to comment.