Skip to content

Commit

Permalink
Merge pull request #6 from thekorn/controller_event_stream
Browse files Browse the repository at this point in the history
feat: Controller event stream
  • Loading branch information
thekorn authored Jan 28, 2024
2 parents 5fb536e + ee224d8 commit 01eca4a
Show file tree
Hide file tree
Showing 18 changed files with 509 additions and 173 deletions.
17 changes: 17 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[*.{kt,kts}]
end_of_line = lf
ij_kotlin_allow_trailing_comma = false
ij_kotlin_allow_trailing_comma_on_call_site = false
ij_kotlin_imports_layout = *
ij_kotlin_packages_to_use_import_on_demand = java.util.*,kotlinx.android.synthetic.**
indent_size = 4
indent_style = space
insert_final_newline = true
ktlint_chain_method_rule_force_multiline_when_chain_operator_count_greater_or_equal_than = unset
ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = unset
ktlint_code_style = android_studio
ktlint_function_naming_ignore_when_annotated_with = [unset]
ktlint_function_signature_body_expression_wrapping = default
ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = unset
ktlint_ignore_back_ticked_identifier = false
max_line_length = 100
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Packages:
- dart
- flutter
- swiftformat
- ktlint

```bash
dart pub global activate melos
Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"bunte",
"demoads",
"flutterfire",
"ktlint",
"swiftformat",
"swiftversion",
"thekorn",
Expand Down
5 changes: 4 additions & 1 deletion melos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@ scripts:
format:
run: |
fvm dart pub global run flutter_plugin_tools format && \
swiftformat --swiftversion 5 .
swiftformat --swiftversion 5 . && \
ktlint --format '**/*.kt' '**/*.kts' '!**/*.g.kt'
description: |
- Requires `swiftformat` (can be installed via Brew on macOS).
- Requires `ktlint` (can be installed via Brew on macOS).
test:all:
run: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ package de.thekorn.xandr.example

import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {
}
class MainActivity : FlutterActivity()
18 changes: 7 additions & 11 deletions packages/xandr/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@ import 'package:flutter/material.dart';
import 'package:xandr/ad_banner.dart';
import 'package:xandr/ad_size.dart';
import 'package:xandr/xandr.dart';

class XandrBuilder extends FutureBuilder<bool> {
XandrBuilder({
required XandrController controller,
required super.builder,
required int memberId,
super.key,
}) : super(future: controller.init(memberId));
}
import 'package:xandr/xandr_builder.dart';

void main() {
WidgetsFlutterBinding.ensureInitialized();
Expand Down Expand Up @@ -60,7 +52,10 @@ class _XandrExampleState extends State<XandrExample> {
controller: _controller,
//placementID: '17058950',
inventoryCode: 'bunte_webdesktop_home_homepage_hor_1',
adSizes: const [AdSize(728, 90)], //[AdSize(300, 250)],
adSizes: const [
AdSize(1, 1),
AdSize(728, 90),
], //[AdSize(300, 250)],
customKeywords: useDemoAds,
),
AdBanner(
Expand All @@ -69,7 +64,8 @@ class _XandrExampleState extends State<XandrExample> {
inventoryCode: 'bunte_webdesktop_home_homepage_hor_1',
adSizes: const [AdSize(728, 90)], //[AdSize(300, 250)],
customKeywords: useDemoAds,
allowNativeDemand: true,
width: 10,
height: 10,
),
],
);
Expand Down
90 changes: 79 additions & 11 deletions packages/xandr/lib/ad_banner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:xandr/ad_size.dart';
import 'package:xandr/xandr.dart';
import 'package:xandr_android/xandr_android.dart';

class AdBanner extends StatelessWidget {
class AdBanner extends StatefulWidget {
AdBanner({
required this.adSizes,
required this.controller,
Expand All @@ -15,31 +16,66 @@ class AdBanner extends StatelessWidget {
this.customKeywords,
this.autoRefreshInterval = const Duration(seconds: 30),
this.allowNativeDemand = false,
double? width,
double? height,
}) : assert(adSizes.isNotEmpty, 'adSizes must not be empty'),
assert(
placementID != null || inventoryCode != null,
'placementID or inventoryCode must not be null',
);
),
width = width ?? adSizes.first.width.toDouble(),
height = height ?? adSizes.first.height.toDouble();
final String? placementID;
final String? inventoryCode;
final List<AdSize> adSizes;
final CustomKeywords? customKeywords;
final XandrController controller;
final Duration autoRefreshInterval;
final bool allowNativeDemand;
final double width;
final double height;

@override
State<AdBanner> createState() => _AdBannerState();
}

class _AdBannerState extends State<AdBanner> {
double _width = 1;
double _height = 1;

@override
void initState() {
super.initState();
_height = widget.height;
_width = widget.width;
}

void changeSize(double width, double height) {
setState(() {
_width = width;
_height = height;
});
}

@override
Widget build(BuildContext context) {
return SizedBox(
width: adSizes.first.width.toDouble(),
height: adSizes.first.height.toDouble(),
width: _width, //adSizes.first.width.toDouble(),
height: _height, //adSizes.first.height.toDouble(),
child: _HostAdBannerView(
placementID: placementID,
inventoryCode: inventoryCode,
adSizes: adSizes,
customKeywords: customKeywords ?? {},
allowNativeDemand: allowNativeDemand,
autoRefreshInterval: autoRefreshInterval,
placementID: widget.placementID,
inventoryCode: widget.inventoryCode,
adSizes: widget.adSizes,
customKeywords: widget.customKeywords ?? {},
allowNativeDemand: widget.allowNativeDemand,
autoRefreshInterval: widget.autoRefreshInterval,
controller: widget.controller,
delegate: BannerAdEventDelegate(
onBannerAdLoaded: (event) {
debugPrint('>>>> onBannerAdLoaded: $event');
changeSize(event.width.toDouble(), event.height.toDouble());
},
),
),
);
}
Expand All @@ -53,6 +89,8 @@ class _HostAdBannerView extends StatelessWidget {
required CustomKeywords customKeywords,
required bool allowNativeDemand,
required Duration autoRefreshInterval,
required this.controller,
this.delegate,
}) : creationParams = <String, dynamic>{
'placementID': placementID,
'inventoryCode': inventoryCode,
Expand All @@ -63,15 +101,45 @@ class _HostAdBannerView extends StatelessWidget {
};
static const StandardMessageCodec _decoder = StandardMessageCodec();
final Map<String, dynamic> creationParams;
final XandrController controller;
final BannerAdEventDelegate? delegate;

@override
Widget build(BuildContext context) {
// FIXME(thekorn): use proper host platform implementation
return AndroidView(
viewType: 'de.thekorn.xandr/ad_banner',
onPlatformViewCreated: (id) => debugPrint('Created banner view: $id'),
onPlatformViewCreated: (id) {
debugPrint('Created banner view: $id');
controller.listen(id, (event) {
if (event is BannerAdLoadedEvent) {
delegate?.onBannerAdLoaded?.call(event);
} else if (event is BannerAdLoadedErrorEvent) {
delegate?.onBannerAdLoadedError?.call(event);
} else if (event is NativeBannerAdLoadedEvent) {
delegate?.onNativeBannerAdLoaded?.call(event);
} else if (event is NativeBannerAdLoadedErrorEvent) {
delegate?.onNativeBannerAdLoadedError?.call(event);
}
});
},
creationParams: creationParams,
creationParamsCodec: _decoder,
);
}
}

class BannerAdEventDelegate {
BannerAdEventDelegate({
this.onBannerAdLoaded,
this.onBannerAdLoadedError,
this.onNativeBannerAdLoaded,
this.onNativeBannerAdLoadedError,
});

final void Function(BannerAdLoadedEvent)? onBannerAdLoaded;
final void Function(BannerAdLoadedErrorEvent)? onBannerAdLoadedError;
final void Function(NativeBannerAdLoadedEvent)? onNativeBannerAdLoaded;
final void Function(NativeBannerAdLoadedErrorEvent)?
onNativeBannerAdLoadedError;
}
24 changes: 23 additions & 1 deletion packages/xandr/lib/xandr.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:xandr_platform_interface/xandr_platform_interface.dart';

Expand All @@ -19,14 +21,34 @@ class XandrController {
/// controller.start();
/// ```
XandrController() {
_platform.registerEventDelegate();
_platform.registerEventStream(controller: _eventStreamController);
}

