Skip to content

Commit

Permalink
feat: sign up screen (#11)
Browse files Browse the repository at this point in the history
* feat: sign up screen

* refactor: minor changes

* Include error message in the error body

* refactor: requested changes

---------

Co-authored-by: mirland <[email protected]>
  • Loading branch information
nicolantean and mirland authored Oct 17, 2023
1 parent b809c87 commit 1da29a8
Show file tree
Hide file tree
Showing 31 changed files with 631 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,21 @@ const supabaseClient = createClient(
);

serve(async (req) => {
const { id, message } = await req.json()
const { id } = await req.json()

const capitalizedMessage = message.toUpperCase()
const { data, error: getBodyError } = await supabaseClient.from("messages").select("body").eq("id", id)

const { error } = await supabaseClient.from("messages").update({ body: capitalizedMessage }).eq("id", id)
if (getBodyError != null) {
return new Response(JSON.stringify({ "message": "Error getting message body" }), { headers: { "Content-Type": "application/json" } },)
}

const body = data[0].body

const capitalizedMessage = body.toUpperCase()

const { error: updateMessageError } = await supabaseClient.from("messages").update({ body: capitalizedMessage }).eq("id", id)

if (error != null) {
if (updateMessageError != null) {
return new Response(JSON.stringify({ "message": "Error updating message" }), { headers: { "Content-Type": "application/json" } },)
}

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion supabase-ws-flutter-mobile/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 4e8f8b2be68aeea4c0d5beb6ff1e79fface1d048

COCOAPODS: 1.12.1
COCOAPODS: 1.11.3
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter_template/core/repository/session_repository.dart';
import 'package:flutter_template/core/source/auth_local_source.dart';
import 'package:flutter_template/core/source/auth_remote_source.dart';
import 'package:flutter_template/core/source/messages_remote_source.dart';
import 'package:flutter_template/core/source/users_remote_source.dart';
import 'package:get_it/get_it.dart';

class RepositoryDiModule {
Expand All @@ -22,7 +23,7 @@ class RepositoryDiModule {

extension _GetItDiModuleExtensions on GetIt {
void _setupRepositories() {
registerLazySingleton(() => MessagesRepository(get(), get()));
registerLazySingleton(() => MessagesRepository(get(), get(), get()));
registerLazySingleton(() => SessionRepository(get(), get()));
}

Expand All @@ -32,5 +33,8 @@ extension _GetItDiModuleExtensions on GetIt {
registerLazySingleton<MessagesRemoteSource>(
() => MessagesRemoteSourceImpl(get()),
);
registerLazySingleton<UsersRemoteSource>(
() => UsersRemoteSourceImpl(get()),
);
}
}
4 changes: 2 additions & 2 deletions supabase-ws-flutter-mobile/lib/core/model/message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ class MessageResponse with _$MessageResponse {
json.map((e) => MessageResponse.fromJson(e)).toList();
}

UserResponse _userResponseSerializer(dynamic data) =>
UserResponse.fromJson(data);
UserResponse? _userResponseSerializer(dynamic data) =>
data == data ? null : UserResponse.fromJson(data);

@freezed
class MessageRequest with _$MessageRequest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@ import 'package:flutter_template/core/model/message.dart';
import 'package:flutter_template/core/model/user_message.dart';
import 'package:flutter_template/core/source/auth_remote_source.dart';
import 'package:flutter_template/core/source/messages_remote_source.dart';
import 'package:flutter_template/core/source/users_remote_source.dart';
import 'package:rxdart/rxdart.dart';

class MessagesRepository {
static const _useMessageStream = true;

final MessagesRemoteSource _messagesRemoteSource;
final UsersRemoteSource _usersRemoteSource;
final AuthRemoteSource _authRemoteSource;

MessagesRepository(this._messagesRemoteSource, this._authRemoteSource);
MessagesRepository(
this._messagesRemoteSource,
this._usersRemoteSource,
this._authRemoteSource,
);

Stream<List<UserMessage>> getMessages() => _useMessageStream
? _getMessagesStream()
Expand All @@ -21,7 +27,7 @@ class MessagesRepository {

Stream<List<UserMessage>> _getMessagesStream() => Rx.combineLatest3(
_messagesRemoteSource.getMessagesStream(),
_messagesRemoteSource.getUsersStream(),
_usersRemoteSource.getUsersStream(),
_authRemoteSource.getUserId(),
(messages, users, currentUserId) => messages.toUserMessageList(
users: users,
Expand All @@ -32,6 +38,6 @@ class MessagesRepository {
Future<void> sendMessage(String body) =>
_messagesRemoteSource.sendMessage(body: body);

Future<void> uppercaseMessage(Message message) => _messagesRemoteSource
.uppercaseMessage(id: message.id, body: message.body);
Future<void> uppercaseMessage(Message message) =>
_messagesRemoteSource.uppercaseMessage(id: message.id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ class SessionRepository {
await _authRemoteSource.signIn(email: email, password: password);
}

Future<void> signUpUser({
required String email,
required String password,
required String alias,
}) =>
_authRemoteSource.signUp(
alias: alias,
email: email,
password: password,
);

Future<void> logOut() async {
await _authLocalSource.saveUserToken(null);
await _authLocalSource.saveUserInfo(null);
Expand Down
27 changes: 18 additions & 9 deletions supabase-ws-flutter-mobile/lib/core/source/auth_remote_source.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,29 @@ class AuthRemoteSourceImpl implements AuthRemoteSource {
_supabaseClient.auth
.signInWithPassword(email: email, password: password)
.then(
(authResponse) =>
User(email: authResponse.user!.email!, name: "TODO"),
(authResponse) => User(
email: authResponse.user!.email!,
name: authResponse.user?.userMetadata!['alias'] as String,
),
);

@override
Future<void> signOut() => _supabaseClient.auth.signOut();

@override
Future<User> signUp({
required String alias,
required String email,
required String password,
}) {
// TODO: implement signUp
throw UnimplementedError();
}
}) =>
_supabaseClient.auth.signUp(
email: email,
password: password,
data: {'alias': alias},
).then(
(authResponse) => User(
email: authResponse.user!.email!,
name: authResponse.user?.userMetadata!['alias'] as String,
),
);

@override
Future<void> signOut() => _supabaseClient.auth.signOut();
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import 'dart:async';

import 'package:flutter_template/core/model/message.dart';
import 'package:flutter_template/core/model/user.dart';
import 'package:flutter_template/core/model/user_message.dart';
import 'package:supabase_flutter/supabase_flutter.dart' hide UserResponse;

abstract interface class MessagesRemoteSource {
Future<List<UserMessage>> getMessages();
Stream<List<Message>> getMessagesStream();
Stream<List<UserResponse>> getUsersStream();
Future<void> sendMessage({required String body});
Future<void> uppercaseMessage({required String id, required String body});
Future<void> uppercaseMessage({required String id});
}

class MessagesRemoteSourceImpl implements MessagesRemoteSource {
Expand Down Expand Up @@ -39,22 +37,15 @@ class MessagesRemoteSourceImpl implements MessagesRemoteSource {
(response) => Message.fromJsonList(response),
);

@override
Stream<List<UserResponse>> getUsersStream() =>
_supabaseClient.from('users').stream(primaryKey: ['id']).map(
(response) => UserResponse.fromJsonList(response),
);

@override
Future<void> sendMessage({required String body}) async {
final currentUserId = _supabaseClient.auth.currentUser!.id;
return _supabaseClient
.from('messages')
.insert(MessageRequest(body: body, sender: currentUserId));
.insert(MessageRequest(body: body, sender: currentUserId).toJson());
}

@override
Future<void> uppercaseMessage({required String id, required String body}) =>
_supabaseClient.functions
.invoke('uppercase_message', body: {"id": id, "message": body});
Future<void> uppercaseMessage({required String id}) =>
_supabaseClient.functions.invoke('uppercase_message', body: {"id": id});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'dart:async';

import 'package:flutter_template/core/model/user.dart';
import 'package:supabase_flutter/supabase_flutter.dart' hide UserResponse;

abstract interface class UsersRemoteSource {
Stream<List<UserResponse>> getUsersStream();
}

class UsersRemoteSourceImpl implements UsersRemoteSource {
final SupabaseClient _supabaseClient;

UsersRemoteSourceImpl(this._supabaseClient);

@override
Stream<List<UserResponse>> getUsersStream() =>
_supabaseClient.from('users').stream(primaryKey: ['id']).map(
(response) => UserResponse.fromJsonList(response),
);
}
5 changes: 4 additions & 1 deletion supabase-ws-flutter-mobile/lib/gen/assets.gen.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions supabase-ws-flutter-mobile/lib/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,10 @@
"mail": "Mail",
"password": "Password",
"sign_in": "Sign In",
"sign_up": "Sign Up",
"sign_up_already_have_an_account": "Already have an account?",
"sign_up_email_label": "Email address",
"sign_up_password_label": "Password",
"sign_up_username_label": "Username",
"xmartlabs_projects": "Xmartlabs' projects"
}
12 changes: 6 additions & 6 deletions supabase-ws-flutter-mobile/lib/ui/home/home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) => BlocProvider(
create: (context) => HomeCubit(context.read<GlobalEventHandlerCubit>()),
child: _WelcomeContentScreen(),
child: _HomeContentScreen(),
);
}

class _WelcomeContentScreen extends StatefulWidget {
class _HomeContentScreen extends StatefulWidget {
@override
State<_WelcomeContentScreen> createState() => _WelcomeContentScreenState();
State<_HomeContentScreen> createState() => _HomeContentScreenState();
}

class _WelcomeContentScreenState extends State<_WelcomeContentScreen> {
class _HomeContentScreenState extends State<_HomeContentScreen> {
final _textController = TextEditingController();

@override
Expand All @@ -47,8 +47,8 @@ class _WelcomeContentScreenState extends State<_WelcomeContentScreen> {
IconButton(
icon: const Icon(Icons.more_vert),
color: context.theme.colors.textColor.shade100,
//TODO: add logic
onPressed: () => {},
//TODO: change it later to show a menu
onPressed: () => context.read<HomeCubit>().logOut(),
),
],
),
Expand Down
6 changes: 4 additions & 2 deletions supabase-ws-flutter-mobile/lib/ui/router/app_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import 'package:auto_route/auto_route.dart';
import 'package:flutter_template/core/repository/session_repository.dart';
import 'package:flutter_template/ui/router/app_router_guards.dart';
import 'package:flutter_template/ui/section/section_router.dart';
import 'package:flutter_template/ui/signin/signin_screen.dart';
import 'package:flutter_template/ui/sign_in/sign_in_screen.dart';
import 'package:flutter_template/ui/sign_up/sign_up_screen.dart';
import 'package:flutter_template/ui/home/home_screen.dart';

part 'app_router.gr.dart';
Expand All @@ -26,7 +27,8 @@ class AppRouter extends _$AppRouter {
path: '/',
guards: [UnauthenticatedGuard(sessionRepository)],
children: [
RedirectRoute(path: '', redirectTo: 'login'),
RedirectRoute(path: '', redirectTo: 'sign_up'),
AutoRoute(path: 'sign_up', page: SignUpRoute.page),
AutoRoute(path: 'login', page: SignInRoute.page),
],
),
Expand Down
20 changes: 20 additions & 0 deletions supabase-ws-flutter-mobile/lib/ui/router/app_router.gr.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions supabase-ws-flutter-mobile/lib/ui/section/section_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ class SectionRouter extends StatelessWidget {
BuildContext context,
) =>
switch (errorType) {
UnknownError(retry: final retry) => _showDialog(
UnknownError(error: final error, retry: final retry) => _showDialog(
context,
context.localizations.error_unknown_error_title,
context.localizations.error_unknown_error_description,
error?.toString() ??
context.localizations.error_unknown_error_description,
retry,
),
InternetError(retry: final retry) => _showDialog(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import 'package:flutter_template/core/repository/session_repository.dart';
import 'package:flutter_template/ui/section/error_handler/global_event_handler_cubit.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

part 'signin_cubit.freezed.dart';
part 'sign_in_cubit.freezed.dart';

part 'signin_state.dart';
part 'sign_in_state.dart';

class SignInCubit extends Cubit<SignInBaseState> {
final GlobalEventHandler _globalEventHandler;
Expand All @@ -24,7 +24,8 @@ class SignInCubit extends Cubit<SignInBaseState> {

void changeEmail(String email) => emit(state.copyWith(email: email));

void changePassword(String email) => emit(state.copyWith(email: email));
void changePassword(String password) =>
emit(state.copyWith(password: password));

Future<void> signIn() => _sessionRepository
.signInUser(email: state.email!, password: state.password!)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 1da29a8

Please sign in to comment.