diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 4662933..a752976 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -30,4 +30,7 @@
android:name="flutterEmbedding"
android:value="2" />
+
+
+
diff --git a/lib/main.dart b/lib/main.dart
index 94679f0..3dd3002 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,26 +1,80 @@
import 'package:flutter/material.dart';
import 'package:learn_project/screens/home.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
+import 'package:learn_project/screens/account_page.dart';
+import 'package:learn_project/screens/login_page.dart';
+import 'package:learn_project/screens/splash_page.dart';
+import 'utils/constants.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Supabase.initialize(
- url: 'http://192.168.179.86:8000/',
- anonKey: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InZ2dGVmcWRxYWhjcHpnb2x2dXB2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTYwMjE2NTIsImV4cCI6MjAzMTU5NzY1Mn0.1bp5V61Oguo5zLUhCFJmCabUY1sujeISr_CR2XUKvh4',
+ url: 'http://192.168.179.86:8000/',//'https://vvtefqdqahcpzgolvupv.supabase.co',//'https://vvtefqdqahcpzgolvupv.supabase.co',//
+ anonKey: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InZ2dGVmcWRxYWhjcHpnb2x2dXB2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTYwMjE2NTIsImV4cCI6MjAzMTU5NzY1Mn0.1bp5V61Oguo5zLUhCFJmCabUY1sujeISr_CR2XUKvh4',//'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InZ2dGVmcWRxYWhjcHpnb2x2dXB2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTYwMjE3ODksImV4cCI6MjAzMTU5Nzc4OX0.6g5EtS9HrgxC6cpCYgOT0HLpA4lEnASQbKs9mfnUM7k',//Constants.supabaseAnnonKey,//
);
- runApp(const MyApp());
+ runApp( MyApp());
}
-
/// Supabase client
final supabase = Supabase.instance.client;
/// Error message to display the user when unexpected error occurs.
const unexpectedErrorMessage = 'Unexpected error occurred.';
+
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
+ Widget build(BuildContext context) {
+ return const MaterialApp(
+ title: 'Events',
+ home: HomePage(),
+ );
+ }
+}
+
+class HomePage extends StatefulWidget {
+ const HomePage({super.key});
+
+ @override
+ State createState() => _HomePageState();
+}
+
+class _HomePageState extends State {
+ final _future = Supabase.instance.client
+ .from('events')
+ .select();
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: FutureBuilder(
+ future: _future,
+ builder: (context, snapshot) {
+ if (!snapshot.hasData) {
+ return const Center(child: CircularProgressIndicator());
+ }
+ final events = snapshot.data!;
+ return ListView.builder(
+ itemCount: events.length,
+ itemBuilder: ((context, index) {
+ final event = events[index];
+ return ListTile(
+ title: Text(event['name']),
+ subtitle: Text(event['description']),
+ );
+ }),
+ );
+ },
+ ),
+ );
+ }
+}
+
+/* class MyApp extends StatelessWidget { */
+ //MyApp({super.key});
+
+ /* @override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
@@ -33,5 +87,74 @@ class MyApp extends StatelessWidget {
),
home: const HomePage(),
);
- }
+ } */
+
+
+
+ /* @override
+ Widget build(BuildContext context) {
+
+ return MaterialApp(
+ title: 'Supabase Flutter',
+ theme: ThemeData.dark().copyWith(
+ primaryColor: Colors.green,
+ textButtonTheme: TextButtonThemeData(
+ style: TextButton.styleFrom(
+ foregroundColor: Colors.green,
+ ),
+ ),
+ elevatedButtonTheme: ElevatedButtonThemeData(
+ style: ElevatedButton.styleFrom(
+ foregroundColor: Colors.white,
+ backgroundColor: Colors.green,
+ ),
+ ),
+ ),
+ initialRoute: '/',
+ routes: {
+ '/': (_) => const SplashPage(),
+ '/login': (_) => const LoginPage(),
+ '/account': (_) => const AccountPage(),
+ },
+ );
+ } */
+/* Future readData() async {
+ final response = await Supabase.instance.client.from('events').select();
+ if (response.error == null) {
+ final data = response.data;
+ print('Fetched data: $data');
+ } else {
+ print('Error reading data: ${response.error!.message}');
+ }}
+
+ final _future = Supabase.instance.client
+ .from('events')
+ .select();
+ @override
+ Widget build(BuildContext context) {
+ return Directionality(
+ textDirection: TextDirection.ltr,
+ child: Scaffold(
+ appBar: AppBar(
+ title: Text('Home Page'),
+ ),
+ body: FutureBuilder(
+ future: _future,
+ builder: (context, snapshot) {
+
}
+ final countries = snapshot.data!;
+ return ListView.builder(
+ itemCount: countries.length,
+ itemBuilder: ((context, index) {
+ final country = countries[index];
+ return ListTile(
+ title: Text(country['name']),
+ );
+ }),
+ );})));
+ }
+}
+
+class _execute {
+}*/
\ No newline at end of file
diff --git a/lib/screens/account_page.dart b/lib/screens/account_page.dart
new file mode 100644
index 0000000..b8d8b4e
--- /dev/null
+++ b/lib/screens/account_page.dart
@@ -0,0 +1,163 @@
+import 'package:flutter/material.dart';
+import 'package:supabase_flutter/supabase_flutter.dart';
+import 'package:learn_project/main.dart';
+
+class AccountPage extends StatefulWidget {
+ const AccountPage({super.key});
+
+ @override
+ State createState() => _AccountPageState();
+}
+
+class _AccountPageState extends State {
+ final _usernameController = TextEditingController();
+ final _websiteController = TextEditingController();
+
+ var _loading = true;
+
+ /// Called once a user id is received within `onAuthenticated()`
+ Future _getProfile() async {
+ setState(() {
+ _loading = true;
+ });
+
+ try {
+ final userId = supabase.auth.currentUser!.id;
+ final data =
+ await supabase.from('profiles').select().eq('id', userId).single();
+ _usernameController.text = (data['username'] ?? '') as String;
+ _websiteController.text = (data['website'] ?? '') as String;
+ } on PostgrestException catch (error) {
+ if (mounted) {
+ SnackBar(
+ content: Text(error.message),
+ backgroundColor: Theme.of(context).colorScheme.error,
+ );
+ }
+ } catch (error) {
+ if (mounted) {
+ SnackBar(
+ content: const Text('Unexpected error occurred'),
+ backgroundColor: Theme.of(context).colorScheme.error,
+ );
+ }
+ } finally {
+ if (mounted) {
+ setState(() {
+ _loading = false;
+ });
+ }
+ }
+ }
+
+ /// Called when user taps `Update` button
+ Future _updateProfile() async {
+ setState(() {
+ _loading = true;
+ });
+ final userName = _usernameController.text.trim();
+ final website = _websiteController.text.trim();
+ final user = supabase.auth.currentUser;
+ final updates = {
+ 'id': user!.id,
+ 'username': userName,
+ 'website': website,
+ 'updated_at': DateTime.now().toIso8601String(),
+ };
+ try {
+ await supabase.from('profiles').upsert(updates);
+ if (mounted) {
+ const SnackBar(
+ content: Text('Successfully updated profile!'),
+ );
+ }
+ } on PostgrestException catch (error) {
+ if (mounted) {
+ SnackBar(
+ content: Text(error.message),
+ backgroundColor: Theme.of(context).colorScheme.error,
+ );
+ }
+ } catch (error) {
+ if (mounted) {
+ SnackBar(
+ content: const Text('Unexpected error occurred'),
+ backgroundColor: Theme.of(context).colorScheme.error,
+ );
+ }
+ } finally {
+ if (mounted) {
+ setState(() {
+ _loading = false;
+ });
+ }
+ }
+ }
+
+ Future _signOut() async {
+ try {
+ await supabase.auth.signOut();
+ } on AuthException catch (error) {
+ if (mounted) {
+ SnackBar(
+ content: Text(error.message),
+ backgroundColor: Theme.of(context).colorScheme.error,
+ );
+ }
+ } catch (error) {
+ if (mounted) {
+ SnackBar(
+ content: const Text('Unexpected error occurred'),
+ backgroundColor: Theme.of(context).colorScheme.error,
+ );
+ }
+ } finally {
+ if (mounted) {
+ Navigator.of(context).pushReplacementNamed('/login');
+ }
+ }
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ _getProfile();
+ }
+
+ @override
+ void dispose() {
+ _usernameController.dispose();
+ _websiteController.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('Profile')),
+ body: _loading
+ ? const Center(child: CircularProgressIndicator())
+ : ListView(
+ padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 12),
+ children: [
+ TextFormField(
+ controller: _usernameController,
+ decoration: const InputDecoration(labelText: 'User Name'),
+ ),
+ const SizedBox(height: 18),
+ TextFormField(
+ controller: _websiteController,
+ decoration: const InputDecoration(labelText: 'Website'),
+ ),
+ const SizedBox(height: 18),
+ ElevatedButton(
+ onPressed: _loading ? null : _updateProfile,
+ child: Text(_loading ? 'Saving...' : 'Update'),
+ ),
+ const SizedBox(height: 18),
+ TextButton(onPressed: _signOut, child: const Text('Sign Out')),
+ ],
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/screens/details.dart b/lib/screens/details.dart
index c18428a..9580eea 100644
--- a/lib/screens/details.dart
+++ b/lib/screens/details.dart
@@ -1,12 +1,38 @@
import 'package:flutter/material.dart';
import 'package:learn_project/utils/class.dart';
import 'package:learn_project/utils/widgets.dart';
+import 'package:supabase_flutter/supabase_flutter.dart';
class DetailsPage extends StatelessWidget {
- final Recipe recipe;
- const DetailsPage({required this.recipe});
-
- @override
+ //final Recipe recipe;
+ final _future = Supabase.instance.client
+ .from('events')
+ .select();
+ //const DetailsPage({required this.recipe});
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: FutureBuilder(
+ future: _future,
+ builder: (context, snapshot) {
+ if (!snapshot.hasData) {
+ return const Center(child: CircularProgressIndicator());
+ }
+ final events = snapshot.data!;
+ return ListView.builder(
+ itemCount: events.length,
+ itemBuilder: ((context, index) {
+ final event = events[index];
+ return ListTile(
+ title: Text(event['name']),
+ );
+ }),
+ );
+ },
+ ),
+ );
+ }
+ /* @override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
@@ -69,7 +95,7 @@ class DetailsPage extends StatelessWidget {
),
),
);
- }
+ } */
}
class RecipeSteps extends StatelessWidget {
diff --git a/lib/screens/home.dart b/lib/screens/home.dart
index f9411e9..0b5da6e 100644
--- a/lib/screens/home.dart
+++ b/lib/screens/home.dart
@@ -144,7 +144,7 @@ class HomePage extends StatelessWidget {
context,
MaterialPageRoute(
builder: (context) => DetailsPage(
- recipe: Data.recipes[index],
+ //_future: Data.recipes[index],
)));
},
child: Card(
diff --git a/lib/screens/login_page.dart b/lib/screens/login_page.dart
new file mode 100644
index 0000000..23e01c0
--- /dev/null
+++ b/lib/screens/login_page.dart
@@ -0,0 +1,102 @@
+import 'dart:async';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:supabase_flutter/supabase_flutter.dart';
+import 'package:learn_project/main.dart';
+
+class LoginPage extends StatefulWidget {
+ const LoginPage({super.key});
+
+ @override
+ State createState() => _LoginPageState();
+}
+
+class _LoginPageState extends State {
+ bool _isLoading = false;
+ bool _redirecting = false;
+ late final TextEditingController _emailController = TextEditingController();
+ late final StreamSubscription _authStateSubscription;
+
+ Future _signIn() async {
+ try {
+ setState(() {
+ _isLoading = true;
+ });
+ await supabase.auth.signInWithOtp(
+ email: _emailController.text.trim(),
+ emailRedirectTo:
+ kIsWeb ? null : 'io.supabase.flutterquickstart://login-callback/',
+ );
+ if (mounted) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text('Check your email for a login link!')),
+ );
+ _emailController.clear();
+ }
+ } on AuthException catch (error) {
+ if (mounted) {
+ SnackBar(
+ content: Text(error.message),
+ backgroundColor: Theme.of(context).colorScheme.error,
+ );
+ }
+ } catch (error) {
+ if (mounted) {
+ SnackBar(
+ content: const Text('Unexpected error occurred'),
+ backgroundColor: Theme.of(context).colorScheme.error,
+ );
+ }
+ } finally {
+ if (mounted) {
+ setState(() {
+ _isLoading = false;
+ });
+ }
+ }
+ }
+
+ @override
+ void initState() {
+ _authStateSubscription = supabase.auth.onAuthStateChange.listen((data) {
+ if (_redirecting) return;
+ final session = data.session;
+ if (session != null) {
+ _redirecting = true;
+ Navigator.of(context).pushReplacementNamed('/account');
+ }
+ });
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ _emailController.dispose();
+ _authStateSubscription.cancel();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('Sign In')),
+ body: ListView(
+ padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 12),
+ children: [
+ const Text('Sign in via the magic link with your email below'),
+ const SizedBox(height: 18),
+ TextFormField(
+ controller: _emailController,
+ decoration: const InputDecoration(labelText: 'Email'),
+ ),
+ const SizedBox(height: 18),
+ ElevatedButton(
+ onPressed: _isLoading ? null : _signIn,
+ child: Text(_isLoading ? 'Loading' : 'Send Magic Link'),
+ ),
+ ],
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/screens/splash_page.dart b/lib/screens/splash_page.dart
new file mode 100644
index 0000000..2bfffdf
--- /dev/null
+++ b/lib/screens/splash_page.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+import 'package:learn_project/main.dart';
+
+class SplashPage extends StatefulWidget {
+ const SplashPage({super.key});
+
+ @override
+ State createState() => _SplashPageState();
+}
+
+class _SplashPageState extends State {
+ @override
+ void initState() {
+ super.initState();
+ _redirect();
+ }
+
+ Future _redirect() async {
+ await Future.delayed(Duration.zero);
+ if (!mounted) {
+ return;
+ }
+
+ final session = supabase.auth.currentSession;
+ if (session != null) {
+ Navigator.of(context).pushReplacementNamed('/account');
+ } else {
+ Navigator.of(context).pushReplacementNamed('/login');
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return const Scaffold(
+ body: Center(child: CircularProgressIndicator()),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart
index ec5ccce..8e26a98 100644
--- a/lib/utils/constants.dart
+++ b/lib/utils/constants.dart
@@ -1,83 +1,14 @@
-import 'package:flutter/material.dart';
-import 'package:supabase_flutter/supabase_flutter.dart';
+/// Environment variables and shared app constants.
+abstract class Constants {
+ static const String supabaseUrl = String.fromEnvironment(
+ //'http://192.168.179.86:8000/', //local
+ 'https://vvtefqdqahcpzgolvupv.supabase.co',
+ //defaultValue: '',
+ );
-/// Supabase client
-final supabase = Supabase.instance.client;
-
-/// Simple preloader inside a Center widget
-const preloader =
- Center(child: CircularProgressIndicator(color: Colors.orange));
-
-/// Simple sized box to space out form elements
-const formSpacer = SizedBox(width: 16, height: 16);
-
-/// Some padding for all the forms to use
-const formPadding = EdgeInsets.symmetric(vertical: 20, horizontal: 16);
-
-/// Error message to display the user when unexpected error occurs.
-const unexpectedErrorMessage = 'Unexpected error occurred.';
-
-/// Basic theme to change the look and feel of the app
-final appTheme = ThemeData.light().copyWith(
- primaryColorDark: Colors.orange,
- appBarTheme: const AppBarTheme(
- elevation: 1,
- backgroundColor: Colors.white,
- iconTheme: IconThemeData(color: Colors.black),
- titleTextStyle: TextStyle(
- color: Colors.black,
- fontSize: 18,
- ),
- ),
- primaryColor: Colors.orange,
- textButtonTheme: TextButtonThemeData(
- style: TextButton.styleFrom(
- foregroundColor: Colors.orange,
- ),
- ),
- elevatedButtonTheme: ElevatedButtonThemeData(
- style: ElevatedButton.styleFrom(
- foregroundColor: Colors.white,
- backgroundColor: Colors.orange,
- ),
- ),
- inputDecorationTheme: InputDecorationTheme(
- floatingLabelStyle: const TextStyle(
- color: Colors.orange,
- ),
- border: OutlineInputBorder(
- borderRadius: BorderRadius.circular(12),
- borderSide: const BorderSide(
- color: Colors.grey,
- width: 2,
- ),
- ),
- focusColor: Colors.orange,
- focusedBorder: OutlineInputBorder(
- borderRadius: BorderRadius.circular(12),
- borderSide: const BorderSide(
- color: Colors.orange,
- width: 2,
- ),
- ),
- ),
-);
-
-/// Set of extension methods to easily display a snackbar
-extension ShowSnackBar on BuildContext {
- /// Displays a basic snackbar
- void showSnackBar({
- required String message,
- Color backgroundColor = Colors.white,
- }) {
- ScaffoldMessenger.of(this).showSnackBar(SnackBar(
- content: Text(message),
- backgroundColor: backgroundColor,
- ));
- }
-
- /// Displays a red snackbar indicating error
- void showErrorSnackBar({required String message}) {
- showSnackBar(message: message, backgroundColor: Colors.red);
- }
-}
+ static const String supabaseAnnonKey = String.fromEnvironment(
+ //'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InZ2dGVmcWRxYWhjcHpnb2x2dXB2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTYwMjE2NTIsImV4cCI6MjAzMTU5NzY1Mn0.1bp5V61Oguo5zLUhCFJmCabUY1sujeISr_CR2XUKvh4', // local
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InZ2dGVmcWRxYWhjcHpnb2x2dXB2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTYwMjE3ODksImV4cCI6MjAzMTU5Nzc4OX0.6g5EtS9HrgxC6cpCYgOT0HLpA4lEnASQbKs9mfnUM7k',
+ //defaultValue: '',
+ );
+}
\ No newline at end of file
diff --git a/lib/utils/data.dart b/lib/utils/data.dart
index a2ef953..a3ea1e2 100644
--- a/lib/utils/data.dart
+++ b/lib/utils/data.dart
@@ -1,5 +1,9 @@
-import 'package:learn_project/utils/class.dart';
+import 'dart:async';
+import 'package:flutter/material.dart';
+import 'package:learn_project/utils/class.dart';
+const Duration fakeAPIDuration = Duration(milliseconds: 50);
+const Duration debounceDuration = Duration(milliseconds: 50);
class Data {
static List recipes = [
Recipe(
@@ -124,4 +128,175 @@ class Data {
'4 ounces milk'
]),
];
+
+
+
+
}
+
+
+/* class _AsyncAutocomplete extends StatefulWidget {
+ const _AsyncAutocomplete();
+
+ @override
+ State<_AsyncAutocomplete> createState() => _AsyncAutocompleteState();
+}
+
+class _AsyncAutocompleteState extends State<_AsyncAutocomplete> {
+ // The query currently being searched for. If null, there is no pending
+ // request.
+ String? _currentQuery;
+
+ // The most recent options received from the API.
+ late Iterable _lastOptions = [];
+
+ late final _Debounceable?, String> _debouncedSearch;
+
+ // Whether to consider the fake network to be offline.
+ bool _networkEnabled = true;
+
+ // A network error was recieved on the most recent query.
+ bool _networkError = false;
+
+ // Calls the "remote" API to search with the given query. Returns null when
+ // the call has been made obsolete.
+ Future?> _search(String query) async {
+ _currentQuery = query;
+
+ late final Iterable options;
+ try {
+ options = await _FakeAPI.search(_currentQuery!, _networkEnabled);
+ } catch (error) {
+ if (error is _NetworkException) {
+ setState(() {
+ _networkError = true;
+ });
+ return [];
+ }
+ rethrow;
+ }
+
+ // If another search happened after this one, throw away these options.
+ if (_currentQuery != query) {
+ return null;
+ }
+ _currentQuery = null;
+
+ return options;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ // TODO: implement build
+ throw UnimplementedError();
+ }
+}
+ // Mimics a remote API.
+class _FakeAPI {
+ static const List _kOptions = [
+ 'ingolstadt',
+ 'jesuitenstraße',
+ 'eiskeller',
+ ];
+
+ // Searches the options, but injects a fake "network" delay.
+ static Future> search(
+ String query, bool networkEnabled) async {
+ await Future.delayed(fakeAPIDuration); // Fake 1 second delay.
+ if (!networkEnabled) {
+ throw const _NetworkException();
+ }
+ if (query == '') {
+ return const Iterable.empty();
+ }
+ return _kOptions.where((String option) {
+ return option.contains(query.toLowerCase());
+ });
+ }
+}
+
+typedef _Debounceable = Future Function(T parameter);
+
+/// Returns a new function that is a debounced version of the given function.
+///
+/// This means that the original function will be called only after no calls
+/// have been made for the given Duration.
+_Debounceable _debounce(_Debounceable function) {
+ _DebounceTimer? debounceTimer;
+
+ return (T parameter) async {
+ if (debounceTimer != null && !debounceTimer!.isCompleted) {
+ debounceTimer!.cancel();
+ }
+ debounceTimer = _DebounceTimer();
+ try {
+ await debounceTimer!.future;
+ } catch (error) {
+ if (error is _CancelException) {
+ return null;
+ }
+ rethrow;
+ }
+ return function(parameter);
+ };
+}
+
+// A wrapper around Timer used for debouncing.
+class _DebounceTimer {
+ _DebounceTimer() {
+ _timer = Timer(debounceDuration, _onComplete);
+ }
+
+ late final Timer _timer;
+ final Completer _completer = Completer();
+
+ void _onComplete() {
+ _completer.complete();
+ }
+
+ Future get future => _completer.future;
+
+ bool get isCompleted => _completer.isCompleted;
+
+ void cancel() {
+ _timer.cancel();
+ _completer.completeError(const _CancelException());
+ }
+}
+
+// An exception indicating that the timer was canceled.
+class _CancelException implements Exception {
+ const _CancelException();
+}
+
+// An exception indicating that a network request has failed.
+class _NetworkException implements Exception {
+ const _NetworkException();
+}
+ final _future = Supabase.instance.client
+ .from('countries')
+ .select();
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: FutureBuilder(
+ future: _future,
+ builder: (context, snapshot) {
+ if (!snapshot.hasData) {
+ return const Center(child: CircularProgressIndicator());
+ }
+ final countries = snapshot.data!;
+ return ListView.builder(
+ itemCount: countries.length,
+ itemBuilder: ((context, index) {
+ final country = countries[index];
+ return ListTile(
+ title: Text(country['name']),
+ );
+ }),
+ );
+ },
+ ),
+ );
+ } */
\ No newline at end of file
diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc
index 3792af4..e12c657 100644
--- a/linux/flutter/generated_plugin_registrant.cc
+++ b/linux/flutter/generated_plugin_registrant.cc
@@ -6,10 +6,14 @@
#include "generated_plugin_registrant.h"
+#include
#include
#include
void fl_register_plugins(FlPluginRegistry* registry) {
+ g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
+ fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
+ file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) gtk_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin");
gtk_plugin_register_with_registrar(gtk_registrar);
diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake
index 5d07423..4453582 100644
--- a/linux/flutter/generated_plugins.cmake
+++ b/linux/flutter/generated_plugins.cmake
@@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
+ file_selector_linux
gtk
url_launcher_linux
)
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 92b6497..d32ccbe 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -6,12 +6,14 @@ import FlutterMacOS
import Foundation
import app_links
+import file_selector_macos
import path_provider_foundation
import shared_preferences_foundation
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin"))
+ FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
diff --git a/macos/Podfile.lock b/macos/Podfile.lock
new file mode 100644
index 0000000..1ecc3ee
--- /dev/null
+++ b/macos/Podfile.lock
@@ -0,0 +1,42 @@
+PODS:
+ - app_links (1.0.0):
+ - FlutterMacOS
+ - FlutterMacOS (1.0.0)
+ - path_provider_foundation (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - shared_preferences_foundation (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - url_launcher_macos (0.0.1):
+ - FlutterMacOS
+
+DEPENDENCIES:
+ - app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`)
+ - FlutterMacOS (from `Flutter/ephemeral`)
+ - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
+ - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
+ - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
+
+EXTERNAL SOURCES:
+ app_links:
+ :path: Flutter/ephemeral/.symlinks/plugins/app_links/macos
+ FlutterMacOS:
+ :path: Flutter/ephemeral
+ path_provider_foundation:
+ :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
+ shared_preferences_foundation:
+ :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
+ url_launcher_macos:
+ :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
+
+SPEC CHECKSUMS:
+ app_links: 10e0a0ab602ffaf34d142cd4862f29d34b303b2a
+ FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
+ path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
+ shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
+ url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
+
+PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367
+
+COCOAPODS: 1.14.3
diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj
index 98b579c..aef2333 100644
--- a/macos/Runner.xcodeproj/project.pbxproj
+++ b/macos/Runner.xcodeproj/project.pbxproj
@@ -21,12 +21,14 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
+ 0F01822AA9A9E9749238513B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 311DE641954640D99B1B4FE4 /* Pods_Runner.framework */; };
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
+ C6804CBBFD4C528011277B05 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECFEDF50F009974C064DFA75 /* Pods_RunnerTests.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -60,11 +62,13 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 2300B308B78E43D2FDF50990 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; };
+ 311DE641954640D99B1B4FE4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; };
- 33CC10ED2044A3C60003C045 /* learn_project.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "learn_project.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 33CC10ED2044A3C60003C045 /* learn_project.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = learn_project.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
@@ -76,8 +80,14 @@
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; };
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; };
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; };
+ 4DDE30153BF6FBE35130B07A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; };
+ BF57888D5C07BC59C7600C12 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
+ C02918AD8AEC830CF0676619 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
+ D6246F994D1DCD4DC57DD5E5 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; };
+ ECFEDF50F009974C064DFA75 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ EEFA829C491B67BB2695D9B1 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -85,6 +95,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ C6804CBBFD4C528011277B05 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -92,12 +103,27 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 0F01822AA9A9E9749238513B /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 04AF439F2AB063A1706FF61C /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ 4DDE30153BF6FBE35130B07A /* Pods-Runner.debug.xcconfig */,
+ BF57888D5C07BC59C7600C12 /* Pods-Runner.release.xcconfig */,
+ C02918AD8AEC830CF0676619 /* Pods-Runner.profile.xcconfig */,
+ EEFA829C491B67BB2695D9B1 /* Pods-RunnerTests.debug.xcconfig */,
+ D6246F994D1DCD4DC57DD5E5 /* Pods-RunnerTests.release.xcconfig */,
+ 2300B308B78E43D2FDF50990 /* Pods-RunnerTests.profile.xcconfig */,
+ );
+ name = Pods;
+ path = Pods;
+ sourceTree = "";
+ };
331C80D6294CF71000263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
@@ -125,6 +151,7 @@
331C80D6294CF71000263BE5 /* RunnerTests */,
33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */,
+ 04AF439F2AB063A1706FF61C /* Pods */,
);
sourceTree = "";
};
@@ -175,6 +202,8 @@
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 311DE641954640D99B1B4FE4 /* Pods_Runner.framework */,
+ ECFEDF50F009974C064DFA75 /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "";
@@ -186,6 +215,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
+ 52B53316CDFDEB6B4041714D /* [CP] Check Pods Manifest.lock */,
331C80D1294CF70F00263BE5 /* Sources */,
331C80D2294CF70F00263BE5 /* Frameworks */,
331C80D3294CF70F00263BE5 /* Resources */,
@@ -204,11 +234,13 @@
isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
+ C0C8FBDF1207306A464888E9 /* [CP] Check Pods Manifest.lock */,
33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */,
+ B59A99DE8345B4DEFE849FE7 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -227,7 +259,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0920;
- LastUpgradeCheck = 1430;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C80D4294CF70F00263BE5 = {
@@ -328,6 +360,67 @@
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
+ 52B53316CDFDEB6B4041714D /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ B59A99DE8345B4DEFE849FE7 /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ C0C8FBDF1207306A464888E9 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -379,6 +472,7 @@
/* Begin XCBuildConfiguration section */
331C80DB294CF71000263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = EEFA829C491B67BB2695D9B1 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
@@ -393,6 +487,7 @@
};
331C80DC294CF71000263BE5 /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = D6246F994D1DCD4DC57DD5E5 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
@@ -407,6 +502,7 @@
};
331C80DD294CF71000263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 2300B308B78E43D2FDF50990 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 38981be..2635ffc 100644
--- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
+
+
diff --git a/pubspec.lock b/pubspec.lock
index 3e4245a..0303ce0 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -49,6 +49,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.18.0"
+ cross_file:
+ dependency: transitive
+ description:
+ name: cross_file
+ sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.3.4+1"
crypto:
dependency: transitive
description:
@@ -89,6 +97,38 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.0"
+ file_selector_linux:
+ dependency: transitive
+ description:
+ name: file_selector_linux
+ sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.9.2+1"
+ file_selector_macos:
+ dependency: transitive
+ description:
+ name: file_selector_macos
+ sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.9.4"
+ file_selector_platform_interface:
+ dependency: transitive
+ description:
+ name: file_selector_platform_interface
+ sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.6.2"
+ file_selector_windows:
+ dependency: transitive
+ description:
+ name: file_selector_windows
+ sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.9.3+1"
flutter:
dependency: "direct main"
description: flutter
@@ -102,6 +142,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.2"
+ flutter_plugin_android_lifecycle:
+ dependency: transitive
+ description:
+ name: flutter_plugin_android_lifecycle
+ sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.19"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -152,6 +200,70 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
+ image_picker:
+ dependency: "direct main"
+ description:
+ name: image_picker
+ sha256: "33974eca2e87e8b4e3727f1b94fa3abcb25afe80b6bc2c4d449a0e150aedf720"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ image_picker_android:
+ dependency: transitive
+ description:
+ name: image_picker_android
+ sha256: "0f57fee1e8bfadf8cc41818bbcd7f72e53bb768a54d9496355d5e8a5681a19f1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.8.12+1"
+ image_picker_for_web:
+ dependency: transitive
+ description:
+ name: image_picker_for_web
+ sha256: "5d6eb13048cd47b60dbf1a5495424dea226c5faf3950e20bf8120a58efb5b5f3"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.4"
+ image_picker_ios:
+ dependency: transitive
+ description:
+ name: image_picker_ios
+ sha256: "4824d8c7f6f89121ef0122ff79bb00b009607faecc8545b86bca9ab5ce1e95bf"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.8.11+2"
+ image_picker_linux:
+ dependency: transitive
+ description:
+ name: image_picker_linux
+ sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.2.1+1"
+ image_picker_macos:
+ dependency: transitive
+ description:
+ name: image_picker_macos
+ sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.2.1+1"
+ image_picker_platform_interface:
+ dependency: transitive
+ description:
+ name: image_picker_platform_interface
+ sha256: "9ec26d410ff46f483c5519c29c02ef0e02e13a543f882b152d4bfd2f06802f80"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.10.0"
+ image_picker_windows:
+ dependency: transitive
+ description:
+ name: image_picker_windows
+ sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.2.1+1"
intl:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 340f2a9..93fbc08 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -37,6 +37,7 @@ dependencies:
cupertino_icons: ^1.0.2
supabase_flutter: ^2.5.2
timeago: ^3.1.0
+ image_picker: ^1.0.5
dev_dependencies:
flutter_test:
diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc
index 785a046..5bbd4c3 100644
--- a/windows/flutter/generated_plugin_registrant.cc
+++ b/windows/flutter/generated_plugin_registrant.cc
@@ -7,11 +7,14 @@
#include "generated_plugin_registrant.h"
#include
+#include
#include
void RegisterPlugins(flutter::PluginRegistry* registry) {
AppLinksPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("AppLinksPluginCApi"));
+ FileSelectorWindowsRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("FileSelectorWindows"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
}
diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake
index 8f8ee4f..79001bc 100644
--- a/windows/flutter/generated_plugins.cmake
+++ b/windows/flutter/generated_plugins.cmake
@@ -4,6 +4,7 @@
list(APPEND FLUTTER_PLUGIN_LIST
app_links
+ file_selector_windows
url_launcher_windows
)