Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into camx_aspect
Browse files Browse the repository at this point in the history
  • Loading branch information
camsim99 committed Mar 20, 2024
2 parents 02d8bb0 + 6975ba7 commit e22de74
Show file tree
Hide file tree
Showing 24 changed files with 8,342 additions and 145 deletions.
2 changes: 1 addition & 1 deletion .ci/flutter_master.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
d31a85ba5c5e67199a9a3c95fd9fef51c89a9306
b96c13d1e9ff3e8ebb9f3647b43c8d51c221e82e
4 changes: 4 additions & 0 deletions packages/camera/camera_android_camerax/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

* Modifies resolution selection logic to use an `AspectRatioStrategy` for all aspect ratios supported by CameraX.

## 0.6.0+1

* Updates `README.md` to encourage developers to opt into this implementation of the camera plugin.

## 0.6.0

* Implements `setFocusMode`, which makes this plugin reach feature parity with camera_android.
Expand Down
25 changes: 11 additions & 14 deletions packages/camera/camera_android_camerax/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,23 @@

An Android implementation of [`camera`][1] that uses the [CameraX library][2].

*Note*: This package is under development, so please note the
[missing features and limitations](#limitations), but
otherwise feel free to try out the current implementation and provide any
feedback by filing issues under [`flutter/flutter`][5] with `[camerax]` in
the title, which will be actively triaged.
*Note*: This implementation will become the default implementation of `camera`
on Android by May 2024, so **we strongly encourage you to opt into it**
by using [the instructions](#usage) below. If any of [the limitations](#limitations)
prevent you from using `camera_android_camerax` or if you run into any problems,
please report these issues under [`flutter/flutter`][5] with `[camerax]` in
the title.

## Usage

This package is [non-endorsed][3]; the endorsed Android implementation of `camera`
is [`camera_android`][4]. To use this implementation of the plugin instead of
`camera_android`, you will need to specify it in your `pubspec.yaml` file as a
dependency in addition to `camera`:
To use this plugin instead of [`camera_android`][4], run

```yaml
dependencies:
# ...along with your other dependencies
camera: ^0.10.4
camera_android_camerax: ^0.5.0
```sh
$ flutter pub add camera_android_camerax
```

from your project's root directory.

## Limitations

### 240p resolution configuration for video recording
Expand Down
5 changes: 5 additions & 0 deletions packages/flutter_markdown/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.6.22

* Introduces a new `MarkdownElementBuilder.isBlockElement()` method to specify if custom element
is a block.

## 0.6.21+1

* Adds `onSelectionChanged` to the constructors of `Markdown` and `MarkdownBody`.
Expand Down
8 changes: 7 additions & 1 deletion packages/flutter_markdown/lib/src/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import '_functions_io.dart' if (dart.library.js_interop) '_functions_web.dart';
import 'style_sheet.dart';
import 'widget.dart';

const List<String> _kBlockTags = <String>[
final List<String> _kBlockTags = <String>[
'p',
'h1',
'h2',
Expand Down Expand Up @@ -190,6 +190,12 @@ class MarkdownBuilder implements md.NodeVisitor {
_linkHandlers.clear();
_isInBlockquote = false;

builders.forEach((String key, MarkdownElementBuilder value) {
if (value.isBlockElement()) {
_kBlockTags.add(key);
}
});

_blocks.add(_BlockElement(null));

for (final md.Node node in nodes) {
Expand Down
5 changes: 5 additions & 0 deletions packages/flutter_markdown/lib/src/widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ abstract class SyntaxHighlighter {

/// An interface for an element builder.
abstract class MarkdownElementBuilder {
/// For block syntax has to return true.
///
/// By default returns false.
bool isBlockElement() => false;

/// Called when an Element has been reached, before its children have been
/// visited.
void visitElementBefore(md.Element element) {}
Expand Down
2 changes: 1 addition & 1 deletion packages/flutter_markdown/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: A Markdown renderer for Flutter. Create rich text output,
formatted with simple Markdown tags.
repository: https://github.com/flutter/packages/tree/main/packages/flutter_markdown
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_markdown%22
version: 0.6.21+1
version: 0.6.22

environment:
sdk: ^3.3.0
Expand Down
49 changes: 49 additions & 0 deletions packages/flutter_markdown/test/custom_syntax_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,30 @@ void defineTests() {
},
);

testWidgets(
'Custom block element',
(WidgetTester tester) async {
const String blockContent = 'note block';
await tester.pumpWidget(
boilerplate(
Markdown(
data: '[!NOTE] $blockContent',
extensionSet: md.ExtensionSet.none,
blockSyntaxes: <md.BlockSyntax>[NoteSyntax()],
builders: <String, MarkdownElementBuilder>{
'note': NoteBuilder(),
},
),
),
);
final ColoredBox container =
tester.widgetList(find.byType(ColoredBox)).first as ColoredBox;
expect(container.color, Colors.red);
expect(container.child, isInstanceOf<Text>());
expect((container.child! as Text).data, blockContent);
},
);

testWidgets(
'link for wikistyle',
(WidgetTester tester) async {
Expand Down Expand Up @@ -331,3 +355,28 @@ class ImgBuilder extends MarkdownElementBuilder {
return Text('foo', style: preferredStyle);
}
}

class NoteBuilder extends MarkdownElementBuilder {
@override
Widget? visitText(md.Text text, TextStyle? preferredStyle) {
return ColoredBox(
color: Colors.red, child: Text(text.text, style: preferredStyle));
}

@override
bool isBlockElement() {
return true;
}
}

class NoteSyntax extends md.BlockSyntax {
@override
md.Node? parse(md.BlockParser parser) {
final md.Line line = parser.current;
parser.advance();
return md.Element('note', <md.Node>[md.Text(line.content.substring(8))]);
}

@override
RegExp get pattern => RegExp(r'^\[!NOTE] ');
}
4 changes: 4 additions & 0 deletions packages/pigeon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 17.2.0

* [dart] Adds implementation for `@ProxyApi`.

## 17.1.3

* [objc] Fixes double prefixes added to enum names.
Expand Down
127 changes: 127 additions & 0 deletions packages/pigeon/lib/ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,133 @@ class AstProxyApi extends Api {
(ApiField field) => !field.isAttached,
);

/// A list of AstProxyApis where each `extends` the API that follows it.
///
/// Returns an empty list if this api does not extend a ProxyApi.
///
/// This method assumes the super classes of each ProxyApi doesn't create a
/// loop. Throws a [ArgumentError] if a loop is found.
///
/// This method also assumes that all super classes are ProxyApis. Otherwise,
/// throws an [ArgumentError].
Iterable<AstProxyApi> allSuperClasses() {
final List<AstProxyApi> superClassChain = <AstProxyApi>[];

if (superClass != null && !superClass!.isProxyApi) {
throw ArgumentError(
'Could not find a ProxyApi for super class: ${superClass!.baseName}',
);
}

AstProxyApi? currentProxyApi = superClass?.associatedProxyApi;
while (currentProxyApi != null) {
if (superClassChain.contains(currentProxyApi)) {
throw ArgumentError(
'Loop found when processing super classes for a ProxyApi: '
'$name, ${superClassChain.map((AstProxyApi api) => api.name)}',
);
}

superClassChain.add(currentProxyApi);

if (currentProxyApi.superClass != null &&
!currentProxyApi.superClass!.isProxyApi) {
throw ArgumentError(
'Could not find a ProxyApi for super class: '
'${currentProxyApi.superClass!.baseName}',
);
}

currentProxyApi = currentProxyApi.superClass?.associatedProxyApi;
}

return superClassChain;
}

/// All ProxyApis this API `implements` and all the interfaces those APIs
/// `implements`.
Iterable<AstProxyApi> apisOfInterfaces() => _recursiveFindAllInterfaceApis();

/// All methods inherited from interfaces and the interfaces of interfaces.
Iterable<Method> flutterMethodsFromInterfaces() sync* {
for (final AstProxyApi proxyApi in apisOfInterfaces()) {
yield* proxyApi.methods;
}
}

/// A list of Flutter methods inherited from the ProxyApi that this ProxyApi
/// `extends`.
///
/// This also recursively checks the ProxyApi that the super class `extends`
/// and so on.
///
/// This also includes methods that super classes inherited from interfaces
/// with `implements`.
Iterable<Method> flutterMethodsFromSuperClasses() sync* {
for (final AstProxyApi proxyApi in allSuperClasses().toList().reversed) {
yield* proxyApi.flutterMethods;
}
if (superClass != null) {
final Set<AstProxyApi> interfaceApisFromSuperClasses =
superClass!.associatedProxyApi!._recursiveFindAllInterfaceApis();
for (final AstProxyApi proxyApi in interfaceApisFromSuperClasses) {
yield* proxyApi.methods;
}
}
}

/// Whether the api has a method that callbacks to Dart to add a new instance
/// to the InstanceManager.
///
/// This is possible as long as no callback methods are required to
/// instantiate the class.
bool hasCallbackConstructor() {
return flutterMethods
.followedBy(flutterMethodsFromSuperClasses())
.followedBy(flutterMethodsFromInterfaces())
.every((Method method) => !method.isRequired);
}

// Recursively search for all the interfaces apis from a list of names of
// interfaces.
//
// This method assumes that all interfaces are ProxyApis and an api doesn't
// contains itself as an interface. Otherwise, throws an [ArgumentError].
Set<AstProxyApi> _recursiveFindAllInterfaceApis([
Set<AstProxyApi> seenApis = const <AstProxyApi>{},
]) {
final Set<AstProxyApi> allInterfaces = <AstProxyApi>{};

allInterfaces.addAll(
interfaces.map(
(TypeDeclaration type) {
if (!type.isProxyApi) {
throw ArgumentError(
'Could not find a valid ProxyApi for an interface: $type',
);
} else if (seenApis.contains(type.associatedProxyApi)) {
throw ArgumentError(
'A ProxyApi cannot be a super class of itself: ${type.baseName}',
);
}
return type.associatedProxyApi!;
},
),
);

// Adds the current api since it would be invalid for it to be an interface
// of itself.
final Set<AstProxyApi> newSeenApis = <AstProxyApi>{...seenApis, this};

for (final AstProxyApi interfaceApi in <AstProxyApi>{...allInterfaces}) {
allInterfaces.addAll(
interfaceApi._recursiveFindAllInterfaceApis(newSeenApis),
);
}

return allInterfaces;
}

@override
String toString() {
return '(ProxyApi name:$name methods:$methods field:$fields '
Expand Down
Loading

0 comments on commit e22de74

Please sign in to comment.