Skip to content

Commit

Permalink
feat: add analytics
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesblasco committed Mar 18, 2022
1 parent 6fef923 commit e4e45c7
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 10 deletions.
7 changes: 7 additions & 0 deletions lib/bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import 'dart:async';
import 'dart:developer';

import 'package:bloc/bloc.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/widgets.dart';
import 'package:puzzles_repository/puzzles_repository.dart';
import 'package:rush_hour_puzzle/app/view/app.dart';
import 'package:rush_hour_puzzle/firebase_options.dart';

class AppBlocObserver extends BlocObserver {
@override
Expand All @@ -34,6 +36,11 @@ Future<void> bootstrap() async {

const puzzlesRepository = PuzzlesRepository();

WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);

await runZonedGuarded(
() async {
await BlocOverrides.runZoned(
Expand Down
74 changes: 74 additions & 0 deletions lib/firebase_options.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// File generated by FlutterFire CLI.
// ignore_for_file: lines_longer_than_80_chars
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;

/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
/// options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
// ignore: missing_enum_constant_in_switch
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
return macos;
}

throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}

static const FirebaseOptions web = FirebaseOptions(
apiKey: 'AIzaSyDu-cSR-CC4IvKZKdPaXYzEZ4_rWQRKBoE',
appId: '1:1041926528718:web:6111018d26ebe70a19fa9f',
messagingSenderId: '1041926528718',
projectId: 'flutter-rush',
authDomain: 'flutter-rush.firebaseapp.com',
storageBucket: 'flutter-rush.appspot.com',
measurementId: 'G-M09PGRLCJ9',
);

static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyBYTVLwzLY3WkRnKK7p36OFd0aImuWEZ_Q',
appId: '1:1041926528718:android:e34845c71d09020c19fa9f',
messagingSenderId: '1041926528718',
projectId: 'flutter-rush',
storageBucket: 'flutter-rush.appspot.com',
);

static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyAnChv2vIIXIcDug8SIhVBgrmBcHZWyMWE',
appId: '1:1041926528718:ios:8136dbb8a0635b9919fa9f',
messagingSenderId: '1041926528718',
projectId: 'flutter-rush',
storageBucket: 'flutter-rush.appspot.com',
iosClientId: '1041926528718-pqsds9desbjlgo7crtsesdf0ac6i5eje.apps.googleusercontent.com',
iosBundleId: 'app.flutter.rushpuzzle',
);

static const FirebaseOptions macos = FirebaseOptions(
apiKey: 'AIzaSyAnChv2vIIXIcDug8SIhVBgrmBcHZWyMWE',
appId: '1:1041926528718:ios:8136dbb8a0635b9919fa9f',
messagingSenderId: '1041926528718',
projectId: 'flutter-rush',
storageBucket: 'flutter-rush.appspot.com',
iosClientId: '1041926528718-pqsds9desbjlgo7crtsesdf0ac6i5eje.apps.googleusercontent.com',
iosBundleId: 'app.flutter.rushpuzzle',
);
}
67 changes: 61 additions & 6 deletions lib/puzzle/bloc/puzzle_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:flutter/widgets.dart';
import 'package:puzzle_models/puzzle_models.dart';
import 'package:puzzles_repository/puzzles_repository.dart';
Expand Down Expand Up @@ -33,19 +34,43 @@ class PuzzleBloc extends Bloc<PuzzleEvent, PuzzleState> {
PuzzleFetched event,
Emitter<PuzzleState> emit,
) async {
emit(state.copyWith(status: GameStatus.loading));
final game = await _puzzlesRepository.getPuzzle(puzzleVersion);
emit(state.copyWith(status: GameStatus.setup, history: [game]));
try {
emit(state.copyWith(status: GameStatus.loading));
final game = await _puzzlesRepository.getPuzzle(puzzleVersion);
emit(state.copyWith(status: GameStatus.setup, history: [game]));
await FirebaseAnalytics.instance.logEvent(
name: 'game_loaded',
parameters: {
'version': puzzleVersion,
},
);
} catch (e) {
await FirebaseAnalytics.instance.logEvent(
name: 'game_failed',
parameters: {
'version': puzzleVersion,
},
);
}
}

Future<void> _onPuzzleStarted(
PuzzleStarted event,
Emitter<PuzzleState> emit,
) async {
emit(state.copyWith(status: GameStatus.playing));
await FirebaseAnalytics.instance.logEvent(
name: 'game_started',
parameters: {
'version': puzzleVersion,
},
);
}

