Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: fetch crossword from firestore #23

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions api/packages/game_domain/lib/src/models/board_section.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ class BoardSection extends Equatable {
/// Returns a json representation from this instance.
Map<String, dynamic> toJson() => _$BoardSectionToJson(this);

BoardSection copyWith({
Point<int>? position,
}) =>
BoardSection(
id: id,
position: position ?? this.position,
size: size,
words: words,
borderWords: borderWords,
);

@override
List<Object?> get props => [
id,
Expand Down
9 changes: 7 additions & 2 deletions lib/app/view/app.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import 'package:crossword_repository/crossword_repository.dart';
import 'package:flame/cache.dart';
import 'package:flame_audio/flame_audio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:io_crossword/l10n/l10n.dart';
import 'package:io_crossword/loading/loading.dart';
import 'package:provider/provider.dart';

class App extends StatelessWidget {
const App({super.key});
const App({required this.crosswordRepository, super.key});

final CrosswordRepository crosswordRepository;

@override
Widget build(BuildContext context) {
return MultiBlocProvider(
return MultiProvider(
providers: [
Provider.value(value: crosswordRepository),
BlocProvider(
create: (_) => PreloadCubit(
Images(prefix: ''),
Expand Down
3 changes: 3 additions & 0 deletions lib/bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:developer';

import 'package:bloc/bloc.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/widgets.dart';

Expand All @@ -22,6 +23,7 @@ class AppBlocObserver extends BlocObserver {
}

typedef BootstrapBuilder = FutureOr<Widget> Function(
FirebaseFirestore firestore,
FirebaseAuth firebaseAuth,
);

Expand All @@ -36,6 +38,7 @@ Future<void> bootstrap(BootstrapBuilder builder) async {

runApp(
await builder(
FirebaseFirestore.instance,
FirebaseAuth.instance,
),
);
Expand Down
132 changes: 52 additions & 80 deletions lib/crossword/bloc/crossword_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,47 +1,49 @@
import 'package:bloc/bloc.dart';
import 'package:crossword_repository/crossword_repository.dart';
import 'package:equatable/equatable.dart';
import 'package:game_domain/game_domain.dart';

part 'crossword_event.dart';
part 'crossword_state.dart';

class CrosswordBloc extends Bloc<CrosswordEvent, CrosswordState> {
CrosswordBloc() : super(const CrosswordInitial()) {
CrosswordBloc(this.crosswordRepository) : super(const CrosswordInitial()) {
on<InitialBoardLoadRequested>(_onInitialBoardLoadRequested);
on<BoardSectionRequested>(_onBoardSectionRequested);
}

final CrosswordRepository crosswordRepository;

Future<void> _onInitialBoardLoadRequested(
InitialBoardLoadRequested event,
Emitter<CrosswordState> emit,
) async {
final section = BoardSection(
id: '1',
position: const Point(2, 2),
size: 40,
words: [
Word(
axis: Axis.horizontal,
position: const Point(0, 0),
answer: 'flutter',
clue: 'flutter',
hints: const ['dart', 'mobile', 'cross-platform'],
visible: true,
solvedTimestamp: null,
),
],
borderWords: const [],
);

emit(
CrosswordLoaded(
width: 40,
height: 40,
sectionSize: 400,
sections: {
(section.position.x, section.position.y): section,
},
),
return emit.forEach(
crosswordRepository.watchSections(),
onData: (sections) {
final allSections = <BoardSection>[];
// To be removed...
// Translate letters coordinates to sections coordinates
for (final section in sections) {
final x = section.position.x - 21;
final y = section.position.y + 80;
final moduloX = x / 300;
final moduloY = y / 300;
final updated = section.copyWith(
position: Point(moduloX.round(), moduloY.round()));
allSections.add(updated);
}
return CrosswordLoaded(
width: 40,
height: 40,
sectionSize: 300,
sections: const {},
allSections: {
for (final section in allSections)
(section.position.x, section.position.y): section,
},
);
},
);
}

Expand All @@ -51,59 +53,29 @@ class CrosswordBloc extends Bloc<CrosswordEvent, CrosswordState> {
) async {
final loadedState = state;
if (loadedState is CrosswordLoaded) {
final section = BoardSection(
id: '',
position: Point(event.position.$1, event.position.$2),
size: 40,
words: [
Word(
axis: Axis.horizontal,
position: const Point(0, 0),
answer: 'flutter',
clue: 'flutter',
hints: const ['dart', 'mobile', 'cross-platform'],
visible: true,
solvedTimestamp: null,
),
Word(
axis: Axis.vertical,
position: const Point(4, 1),
answer: 'android',
clue: 'flutter',
hints: const ['dart', 'mobile', 'cross-platform'],
visible: true,
solvedTimestamp: null,
),
Word(
axis: Axis.vertical,
position: const Point(8, 3),
answer: 'dino',
clue: 'flutter',
hints: const ['dart', 'mobile', 'cross-platform'],
visible: true,
solvedTimestamp: null,
),
Word(
position: const Point(4, 6),
axis: Axis.horizontal,
answer: 'sparky',
clue: 'flutter',
hints: const ['dart', 'mobile', 'cross-platform'],
visible: true,
solvedTimestamp: null,
),
],
borderWords: const [],
);
if (loadedState.sections.length >= 20) return;
try {
final nextKey = loadedState.allSections.keys.firstWhere(
(element) => !loadedState.sections.containsKey(
element) /*&&
element.$1 == 0 &&
element.$2 == 0,*/
);
final section = loadedState.allSections[nextKey];

emit(
loadedState.copyWith(
sections: {
...loadedState.sections,
(section.position.x, section.position.y): section,
},
),
);
if (section != null) {
emit(
loadedState.copyWith(
sections: {
...loadedState.sections,
(section.position.x, section.position.y): section,
},
),
);
}
} catch (e) {
//print('noproblem');
}
}
}
}
6 changes: 5 additions & 1 deletion lib/crossword/bloc/crossword_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,33 @@ class CrosswordLoaded extends CrosswordState {
required this.height,
required this.sectionSize,
required this.sections,
required this.allSections,
});

final int width;
final int height;
final int sectionSize;
final Map<(int, int), BoardSection> sections;
final Map<(int, int), BoardSection> allSections;

CrosswordLoaded copyWith({
int? width,
int? height,
int? sectionSize,
Map<(int, int), BoardSection>? sections,
Map<(int, int), BoardSection>? allSections,
}) {
return CrosswordLoaded(
width: width ?? this.width,
height: height ?? this.height,
sectionSize: sectionSize ?? this.sectionSize,
sections: sections ?? this.sections,
allSections: allSections ?? this.allSections,
);
}

@override
List<Object> get props => [width, height, sectionSize, sections];
List<Object> get props => [width, height, sectionSize, sections, allSections];
}

class CrosswordError extends CrosswordState {
Expand Down
4 changes: 3 additions & 1 deletion lib/crossword/view/crossword_page.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:crossword_repository/crossword_repository.dart';
import 'package:flame/game.dart' hide Route;
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
Expand All @@ -10,7 +11,8 @@ class CrosswordPage extends StatelessWidget {
return MaterialPageRoute<void>(
builder: (_) => BlocProvider(
create: (BuildContext context) =>
CrosswordBloc()..add(const InitialBoardLoadRequested()),
CrosswordBloc(context.read<CrosswordRepository>())
..add(const InitialBoardLoadRequested()),
child: const CrosswordPage(),
),
);
Expand Down
7 changes: 5 additions & 2 deletions lib/main_development.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';

import 'package:authentication_repository/authentication_repository.dart';
import 'package:crossword_repository/crossword_repository.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/widgets.dart';
import 'package:io_crossword/app/app.dart';
Expand All @@ -16,15 +17,17 @@ void main() async {

unawaited(
bootstrap(
(firebaseAuth) async {
(firestore, firebaseAuth) async {
final authenticationRepository = AuthenticationRepository(
firebaseAuth: firebaseAuth,
);

await authenticationRepository.signInAnonymously();
await authenticationRepository.idToken.first;

return const App();
return App(
crosswordRepository: CrosswordRepository(db: firestore),
);
},
),
);
Expand Down
7 changes: 5 additions & 2 deletions lib/main_production.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';

import 'package:authentication_repository/authentication_repository.dart';
import 'package:crossword_repository/crossword_repository.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/widgets.dart';
import 'package:io_crossword/app/app.dart';
Expand All @@ -16,15 +17,17 @@ void main() async {

unawaited(
bootstrap(
(firebaseAuth) async {
(firestore, firebaseAuth) async {
final authenticationRepository = AuthenticationRepository(
firebaseAuth: firebaseAuth,
);

await authenticationRepository.signInAnonymously();
await authenticationRepository.idToken.first;

return const App();
return App(
crosswordRepository: CrosswordRepository(db: firestore),
);
},
),
);
Expand Down
7 changes: 5 additions & 2 deletions lib/main_staging.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';

import 'package:authentication_repository/authentication_repository.dart';
import 'package:crossword_repository/crossword_repository.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/widgets.dart';
import 'package:io_crossword/app/app.dart';
Expand All @@ -16,15 +17,17 @@ void main() async {

unawaited(
bootstrap(
(firebaseAuth) async {
(firestore, firebaseAuth) async {
final authenticationRepository = AuthenticationRepository(
firebaseAuth: firebaseAuth,
);

await authenticationRepository.signInAnonymously();
await authenticationRepository.idToken.first;

return const App();
return App(
crosswordRepository: CrosswordRepository(db: firestore),
);
},
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class CrosswordRepository {
CrosswordRepository({
required this.db,
}) {
sectionCollection = db.collection('sections');
sectionCollection = db.collection('boardSections');
}

/// The [FirebaseFirestore] instance.
Expand Down
4 changes: 4 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ dependencies:
authentication_repository:
path: packages/authentication_repository
bloc: ^8.1.3
cloud_firestore: ^4.15.6
crossword_repository:
path: packages/crossword_repository
equatable: ^2.0.5
firebase_auth: ^4.17.6
firebase_core: ^2.25.4
Expand All @@ -26,6 +29,7 @@ dependencies:
game_domain:
path: api/packages/game_domain
intl: ^0.18.1
provider: ^6.1.2

dev_dependencies:
bloc_test: ^9.1.6
Expand Down
Loading
Loading