Skip to content

Commit

Permalink
Change position using drag and drop
Browse files Browse the repository at this point in the history
  • Loading branch information
lockieRichter committed Mar 2, 2024
1 parent a6b3eb4 commit 74bebd1
Show file tree
Hide file tree
Showing 9 changed files with 567 additions and 278 deletions.
3 changes: 3 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
<key>CADisableMinimumFrameDurationOnPhone</key>
<true />
<!-- Google Sign-in Section -->
<key>GIDClientID</key>
<!-- Copied from GoogleService-Info.plist key CLIENT_ID -->
<string>150599422814-eorssa86b5b5l2p2h4ri8bhg82jqsovj.apps.googleusercontent.com</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import 'package:dantex/src/data/authentication/authentication_repository.dart';
import 'package:dantex/src/data/authentication/entity/dante_user.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:google_sign_in/google_sign_in.dart';

class FirebaseAuthenticationRepository implements AuthenticationRepository {
final FirebaseAuth _fbAuth;
final GoogleSignIn googleSignIn;

FirebaseAuthenticationRepository(this._fbAuth);
FirebaseAuthenticationRepository(this._fbAuth, this.googleSignIn);

@override
Stream<DanteUser?> get authStateChanges =>
Expand Down Expand Up @@ -89,14 +91,23 @@ class FirebaseAuthenticationRepository implements AuthenticationRepository {
}

@override
Future<UserCredential> loginWithGoogle() {
Future<UserCredential> loginWithGoogle() async {
final googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication? googleAuth =
await googleSignInAccount?.authentication;

final credential = GoogleAuthProvider.credential(
accessToken: googleAuth?.accessToken,
idToken: googleAuth?.idToken,
);

if (kIsWeb) {
return _fbAuth.signInWithPopup(
GoogleAuthProvider(),
);
} else {
return _fbAuth.signInWithProvider(
GoogleAuthProvider(),
return _fbAuth.signInWithCredential(
credential,
);
}
}
Expand Down
2 changes: 2 additions & 0 deletions lib/src/data/book/book_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,6 @@ abstract class BookRepository {
Future<void> deleteNotes(String bookId);

Future<void> saveNotes(String bookId, String notes);

Future<void> updatePositions(List<Book> books);
}
10 changes: 10 additions & 0 deletions lib/src/data/book/firebase_book_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,16 @@ class FirebaseBookRepository implements BookRepository {
Future<void> saveNotes(String bookId, String notes) {
return _booksRef().child(bookId).update({'notes': notes});
}

@override
Future<void> updatePositions(List<Book> books) async {
final Map<String, Object?> updateMap = {};
for (var i = 0; i < books.length; i++) {
final book = books[i];
updateMap[book.id] = book.copyWith(position: i).toJson();
}
await _booksRef().update(updateMap);
}
}

extension DataSnapshotExtension on DataSnapshot {
Expand Down
7 changes: 4 additions & 3 deletions lib/src/providers/authentication.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ AuthenticationRepository authenticationRepository(
) =>
FirebaseAuthenticationRepository(
ref.watch(firebaseAuthProvider),
ref.watch(googleSignInProvider),
);

@riverpod
Expand All @@ -42,13 +43,13 @@ Future<DanteUser?> user(UserRef ref) {
return ref.watch(authenticationRepositoryProvider).getAccount();
}

@riverpod
@Riverpod(keepAlive: true)
GoogleSignIn googleSignIn(
GoogleSignInRef ref,
) =>
GoogleSignIn(
clientId:
'150599422814-moto7djse1tf7vtso7slemniki76ohg6.apps.googleusercontent.com',
// clientId:
// '150599422814-moto7djse1tf7vtso7slemniki76ohg6.apps.googleusercontent.com',
scopes: [
DriveApi.driveFileScope,
],
Expand Down
1 change: 1 addition & 0 deletions lib/src/ui/book/book_item_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class BookItemWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return InkWell(
borderRadius: BorderRadius.circular(12.0),
onTap: () {
context.go(
DanteRoute.bookDetail.navigationUrl.replaceAll(':bookId', _book.id),
Expand Down
55 changes: 44 additions & 11 deletions lib/src/ui/main/book_state_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,26 +52,59 @@ class _BooksScreen extends ConsumerWidget {
_buildLargeLayout(bookRepository, columns: 3),
DeviceFormFactor.tablet =>
_buildLargeLayout(bookRepository, columns: 2),
DeviceFormFactor.phone => _buildPhoneLayout(
bookRepository,
),
DeviceFormFactor.phone => _buildPhoneLayout(bookRepository),
};
},
);
}

Widget _buildPhoneLayout(BookRepository bookRepository) {
return ListView.separated(
padding: const EdgeInsets.all(16.0),
return ReorderableListView.builder(
proxyDecorator: (child, index, animation) {
return Material(
color: Colors.transparent,
child: Stack(
children: [
Positioned(
top: 0,
left: 0,
right: 0,
bottom: 16,
child: Material(
borderRadius: BorderRadius.circular(16),
elevation: 24,
shadowColor: Colors.black.withOpacity(0.6),
),
),
child,
],
),
);
},
padding: const EdgeInsets.symmetric(horizontal: 16.0),
physics: const BouncingScrollPhysics(),
itemCount: books.length,
itemBuilder: (context, index) => _buildItem(
books[index],
bookRepository,
useMobileLayout: true,
itemBuilder: (context, index) => Column(
key: ValueKey(books[index].id),
children: [
_buildItem(
books[index],
bookRepository,
useMobileLayout: true,
),
const SizedBox(
height: 16,
),
],
),
separatorBuilder: (BuildContext context, int index) =>
const SizedBox(height: 16),
onReorder: (oldIndex, newIndex) async {
if (oldIndex < newIndex) {
newIndex -= 1;
}
final Book book = books.removeAt(oldIndex);
books.insert(newIndex, book);
await bookRepository.updatePositions(books);
},
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import 'package:dantex/src/data/authentication/entity/dante_user.dart';
import 'package:dantex/src/data/authentication/firebase_authentication_repository.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';

import 'firebase_authentication_repository_test.mocks.dart';

@GenerateMocks([
GoogleSignIn,
GoogleSignInAccount,
GoogleSignInAuthentication,
FirebaseAuth,
UserCredential,
User,
Expand All @@ -21,7 +25,8 @@ void main() {

test('Get account returns DanteUser', () async {
final fbAuth = MockFirebaseAuth();
final fbAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final fbAuthRepo = FirebaseAuthenticationRepository(fbAuth, googleSignIn);
final User user = MockUser();
final UserInfo userInfo = MockUserInfo();
final DanteUser danteUser = DanteUser(
Expand Down Expand Up @@ -56,18 +61,29 @@ void main() {
group('Login', () {
test('Login with Google returns user credential on success', () async {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);
final userCred = MockUserCredential();
final googleSignInAccount = MockGoogleSignInAccount();
final googleAuth = MockGoogleSignInAuthentication();

when(fbAuth.signInWithProvider(any)).thenAnswer((_) async => userCred);
when(googleSignIn.signIn()).thenAnswer((_) async => googleSignInAccount);
when(googleSignInAccount.authentication)
.thenAnswer((_) async => googleAuth);
when(googleAuth.idToken).thenReturn('idToken');
when(googleAuth.accessToken).thenReturn('accessToken');
when(fbAuth.signInWithCredential(any)).thenAnswer((_) async => userCred);

expect(await firebaseAuthRepo.loginWithGoogle(), userCred);
verify(fbAuth.signInWithProvider(any)).called(1);
verify(fbAuth.signInWithCredential(any)).called(1);
});

test('Login anonymously returns User Credential on success', () async {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);
final userCred = MockUserCredential();

when(fbAuth.signInAnonymously()).thenAnswer((_) async => userCred);
Expand All @@ -78,7 +94,9 @@ void main() {

test('Login with email returns User Credential on success', () async {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);
final userCred = MockUserCredential();

when(
Expand Down Expand Up @@ -106,7 +124,9 @@ void main() {

test('logout returns void on success', () async {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);

when(fbAuth.signOut()).thenAnswer((_) async => Future<void>);

Expand All @@ -118,7 +138,9 @@ void main() {
'fetchSignInMethodsForEmail maps sign in methods to AuthenticationSource',
() async {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);

when(fbAuth.fetchSignInMethodsForEmail(testEmail))
.thenAnswer((_) async => ['google.com', 'password', 'apple.com']);
Expand All @@ -137,7 +159,9 @@ void main() {

test('Create mail account returns User Credential on success', () async {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);
final userCred = MockUserCredential();

when(
Expand Down Expand Up @@ -165,7 +189,9 @@ void main() {
test('Upgrade anonymous account returns User Credential on success',
() async {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);
final user = MockUser();
final userCred = MockUserCredential();

Expand All @@ -190,7 +216,9 @@ void main() {
'Upgrade anonymous account throws FirebaseAuthException error when user not found',
() async {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);

when(
fbAuth.currentUser,
Expand All @@ -207,7 +235,9 @@ void main() {

test('Update user password returns void on success', () {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);
final user = MockUser();

when(fbAuth.currentUser).thenReturn(user);
Expand All @@ -223,7 +253,9 @@ void main() {
'Upgrade password throws FirebaseAuthException error when user not found',
() async {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);

when(
fbAuth.currentUser,
Expand All @@ -239,7 +271,9 @@ void main() {

test('Send password reset request returns void on success', () {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);

when(fbAuth.sendPasswordResetEmail(email: testEmail))
.thenAnswer((_) async => Future<void>);
Expand All @@ -250,7 +284,9 @@ void main() {

test('Delete user returns void on success', () async {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);
final User user = MockUser();

when(fbAuth.currentUser).thenReturn(user);
Expand All @@ -263,7 +299,9 @@ void main() {

test('Auth state changes returns DanteUser', () {
final fbAuth = MockFirebaseAuth();
final firebaseAuthRepo = FirebaseAuthenticationRepository(fbAuth);
final googleSignIn = MockGoogleSignIn();
final firebaseAuthRepo =
FirebaseAuthenticationRepository(fbAuth, googleSignIn);
final User user = MockUser();
final UserInfo userInfo = MockUserInfo();
final DanteUser danteUser = DanteUser(
Expand Down
Loading

0 comments on commit 74bebd1

Please sign in to comment.