void _onPuzzleVehicleMoved(PuzzleVehicleMoved event, Emitter emit) {
Future<void> _onPuzzleVehicleMoved(
PuzzleVehicleMoved event,
Emitter emit,
) async {
assert(
state.status == GameStatus.playing,
'Vehicle should move only when playing',
Expand All @@ -59,15 +84,31 @@ class PuzzleBloc extends Bloc<PuzzleEvent, PuzzleState> {
status: newPuzzle.isSolved ? GameStatus.finished : null,
),
);
await FirebaseAnalytics.instance.logEvent(
name: 'game_vehicle_moved',
parameters: {
'version': puzzleVersion,
'vehicle': event.vehicle.id,
'newPositionX': event.newPosition.x,
'newPositionY': event.newPosition.y,
'historyMove': newPointer,
},
);
}

void _onPuzzleReseted(PuzzleReseted event, Emitter emit) {
Future<void> _onPuzzleReseted(PuzzleReseted event, Emitter emit) async {
emit(
PuzzleState(
status: GameStatus.setup,
history: [state.history[0]],
),
);
await FirebaseAnalytics.instance.logEvent(
name: 'game_rested',
parameters: {
'version': puzzleVersion,
},
);
}

void _onPuzzleMoveUndid(PuzzleMoveUndid event, Emitter emit) {
Expand All @@ -85,12 +126,26 @@ class PuzzleBloc extends Bloc<PuzzleEvent, PuzzleState> {
Emitter<PuzzleState> emit,
) async {
emit(state.copyWith(perspective: event.perspective));
await FirebaseAnalytics.instance.logEvent(
name: 'game_perspective_changed',
parameters: {
'version': puzzleVersion,
'vehicle': event.perspective,
},
);
}

void _onPuzzleShared(PuzzleShared event, Emitter emit) {
Future<void> _onPuzzleShared(PuzzleShared event, Emitter emit) async {
if (!state.puzzle.isSolved) return;

sharePuzzle(state, puzzleVersion);
await FirebaseAnalytics.instance.logEvent(
name: 'game_shared',
parameters: {
'version': puzzleVersion,
'historyMove': state.historyPointer,
},
);
}
}

Expand Down
12 changes: 10 additions & 2 deletions lib/puzzle/widgets/timer_handler.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:rush_hour_puzzle/puzzle/puzzle.dart';
import 'package:rush_hour_puzzle/timer/timer.dart';


class TimerHandler extends StatelessWidget {
const TimerHandler({Key? key, this.child}) : super(key: key);
const TimerHandler({Key? key, this.child}) : super(key: key);
final Widget? child;
@override
Widget build(BuildContext context) {
Expand All @@ -20,6 +20,14 @@ class TimerHandler extends StatelessWidget {
}
if (state.status == GameStatus.finished) {
context.read<TimerBloc>().add(const TimerStopped());
FirebaseAnalytics.instance.logEvent(
name: 'game_finished',
parameters: {
'version': context.read<PuzzleBloc>().puzzleVersion,
'historyMove': state.historyPointer,
'timer': context.read<TimerBloc>().state.secondsElapsed,
},
);
}
if (state.status == GameStatus.setup) {
context.read<TimerBloc>().add(const TimerReset());
Expand Down
6 changes: 6 additions & 0 deletions macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
import FlutterMacOS
import Foundation

import firebase_analytics
import firebase_core
import firebase_crashlytics
import path_provider_macos
import share_plus_macos
import url_launcher_macos

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin"))
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
Expand Down
58 changes: 57 additions & 1 deletion pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,62 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
firebase_analytics:
dependency: "direct main"
description:
name: firebase_analytics
url: "https://pub.dartlang.org"
source: hosted
version: "9.1.2"
firebase_analytics_platform_interface:
dependency: transitive
description:
name: firebase_analytics_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.1"
firebase_analytics_web:
dependency: transitive
description:
name: firebase_analytics_web
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.0+8"
firebase_core:
dependency: "direct main"
description:
name: firebase_core
url: "https://pub.dartlang.org"
source: hosted
version: "1.13.1"
firebase_core_platform_interface:
dependency: transitive
description:
name: firebase_core_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.5"
firebase_core_web:
dependency: transitive
description:
name: firebase_core_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.1"
firebase_crashlytics:
dependency: "direct main"
description:
name: firebase_crashlytics
url: "https://pub.dartlang.org"
source: hosted
version: "2.5.3"
firebase_crashlytics_platform_interface:
dependency: transitive
description:
name: firebase_crashlytics_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.1"
fireworks:
dependency: "direct main"
description:
Expand Down Expand Up @@ -321,7 +377,7 @@ packages:
name: msix
url: "https://pub.dartlang.org"
source: hosted
version: "3.3.2"
version: "3.4.0"
nested:
dependency: transitive
description:
Expand Down
5 changes: 4 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: rush_hour_puzzle
description: Play a daily Rush Puzzle game
version: 1.0.6+19
version: 1.0.7+20
publish_to: none

environment:
Expand All @@ -9,6 +9,9 @@ environment:
dependencies:
bloc: ^8.0.2
equatable: ^2.0.3
firebase_analytics: ^9.1.2
firebase_core: ^1.13.1
firebase_crashlytics: ^2.5.3
fireworks:
path: packages/fireworks
flutter:
Expand Down

0 comments on commit e4e45c7

Please sign in to comment.