final StreamController<BannerAdEvent> _eventStreamController =
StreamController.broadcast();

/// Initializes the Xandr SDK.
///
/// [memberId] is the Xandr member ID.
Future<bool> init(int memberId) async {
debugPrint('init xandr with memberId=$memberId');
return _platform.init(memberId);
}

/// Listens to the stream of strings and returns a [StreamSubscription] that
/// can be used to cancel the subscription.
///
/// Example usage:
/// ```dart
/// StreamSubscription<BannerAdEvent> subscription = listen();
/// subscription.cancel();
/// ```
StreamSubscription<BannerAdEvent> listen(
int widgetId,
void Function(BannerAdEvent) callback,
) {
return _eventStreamController.stream
.where((event) => event.viewId == widgetId)
.listen(callback);
}
}
20 changes: 20 additions & 0 deletions packages/xandr/lib/xandr_builder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:flutter/widgets.dart';
import 'package:xandr/xandr.dart';

/// A builder class for Xandr that extends [FutureBuilder].
///
/// This class is responsible for building Xandr and handling the asynchronous
/// result of type [bool] which is returned by the [XandrController.init]
/// method and indicates success or failure of the initialization.
class XandrBuilder extends FutureBuilder<bool> {
/// A builder class for creating Xandr objects.
///
/// Use this class to conveniently build Xandr objects with the desired
/// parameters.
XandrBuilder({
required XandrController controller,
required super.builder,
required int memberId,
super.key,
}) : super(future: controller.init(memberId));
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@ class AdInitListener(private val flutterState: FlutterState) : InitListener {
)
this.flutterState.isInitialized.complete(success)
}

}
}
Loading

0 comments on commit 01eca4a

Please sign in to comment.