Skip to content

Commit

Permalink
search
Browse files Browse the repository at this point in the history
  • Loading branch information
Mussabat committed Jan 27, 2024
1 parent f0bebdc commit ba9e5a5
Show file tree
Hide file tree
Showing 12 changed files with 263 additions and 165 deletions.
16 changes: 15 additions & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,24 @@ android {
]
}

signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}

buildTypes {
release {
signingConfig signingConfigs.release
}
}
}

flutter {
source '../..'
}

dependencies {}
dependencies {}
2 changes: 2 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:label="mammoth_task"
android:name="${applicationName}"
Expand Down
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:7.3.0'
classpath 'com.android.tools.build:gradle:7.4.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Expand Down
17 changes: 9 additions & 8 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ PODS:
- Flutter
- google_sign_in_ios (0.0.1):
- Flutter
- FlutterMacOS
- GoogleSignIn (~> 7.0)
- GoogleSignIn (7.0.0):
- AppAuth (~> 1.5)
Expand All @@ -39,7 +40,7 @@ DEPENDENCIES:
- app_links (from `.symlinks/plugins/app_links/ios`)
- Flutter (from `Flutter`)
- flutter_appauth (from `.symlinks/plugins/flutter_appauth/ios`)
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`)
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
Expand All @@ -61,7 +62,7 @@ EXTERNAL SOURCES:
flutter_appauth:
:path: ".symlinks/plugins/flutter_appauth/ios"
google_sign_in_ios:
:path: ".symlinks/plugins/google_sign_in_ios/ios"
:path: ".symlinks/plugins/google_sign_in_ios/darwin"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
shared_preferences_foundation:
Expand All @@ -77,16 +78,16 @@ SPEC CHECKSUMS:
app_links: 5ef33d0d295a89d9d16bb81b0e3b0d5f70d6c875
AppAuth: 3bb1d1cd9340bd09f5ed189fb00b1cc28e1e8570
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_appauth: cf9b928962105b2a64a9802585d1c8adaf3e0f46
google_sign_in_ios: 8115e3fbe097e6509beb819ed602d47369d9011f
flutter_appauth: 0863b1f33110b410213e736aead4a6727303f509
google_sign_in_ios: 1bfaf6607b44cd1b24c4d4bc39719870440f9ce1
GoogleSignIn: b232380cf495a429b8095d3178a8d5855b42e842
GTMAppAuth: 99fb010047ba3973b7026e45393f51f27ab965ae
GTMSessionFetcher: 41b9ef0b4c08a6db4b7eb51a21ae5183ec99a2c8
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440
url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b
webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
webview_flutter_wkwebview: 4f3e50f7273d31e5500066ed267e3ae4309c5ae4

PODFILE CHECKSUM: 70d9d25280d0dd177a5f637cdb0f0b0b12c6a189

Expand Down
18 changes: 18 additions & 0 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
0AD3B6913326E4142BF83758 /* [CP] Embed Pods Frameworks */,
3167BD514375E5010A87A6D3 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
Expand Down Expand Up @@ -286,6 +287,23 @@
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
3167BD514375E5010A87A6D3 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
Expand Down
6 changes: 6 additions & 0 deletions lib/core/enums/search_load_status.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
enum SearchLoadStatus {
initial,
loading,
loaded,
error,
}
6 changes: 3 additions & 3 deletions lib/profile/services/tag_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ class TagService {

Future<String?> _getTagId(String tag) async {
final tagResponse = await supabase.from('tags').select('id').eq('tag', tag);
final tagData = tagResponse as List<dynamic>;

if (tagResponse == null) return null;
if (tagData.isEmpty) return null;

final tagData = tagResponse as List<dynamic>;
final tagId = tagData.first['id'] as String;

return tagId;
Expand All @@ -89,7 +89,7 @@ class TagService {

await supabase.from('user_tags').insert({
'user_id': supabase.auth.currentUser!.id,
'tag_id': tagResponse,
'tag_id': tagResponse.first['id'] as String,
});
}

Expand Down
26 changes: 26 additions & 0 deletions lib/search/bloc/cubit/search_cubit.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:study_match/core/enums/search_load_status.dart';
import 'package:study_match/search/services/search_service.dart';

part 'search_state.dart';

class SearchCubit extends Cubit<SearchState> {
final _searchService = SearchService.instance;

SearchCubit() : super(const SearchState([], SearchLoadStatus.initial));

Future<void> searchUsers(String query) async {
emit(const SearchState([], SearchLoadStatus.loading));
if (query.isEmpty) {
emit(const SearchState([], SearchLoadStatus.initial));
return;
}
final users = await _searchService.searchUsers(query);
emit(SearchState(users, SearchLoadStatus.loaded));
}

void clearSearch() {
emit(const SearchState([], SearchLoadStatus.initial));
}
}
11 changes: 11 additions & 0 deletions lib/search/bloc/cubit/search_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
part of 'search_cubit.dart';

class SearchState extends Equatable {
final List<(String, String)> users;
final SearchLoadStatus status;

const SearchState(this.users, this.status);

@override
List<Object> get props => [users, status];
}
75 changes: 71 additions & 4 deletions lib/search/screens/search_screen.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,81 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:study_match/core/enums/search_load_status.dart';
import 'package:study_match/profile/profile_view.dart';
import 'package:study_match/search/bloc/cubit/search_cubit.dart';

class SearchScreen extends StatelessWidget {
const SearchScreen({super.key});

@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('Search Screen 🔎'),
),
return BlocProvider(
create: (context) => SearchCubit(),
child: const SearchPage(),
);
}
}

class SearchPage extends StatelessWidget {
const SearchPage({super.key});

@override
Widget build(BuildContext context) {
return BlocBuilder<SearchCubit, SearchState>(
builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: Row(
children: [
Expanded(
child: TextField(
decoration: const InputDecoration(
hintText: 'Search for a user',
),
onChanged: (value) {
context.read<SearchCubit>().searchUsers(value);
},
),
),
IconButton(
icon: const Icon(Icons.clear),
onPressed: () {
context.read<SearchCubit>().clearSearch();
},
),
],
),
),
body: _showSearchResults(context, state),
);
},
);
}
}

Widget _showSearchResults(BuildContext context, SearchState state) {
if (state.status == SearchLoadStatus.loading) {
return const Center(child: CircularProgressIndicator());
}

if (state.status == SearchLoadStatus.loaded) {
return ListView.builder(
itemCount: state.users.length,
itemBuilder: (context, index) {
final user = state.users[index];
return ListTile(
title: Text(user.$2),
onTap: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ProfileView(userID: user.$1),
),
),
);
},
);
}

return const Center(
child: Text('Your search results will appear here!'),
); //
}
25 changes: 25 additions & 0 deletions lib/search/services/search_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:supabase_flutter/supabase_flutter.dart';

class SearchService {
final supabase = Supabase.instance.client;
SearchService._();

Future<List<(String, String)>> searchUsers(String query) async {
final response = await supabase
.from('profiles')
.select('id, username')
.ilike('username', '%$query%');

if (response == []) return [];

final data = response as List<dynamic>;
final users = data.map((e) {
final userData = e as Map<String, dynamic>;
return (userData['id'] as String, userData['username'] as String);
}).toList();

return users;
}

static final SearchService instance = SearchService._();
}
Loading

0 comments on commit ba9e5a5

Please sign in to comment.