├── .gitignore
├── .metadata
├── README.md
├── analysis_options.yaml
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── io
│ │ │ │ └── supabase
│ │ │ │ └── supabase_demo
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable-v21
│ │ │ └── launch_background.xml
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── launcher_icon.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── launcher_icon.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── launcher_icon.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── launcher_icon.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── launcher_icon.png
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
└── images
│ ├── logo-dark.png
│ ├── logo.png
│ └── noavatar.jpeg
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ └── Icon-App-83.5x83.5@2x.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
├── lib
├── components
│ ├── auth_required_state.dart
│ └── auth_state.dart
├── configure_nonweb.dart
├── configure_web.dart
├── main.dart
├── screens
│ ├── change_password.dart
│ ├── forgot_password.dart
│ ├── profile_screen.dart
│ ├── signin_screen.dart
│ ├── signup_screen.dart
│ ├── splash_screen.dart
│ └── web_home_screen.dart
└── utils
│ ├── constants.dart
│ └── helpers.dart
├── pubspec.lock
├── pubspec.yaml
├── test
└── widget_test.dart
└── web
├── favicon.ico
├── icons
├── Icon-192.png
└── Icon-512.png
├── index.html
└── manifest.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | .vscode/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | /build/
34 |
35 | # Web related
36 | lib/generated_plugin_registrant.dart
37 |
38 | # Symbolication related
39 | app.*.symbols
40 |
41 | # Obfuscation related
42 | app.*.map.json
43 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Supabase Flutter User Management
2 |
3 | This example will set you up for a very common situation: users can sign up with a magic link and then update their account with public profile information, including a profile image.
4 |
5 | ## Technologies used
6 |
7 | - Frontend:
8 | - [Flutter SDK](https://flutter.dev/) - Google's UI toolkit for crafting beautiful, natively compiled applications for mobile, web, and desktop from a single codebase.
9 | - [supabase_flutter](https://pub.dev/packages/supabase_flutter) for user management and image storage uploading.
10 | - Backend:
11 | - [app.supabase.io](https://app.supabase.io/): hosted Postgres database with restful API for usage with supabase_flutter.
12 |
13 | ## Build from scratch
14 |
15 | ### 1. Create new project
16 |
17 | Sign up to Supabase - [https://app.supabase.io](https://app.supabase.io) and create a new project. Wait for your database to start.
18 |
19 | ### 2. Run "User Management" Quickstart
20 |
21 | Once your database has started, run the "User Management Starter" quickstart. Inside of your project, enter the `SQL editor` tab and scroll down until you see `User Management Starter: Set up a Public Profiles table which you can access with your API`.
22 |
23 | ### 3. Get the URL and Key
24 |
25 | Go to the Project Settings (the cog icon), open the API tab, and find your API URL and `anon` key, you'll need these in the next step.
26 |
27 | The `anon` key is your client-side API key. It allows "anonymous access" to your database, until the user has logged in. Once they have logged in, the keys will switch to the user's own login token. This enables row level security for your data. Read more about this [below](#postgres-row-level-security).
28 |
29 | 
30 |
31 | **_NOTE_**: The `service_role` key has full access to your data, bypassing any security policies. These keys have to be kept secret and are meant to be used in server environments and never on a client or browser.
32 |
33 | ### 4. Setup deeplink redirect urls
34 |
35 | Go to the Authentication Settings page (the user icon). Enter the flutter app redirect url below into `Additional Redirect URLs` field. Then click Save.
36 |
37 | > io.supabase.flutterdemo://login-callback
38 |
39 | 
40 |
41 | ### 5. Setup Github 3rd party logins
42 |
43 | Follow the guide https://supabase.io/docs/guides/auth#third-party-logins
44 |
45 | ### 6. Run the flutter application
46 |
47 | - Go to `lib/utils/constants.dart` file
48 | - Update `SUPABASE_URL` and `SUPABASE_ANNON_KEY` with your URL and Key
49 | - Run the application: `flutter run`
50 |
51 | ## Supabase details
52 |
53 | ### Postgres Row level security
54 |
55 | This project uses very high-level Authorization using Postgres' Role Level Security.
56 | When you start a Postgres database on Supabase, we populate it with an `auth` schema, and some helper functions.
57 | When a user logs in, they are issued a JWT with the role `authenticated` and thier UUID.
58 | We can use these details to provide fine-grained control over what each user can and cannot do.
59 |
60 | This is a trimmed-down schema, with the policies:
61 |
62 | ```sql
63 | -- Create a table for Public Profiles
64 | create table profiles (
65 | id uuid references auth.users not null,
66 | updated_at timestamp with time zone,
67 | username text unique,
68 | avatar_url text,
69 | website text,
70 |
71 | primary key (id),
72 | unique(username),
73 | constraint username_length check (char_length(username) >= 3)
74 | );
75 |
76 | alter table profiles enable row level security;
77 |
78 | create policy "Public profiles are viewable by everyone."
79 | on profiles for select
80 | using ( true );
81 |
82 | create policy "Users can insert their own profile."
83 | on profiles for insert
84 | with check ( auth.uid() = id );
85 |
86 | create policy "Users can update own profile."
87 | on profiles for update
88 | using ( auth.uid() = id );
89 |
90 | -- Set up Realtime!
91 | begin;
92 | drop publication if exists supabase_realtime;
93 | create publication supabase_realtime;
94 | commit;
95 | alter publication supabase_realtime add table profiles;
96 |
97 | -- Set up Storage!
98 | insert into storage.buckets (id, name)
99 | values ('avatars', 'avatars');
100 |
101 | create policy "Avatar images are publicly accessible."
102 | on storage.objects for select
103 | using ( bucket_id = 'avatars' );
104 |
105 | create policy "Anyone can upload an avatar."
106 | on storage.objects for insert
107 | with check ( bucket_id = 'avatars' );
108 |
109 | create policy "Anyone can update an avatar."
110 | on storage.objects for update
111 | with check ( bucket_id = 'avatars' );
112 | ```
113 |
114 | ## Authors
115 |
116 | - [Supabase](https://supabase.io)
117 |
118 | Supabase is open source. We'd love for you to follow along and get involved at https://github.com/supabase/supabase
119 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:lint/analysis_options.yaml
2 |
3 | linter:
4 | rules:
5 | avoid_print: false
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | compileSdkVersion 30
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | defaultConfig {
36 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
37 | applicationId "io.supabase.supabase_demo"
38 | minSdkVersion 18
39 | targetSdkVersion 30
40 | versionCode flutterVersionCode.toInteger()
41 | versionName flutterVersionName
42 | }
43 |
44 | buildTypes {
45 | release {
46 | // TODO: Add your own signing config for the release build.
47 | // Signing with the debug keys for now, so `flutter run --release` works.
48 | signingConfig signingConfigs.debug
49 | }
50 | }
51 | }
52 |
53 | flutter {
54 | source '../..'
55 | }
56 |
57 | dependencies {
58 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
59 | }
60 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
15 |
19 |
23 |
28 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
48 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/io/supabase/supabase_demo/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package io.supabase.supabase_demo
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/android/app/src/main/res/mipmap-hdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/android/app/src/main/res/mipmap-mdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:4.1.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | project.evaluationDependsOn(':app')
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
7 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/assets/images/logo-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/assets/images/logo-dark.png
--------------------------------------------------------------------------------
/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/assets/images/logo.png
--------------------------------------------------------------------------------
/assets/images/noavatar.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/assets/images/noavatar.jpeg
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/ephemeral/
22 | Flutter/app.flx
23 | Flutter/app.zip
24 | Flutter/flutter_assets/
25 | Flutter/flutter_export_environment.sh
26 | ServiceDefinitions.json
27 | Runner/GeneratedPluginRegistrant.*
28 |
29 | # Exceptions to above rules.
30 | !default.mode1v3
31 | !default.mode2v3
32 | !default.pbxuser
33 | !default.perspectivev3
34 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
16 | /* End PBXBuildFile section */
17 |
18 | /* Begin PBXCopyFilesBuildPhase section */
19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
20 | isa = PBXCopyFilesBuildPhase;
21 | buildActionMask = 2147483647;
22 | dstPath = "";
23 | dstSubfolderSpec = 10;
24 | files = (
25 | );
26 | name = "Embed Frameworks";
27 | runOnlyForDeploymentPostprocessing = 0;
28 | };
29 | /* End PBXCopyFilesBuildPhase section */
30 |
31 | /* Begin PBXFileReference section */
32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
45 | /* End PBXFileReference section */
46 |
47 | /* Begin PBXFrameworksBuildPhase section */
48 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
49 | isa = PBXFrameworksBuildPhase;
50 | buildActionMask = 2147483647;
51 | files = (
52 | );
53 | runOnlyForDeploymentPostprocessing = 0;
54 | };
55 | /* End PBXFrameworksBuildPhase section */
56 |
57 | /* Begin PBXGroup section */
58 | 9740EEB11CF90186004384FC /* Flutter */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
65 | );
66 | name = Flutter;
67 | sourceTree = "";
68 | };
69 | 97C146E51CF9000F007C117D = {
70 | isa = PBXGroup;
71 | children = (
72 | 9740EEB11CF90186004384FC /* Flutter */,
73 | 97C146F01CF9000F007C117D /* Runner */,
74 | 97C146EF1CF9000F007C117D /* Products */,
75 | );
76 | sourceTree = "";
77 | };
78 | 97C146EF1CF9000F007C117D /* Products */ = {
79 | isa = PBXGroup;
80 | children = (
81 | 97C146EE1CF9000F007C117D /* Runner.app */,
82 | );
83 | name = Products;
84 | sourceTree = "";
85 | };
86 | 97C146F01CF9000F007C117D /* Runner */ = {
87 | isa = PBXGroup;
88 | children = (
89 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
92 | 97C147021CF9000F007C117D /* Info.plist */,
93 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
94 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
95 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
96 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
97 | );
98 | path = Runner;
99 | sourceTree = "";
100 | };
101 | /* End PBXGroup section */
102 |
103 | /* Begin PBXNativeTarget section */
104 | 97C146ED1CF9000F007C117D /* Runner */ = {
105 | isa = PBXNativeTarget;
106 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
107 | buildPhases = (
108 | 9740EEB61CF901F6004384FC /* Run Script */,
109 | 97C146EA1CF9000F007C117D /* Sources */,
110 | 97C146EB1CF9000F007C117D /* Frameworks */,
111 | 97C146EC1CF9000F007C117D /* Resources */,
112 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
113 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
114 | );
115 | buildRules = (
116 | );
117 | dependencies = (
118 | );
119 | name = Runner;
120 | productName = Runner;
121 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
122 | productType = "com.apple.product-type.application";
123 | };
124 | /* End PBXNativeTarget section */
125 |
126 | /* Begin PBXProject section */
127 | 97C146E61CF9000F007C117D /* Project object */ = {
128 | isa = PBXProject;
129 | attributes = {
130 | LastUpgradeCheck = 1020;
131 | ORGANIZATIONNAME = "";
132 | TargetAttributes = {
133 | 97C146ED1CF9000F007C117D = {
134 | CreatedOnToolsVersion = 7.3.1;
135 | LastSwiftMigration = 1100;
136 | };
137 | };
138 | };
139 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
140 | compatibilityVersion = "Xcode 9.3";
141 | developmentRegion = en;
142 | hasScannedForEncodings = 0;
143 | knownRegions = (
144 | en,
145 | Base,
146 | );
147 | mainGroup = 97C146E51CF9000F007C117D;
148 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
149 | projectDirPath = "";
150 | projectRoot = "";
151 | targets = (
152 | 97C146ED1CF9000F007C117D /* Runner */,
153 | );
154 | };
155 | /* End PBXProject section */
156 |
157 | /* Begin PBXResourcesBuildPhase section */
158 | 97C146EC1CF9000F007C117D /* Resources */ = {
159 | isa = PBXResourcesBuildPhase;
160 | buildActionMask = 2147483647;
161 | files = (
162 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
163 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
164 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
165 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
166 | );
167 | runOnlyForDeploymentPostprocessing = 0;
168 | };
169 | /* End PBXResourcesBuildPhase section */
170 |
171 | /* Begin PBXShellScriptBuildPhase section */
172 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
173 | isa = PBXShellScriptBuildPhase;
174 | buildActionMask = 2147483647;
175 | files = (
176 | );
177 | inputPaths = (
178 | );
179 | name = "Thin Binary";
180 | outputPaths = (
181 | );
182 | runOnlyForDeploymentPostprocessing = 0;
183 | shellPath = /bin/sh;
184 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
185 | };
186 | 9740EEB61CF901F6004384FC /* Run Script */ = {
187 | isa = PBXShellScriptBuildPhase;
188 | buildActionMask = 2147483647;
189 | files = (
190 | );
191 | inputPaths = (
192 | );
193 | name = "Run Script";
194 | outputPaths = (
195 | );
196 | runOnlyForDeploymentPostprocessing = 0;
197 | shellPath = /bin/sh;
198 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
199 | };
200 | /* End PBXShellScriptBuildPhase section */
201 |
202 | /* Begin PBXSourcesBuildPhase section */
203 | 97C146EA1CF9000F007C117D /* Sources */ = {
204 | isa = PBXSourcesBuildPhase;
205 | buildActionMask = 2147483647;
206 | files = (
207 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
208 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
209 | );
210 | runOnlyForDeploymentPostprocessing = 0;
211 | };
212 | /* End PBXSourcesBuildPhase section */
213 |
214 | /* Begin PBXVariantGroup section */
215 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
216 | isa = PBXVariantGroup;
217 | children = (
218 | 97C146FB1CF9000F007C117D /* Base */,
219 | );
220 | name = Main.storyboard;
221 | sourceTree = "";
222 | };
223 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
224 | isa = PBXVariantGroup;
225 | children = (
226 | 97C147001CF9000F007C117D /* Base */,
227 | );
228 | name = LaunchScreen.storyboard;
229 | sourceTree = "";
230 | };
231 | /* End PBXVariantGroup section */
232 |
233 | /* Begin XCBuildConfiguration section */
234 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
235 | isa = XCBuildConfiguration;
236 | buildSettings = {
237 | ALWAYS_SEARCH_USER_PATHS = NO;
238 | CLANG_ANALYZER_NONNULL = YES;
239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
240 | CLANG_CXX_LIBRARY = "libc++";
241 | CLANG_ENABLE_MODULES = YES;
242 | CLANG_ENABLE_OBJC_ARC = YES;
243 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
244 | CLANG_WARN_BOOL_CONVERSION = YES;
245 | CLANG_WARN_COMMA = YES;
246 | CLANG_WARN_CONSTANT_CONVERSION = YES;
247 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
249 | CLANG_WARN_EMPTY_BODY = YES;
250 | CLANG_WARN_ENUM_CONVERSION = YES;
251 | CLANG_WARN_INFINITE_RECURSION = YES;
252 | CLANG_WARN_INT_CONVERSION = YES;
253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
254 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
258 | CLANG_WARN_STRICT_PROTOTYPES = YES;
259 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
260 | CLANG_WARN_UNREACHABLE_CODE = YES;
261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
263 | COPY_PHASE_STRIP = NO;
264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
265 | ENABLE_NS_ASSERTIONS = NO;
266 | ENABLE_STRICT_OBJC_MSGSEND = YES;
267 | GCC_C_LANGUAGE_STANDARD = gnu99;
268 | GCC_NO_COMMON_BLOCKS = YES;
269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
271 | GCC_WARN_UNDECLARED_SELECTOR = YES;
272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
273 | GCC_WARN_UNUSED_FUNCTION = YES;
274 | GCC_WARN_UNUSED_VARIABLE = YES;
275 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
276 | MTL_ENABLE_DEBUG_INFO = NO;
277 | SDKROOT = iphoneos;
278 | SUPPORTED_PLATFORMS = iphoneos;
279 | TARGETED_DEVICE_FAMILY = "1,2";
280 | VALIDATE_PRODUCT = YES;
281 | };
282 | name = Profile;
283 | };
284 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
285 | isa = XCBuildConfiguration;
286 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
287 | buildSettings = {
288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
289 | CLANG_ENABLE_MODULES = YES;
290 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
291 | ENABLE_BITCODE = NO;
292 | INFOPLIST_FILE = Runner/Info.plist;
293 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
294 | PRODUCT_BUNDLE_IDENTIFIER = io.supabase.supabaseDemo;
295 | PRODUCT_NAME = "$(TARGET_NAME)";
296 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
297 | SWIFT_VERSION = 5.0;
298 | VERSIONING_SYSTEM = "apple-generic";
299 | };
300 | name = Profile;
301 | };
302 | 97C147031CF9000F007C117D /* Debug */ = {
303 | isa = XCBuildConfiguration;
304 | buildSettings = {
305 | ALWAYS_SEARCH_USER_PATHS = NO;
306 | CLANG_ANALYZER_NONNULL = YES;
307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
308 | CLANG_CXX_LIBRARY = "libc++";
309 | CLANG_ENABLE_MODULES = YES;
310 | CLANG_ENABLE_OBJC_ARC = YES;
311 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
312 | CLANG_WARN_BOOL_CONVERSION = YES;
313 | CLANG_WARN_COMMA = YES;
314 | CLANG_WARN_CONSTANT_CONVERSION = YES;
315 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
316 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
317 | CLANG_WARN_EMPTY_BODY = YES;
318 | CLANG_WARN_ENUM_CONVERSION = YES;
319 | CLANG_WARN_INFINITE_RECURSION = YES;
320 | CLANG_WARN_INT_CONVERSION = YES;
321 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
322 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
323 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
324 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
325 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
326 | CLANG_WARN_STRICT_PROTOTYPES = YES;
327 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
328 | CLANG_WARN_UNREACHABLE_CODE = YES;
329 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
330 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
331 | COPY_PHASE_STRIP = NO;
332 | DEBUG_INFORMATION_FORMAT = dwarf;
333 | ENABLE_STRICT_OBJC_MSGSEND = YES;
334 | ENABLE_TESTABILITY = YES;
335 | GCC_C_LANGUAGE_STANDARD = gnu99;
336 | GCC_DYNAMIC_NO_PIC = NO;
337 | GCC_NO_COMMON_BLOCKS = YES;
338 | GCC_OPTIMIZATION_LEVEL = 0;
339 | GCC_PREPROCESSOR_DEFINITIONS = (
340 | "DEBUG=1",
341 | "$(inherited)",
342 | );
343 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
344 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
345 | GCC_WARN_UNDECLARED_SELECTOR = YES;
346 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
347 | GCC_WARN_UNUSED_FUNCTION = YES;
348 | GCC_WARN_UNUSED_VARIABLE = YES;
349 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
350 | MTL_ENABLE_DEBUG_INFO = YES;
351 | ONLY_ACTIVE_ARCH = YES;
352 | SDKROOT = iphoneos;
353 | TARGETED_DEVICE_FAMILY = "1,2";
354 | };
355 | name = Debug;
356 | };
357 | 97C147041CF9000F007C117D /* Release */ = {
358 | isa = XCBuildConfiguration;
359 | buildSettings = {
360 | ALWAYS_SEARCH_USER_PATHS = NO;
361 | CLANG_ANALYZER_NONNULL = YES;
362 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
363 | CLANG_CXX_LIBRARY = "libc++";
364 | CLANG_ENABLE_MODULES = YES;
365 | CLANG_ENABLE_OBJC_ARC = YES;
366 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
367 | CLANG_WARN_BOOL_CONVERSION = YES;
368 | CLANG_WARN_COMMA = YES;
369 | CLANG_WARN_CONSTANT_CONVERSION = YES;
370 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
371 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
372 | CLANG_WARN_EMPTY_BODY = YES;
373 | CLANG_WARN_ENUM_CONVERSION = YES;
374 | CLANG_WARN_INFINITE_RECURSION = YES;
375 | CLANG_WARN_INT_CONVERSION = YES;
376 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
377 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
378 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
379 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
380 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
381 | CLANG_WARN_STRICT_PROTOTYPES = YES;
382 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
383 | CLANG_WARN_UNREACHABLE_CODE = YES;
384 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
385 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
386 | COPY_PHASE_STRIP = NO;
387 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
388 | ENABLE_NS_ASSERTIONS = NO;
389 | ENABLE_STRICT_OBJC_MSGSEND = YES;
390 | GCC_C_LANGUAGE_STANDARD = gnu99;
391 | GCC_NO_COMMON_BLOCKS = YES;
392 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
393 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
394 | GCC_WARN_UNDECLARED_SELECTOR = YES;
395 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
396 | GCC_WARN_UNUSED_FUNCTION = YES;
397 | GCC_WARN_UNUSED_VARIABLE = YES;
398 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
399 | MTL_ENABLE_DEBUG_INFO = NO;
400 | SDKROOT = iphoneos;
401 | SUPPORTED_PLATFORMS = iphoneos;
402 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
403 | TARGETED_DEVICE_FAMILY = "1,2";
404 | VALIDATE_PRODUCT = YES;
405 | };
406 | name = Release;
407 | };
408 | 97C147061CF9000F007C117D /* Debug */ = {
409 | isa = XCBuildConfiguration;
410 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
411 | buildSettings = {
412 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
413 | CLANG_ENABLE_MODULES = YES;
414 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
415 | ENABLE_BITCODE = NO;
416 | INFOPLIST_FILE = Runner/Info.plist;
417 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
418 | PRODUCT_BUNDLE_IDENTIFIER = io.supabase.supabaseDemo;
419 | PRODUCT_NAME = "$(TARGET_NAME)";
420 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
421 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
422 | SWIFT_VERSION = 5.0;
423 | VERSIONING_SYSTEM = "apple-generic";
424 | };
425 | name = Debug;
426 | };
427 | 97C147071CF9000F007C117D /* Release */ = {
428 | isa = XCBuildConfiguration;
429 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
430 | buildSettings = {
431 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
432 | CLANG_ENABLE_MODULES = YES;
433 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
434 | ENABLE_BITCODE = NO;
435 | INFOPLIST_FILE = Runner/Info.plist;
436 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
437 | PRODUCT_BUNDLE_IDENTIFIER = io.supabase.supabaseDemo;
438 | PRODUCT_NAME = "$(TARGET_NAME)";
439 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
440 | SWIFT_VERSION = 5.0;
441 | VERSIONING_SYSTEM = "apple-generic";
442 | };
443 | name = Release;
444 | };
445 | /* End XCBuildConfiguration section */
446 |
447 | /* Begin XCConfigurationList section */
448 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
449 | isa = XCConfigurationList;
450 | buildConfigurations = (
451 | 97C147031CF9000F007C117D /* Debug */,
452 | 97C147041CF9000F007C117D /* Release */,
453 | 249021D3217E4FDB00AE95B9 /* Profile */,
454 | );
455 | defaultConfigurationIsVisible = 0;
456 | defaultConfigurationName = Release;
457 | };
458 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
459 | isa = XCConfigurationList;
460 | buildConfigurations = (
461 | 97C147061CF9000F007C117D /* Debug */,
462 | 97C147071CF9000F007C117D /* Release */,
463 | 249021D4217E4FDB00AE95B9 /* Profile */,
464 | );
465 | defaultConfigurationIsVisible = 0;
466 | defaultConfigurationName = Release;
467 | };
468 | /* End XCConfigurationList section */
469 | };
470 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
471 | }
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phamhieu/supabase-flutter-demo/a4a57ce2bd688806e5b0492fd73ec6f3bae6f3be/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | Supabase Demo
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 | CFBundleURLTypes
45 |
46 |
47 | CFBundleTypeRole
48 | Editor
49 | CFBundleURLSchemes
50 |
51 |
52 | io.supabase.flutterdemo
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/lib/components/auth_required_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:supabase_flutter/supabase_flutter.dart';
3 |
4 | class AuthRequiredState
5 | extends SupabaseAuthRequiredState {
6 | @override
7 | void onUnauthenticated() {
8 | Navigator.pushNamedAndRemoveUntil(context, '/signIn', (route) => false);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/lib/components/auth_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:supabase/supabase.dart' as supabase;
3 | import 'package:supabase_flutter/supabase_flutter.dart';
4 |
5 | class AuthState extends SupabaseAuthState {
6 | @override
7 | void onUnauthenticated() {
8 | Navigator.pushNamedAndRemoveUntil(context, '/signIn', (route) => false);
9 | }
10 |
11 | @override
12 | void onAuthenticated(supabase.Session session) {
13 | Navigator.pushNamedAndRemoveUntil(context, '/profile', (route) => false);
14 | }
15 |
16 | @override
17 | void onPasswordRecovery(supabase.Session session) {
18 | Navigator.pushNamedAndRemoveUntil(
19 | context, '/profile/changePassword', (route) => false);
20 | }
21 |
22 | @override
23 | void onErrorAuthenticating(String message) {
24 | print('***** onErrorAuthenticating: $message');
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/configure_nonweb.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_secure_storage/flutter_secure_storage.dart';
2 | import 'package:supabase_flutter/supabase_flutter.dart';
3 |
4 | import 'utils/constants.dart';
5 |
6 | Future configureApp() async {
7 | // init Supabase singleton
8 | await Supabase.initialize(
9 | url: supabaseUrl,
10 | anonKey: supabaseAnnonKey,
11 | authCallbackUrlHostname: 'login-callback',
12 | debug: true,
13 | localStorage: SecureLocalStorage(),
14 | );
15 | }
16 |
17 | // user flutter_secure_storage to persist user session
18 | class SecureLocalStorage extends LocalStorage {
19 | SecureLocalStorage()
20 | : super(
21 | initialize: () async {},
22 | hasAccessToken: () {
23 | const storage = FlutterSecureStorage();
24 | return storage.containsKey(key: supabasePersistSessionKey);
25 | },
26 | accessToken: () {
27 | const storage = FlutterSecureStorage();
28 | return storage.read(key: supabasePersistSessionKey);
29 | },
30 | removePersistedSession: () {
31 | const storage = FlutterSecureStorage();
32 | return storage.delete(key: supabasePersistSessionKey);
33 | },
34 | persistSession: (String value) {
35 | const storage = FlutterSecureStorage();
36 | return storage.write(key: supabasePersistSessionKey, value: value);
37 | },
38 | );
39 | }
40 |
--------------------------------------------------------------------------------
/lib/configure_web.dart:
--------------------------------------------------------------------------------
1 | import 'package:supabase_flutter/supabase_flutter.dart';
2 |
3 | import 'utils/constants.dart';
4 |
5 | Future configureApp() async {
6 | // init Supabase singleton
7 | // no localStorage provided, fallback to use hive as default
8 | await Supabase.initialize(
9 | url: supabaseUrl,
10 | anonKey: supabaseAnnonKey,
11 | authCallbackUrlHostname: 'login-callback',
12 | debug: true,
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | import 'configure_nonweb.dart' if (dart.library.html) 'configure_web.dart';
5 | import 'screens/change_password.dart';
6 | import 'screens/forgot_password.dart';
7 | import 'screens/profile_screen.dart';
8 | import 'screens/signin_screen.dart';
9 | import 'screens/signup_screen.dart';
10 | import 'screens/splash_screen.dart';
11 | import 'screens/web_home_screen.dart';
12 |
13 | Future main() async {
14 | WidgetsFlutterBinding.ensureInitialized();
15 | await configureApp();
16 | runApp(MyApp());
17 | }
18 |
19 | class MyApp extends StatelessWidget {
20 | // This widget is the root of your application.
21 | @override
22 | Widget build(BuildContext context) {
23 | return MaterialApp(
24 | title: 'Supabase Demo',
25 | theme: ThemeData.dark(),
26 | initialRoute: '/',
27 | routes: {
28 | '/signIn': (_) => SignInScreen(),
29 | '/signUp': (_) => SignUpScreen(),
30 | '/forgotPassword': (_) => ForgotPasswordScreen(),
31 | '/profile': (_) => ProfileScreen(),
32 | '/profile/changePassword': (_) => ChangePasswordScreen(),
33 | },
34 | onGenerateRoute: generateRoute,
35 | );
36 | }
37 | }
38 |
39 | Route generateRoute(RouteSettings settings) {
40 | switch (settings.name) {
41 | default:
42 | return MaterialPageRoute(
43 | builder: (_) => kIsWeb ? WebHomeScreen() : SplashScreen());
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/lib/screens/change_password.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:rounded_loading_button/rounded_loading_button.dart';
3 | import 'package:supabase/supabase.dart';
4 | import 'package:supabase_flutter/supabase_flutter.dart';
5 |
6 | import '/components/auth_required_state.dart';
7 | import '/utils/helpers.dart';
8 |
9 | class ChangePasswordScreen extends StatefulWidget {
10 | @override
11 | _ChangePasswordState createState() => _ChangePasswordState();
12 | }
13 |
14 | class _ChangePasswordState extends AuthRequiredState {
15 | final formKey = GlobalKey();
16 | final scaffoldKey = GlobalKey();
17 |
18 | final TextEditingController _passwordField = TextEditingController();
19 |
20 | final RoundedLoadingButtonController _btnController =
21 | RoundedLoadingButtonController();
22 |
23 | String _password = '';
24 |
25 | Future _onPasswordChangePress(BuildContext context) async {
26 | try {
27 | final form = formKey.currentState;
28 |
29 | if (form != null && form.validate()) {
30 | form.save();
31 | FocusScope.of(context).unfocus();
32 |
33 | final userAttributes = UserAttributes(password: _password);
34 | final response =
35 | await Supabase.instance.client.auth.update(userAttributes);
36 | if (response.error != null) {
37 | throw 'Password change failed: ${response.error!.message}';
38 | }
39 |
40 | showMessage('Password updated');
41 | if (Navigator.canPop(context)) {
42 | _btnController.success();
43 | } else {
44 | Navigator.pushNamedAndRemoveUntil(
45 | context,
46 | '/profile',
47 | (route) => false,
48 | );
49 | }
50 | }
51 | } catch (e) {
52 | showMessage(e.toString());
53 | } finally {
54 | _btnController.reset();
55 | }
56 | }
57 |
58 | void showMessage(String message) {
59 | final snackbar = SnackBar(content: Text(message));
60 | ScaffoldMessenger.of(scaffoldKey.currentContext!).showSnackBar(snackbar);
61 | }
62 |
63 | @override
64 | Widget build(BuildContext context) {
65 | return Scaffold(
66 | key: scaffoldKey,
67 | appBar: AppBar(
68 | title: const Text('Change password'),
69 | ),
70 | body: Padding(
71 | padding: const EdgeInsets.all(15.0),
72 | child: Form(
73 | key: formKey,
74 | child: Column(
75 | children: [
76 | const SizedBox(height: 25.0),
77 | TextFormField(
78 | onSaved: (value) => _password = value ?? '',
79 | validator: (val) => validatePassword(val),
80 | controller: _passwordField,
81 | obscureText: true,
82 | decoration: const InputDecoration(
83 | hintText: 'Password',
84 | ),
85 | ),
86 | const SizedBox(height: 15.0),
87 | TextFormField(
88 | validator: (val) =>
89 | val != _passwordField.text ? 'Not Match' : null,
90 | obscureText: true,
91 | decoration: const InputDecoration(
92 | hintText: 'Confirm password',
93 | ),
94 | ),
95 | const SizedBox(height: 15.0),
96 | RoundedLoadingButton(
97 | color: Colors.green,
98 | controller: _btnController,
99 | onPressed: () {
100 | _onPasswordChangePress(context);
101 | },
102 | child: const Text(
103 | 'Save',
104 | style: TextStyle(fontSize: 16, color: Colors.white),
105 | ),
106 | ),
107 | ],
108 | ),
109 | ),
110 | ),
111 | );
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/lib/screens/forgot_password.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:rounded_loading_button/rounded_loading_button.dart';
3 | import 'package:supabase/supabase.dart' as supabase;
4 | import 'package:supabase_flutter/supabase_flutter.dart';
5 |
6 | import '/components/auth_state.dart';
7 | import '/utils/helpers.dart';
8 |
9 | class ForgotPasswordScreen extends StatefulWidget {
10 | @override
11 | _ForgotPasswordState createState() => _ForgotPasswordState();
12 | }
13 |
14 | class _ForgotPasswordState extends AuthState {
15 | final formKey = GlobalKey();
16 | final scaffoldKey = GlobalKey();
17 |
18 | final RoundedLoadingButtonController _btnController =
19 | RoundedLoadingButtonController();
20 |
21 | String _email = '';
22 |
23 | Future _onPasswordRecoverPress(BuildContext context) async {
24 | final form = formKey.currentState;
25 |
26 | if (form != null && form.validate()) {
27 | form.save();
28 | FocusScope.of(context).unfocus();
29 |
30 | final response = await Supabase.instance.client.auth.api
31 | .resetPasswordForEmail(_email,
32 | options: supabase.AuthOptions(redirectTo: authRedirectUri));
33 | if (response.error != null) {
34 | showMessage('Password recovery failed: ${response.error!.message}');
35 | _btnController.reset();
36 | } else {
37 | showMessage('Please check your email for further instructions.');
38 | _btnController.success();
39 | }
40 | }
41 | }
42 |
43 | void showMessage(String message) {
44 | final snackbar = SnackBar(content: Text(message));
45 | ScaffoldMessenger.of(scaffoldKey.currentContext!).showSnackBar(snackbar);
46 | }
47 |
48 | @override
49 | Widget build(BuildContext context) {
50 | return Scaffold(
51 | key: scaffoldKey,
52 | appBar: AppBar(
53 | title: const Text('Forgot password'),
54 | ),
55 | body: Padding(
56 | padding: const EdgeInsets.all(15.0),
57 | child: Form(
58 | key: formKey,
59 | child: Column(
60 | children: [
61 | const SizedBox(height: 25.0),
62 | TextFormField(
63 | onSaved: (value) => _email = value ?? '',
64 | validator: (val) => validateEmail(val),
65 | keyboardType: TextInputType.emailAddress,
66 | decoration: const InputDecoration(
67 | hintText: 'Enter your email address',
68 | ),
69 | ),
70 | const SizedBox(height: 35.0),
71 | RoundedLoadingButton(
72 | color: Colors.green,
73 | controller: _btnController,
74 | onPressed: () {
75 | _onPasswordRecoverPress(context);
76 | },
77 | child: const Text(
78 | 'Send reset password instructions',
79 | style: TextStyle(fontSize: 16, color: Colors.white),
80 | ),
81 | )
82 | ],
83 | ),
84 | ),
85 | ),
86 | );
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/lib/screens/profile_screen.dart:
--------------------------------------------------------------------------------
1 | import 'dart:typed_data';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/foundation.dart';
5 | import 'package:supabase/supabase.dart';
6 | import 'package:flutter/material.dart';
7 | import 'package:rounded_loading_button/rounded_loading_button.dart';
8 | import 'package:image_picker/image_picker.dart';
9 | import 'package:supabase_flutter/supabase_flutter.dart';
10 |
11 | import '/components/auth_required_state.dart';
12 | import '/utils/helpers.dart';
13 |
14 | class ProfileScreen extends StatefulWidget {
15 | @override
16 | _ProfileScreenState createState() => _ProfileScreenState();
17 | }
18 |
19 | class _ProfileScreenState extends AuthRequiredState {
20 | _ProfileScreenState();
21 |
22 | final scaffoldKey = GlobalKey();
23 |
24 | final RoundedLoadingButtonController _signOutBtnController =
25 | RoundedLoadingButtonController();
26 | final RoundedLoadingButtonController _updateProfileBtnController =
27 | RoundedLoadingButtonController();
28 |
29 | final _picker = ImagePicker();
30 |
31 | User? user;
32 | bool loadingProfile = true;
33 | String _appBarTitle = '';
34 | String username = '';
35 | String website = '';
36 | String avatarUrl = '';
37 | String avatarKey = '';
38 |
39 | @override
40 | void onAuthenticated(Session session) {
41 | final _user = session.user;
42 | if (_user != null) {
43 | setState(() {
44 | _appBarTitle = 'Welcome ${_user.email}';
45 | user = _user;
46 | });
47 | _loadProfile(_user.id);
48 | }
49 | }
50 |
51 | Future _loadProfile(String userId) async {
52 | try {
53 | final response = await Supabase.instance.client
54 | .from('profiles')
55 | .select('username, website, avatar_url, updated_at')
56 | .eq('id', userId)
57 | .maybeSingle()
58 | .execute();
59 | if (response.error != null) {
60 | throw "Load profile failed: ${response.error!.message}";
61 | }
62 |
63 | setState(() {
64 | print(response.data);
65 | username = response.data?['username'] as String? ?? '';
66 | website = response.data?['website'] as String? ?? '';
67 | avatarUrl = response.data?['avatar_url'] as String? ?? '';
68 | final updatedAt = response.data?['updated_at'] as String? ?? '';
69 | avatarKey = '$avatarUrl-$updatedAt';
70 | });
71 | } catch (e) {
72 | showMessage(e.toString());
73 | } finally {
74 | setState(() {
75 | loadingProfile = false;
76 | });
77 | }
78 | }
79 |
80 | Future _onSignOutPress(BuildContext context) async {
81 | await Supabase.instance.client.auth.signOut();
82 | Navigator.pushNamedAndRemoveUntil(context, '/signIn', (route) => false);
83 | }
84 |
85 | Future _updateAvatar(BuildContext context) async {
86 | try {
87 | final pickedFile = await _picker.pickImage(
88 | source: ImageSource.gallery,
89 | maxHeight: 600,
90 | maxWidth: 600,
91 | );
92 | if (pickedFile == null) {
93 | return;
94 | }
95 |
96 | final size = await pickedFile.length();
97 | if (size > 1000000) {
98 | throw "The file is too large. Allowed maximum size is 1 MB.";
99 | }
100 |
101 | final bytes = await pickedFile.readAsBytes();
102 | final fileName = avatarUrl == '' ? '${randomString(15)}.jpg' : avatarUrl;
103 | const fileOptions = FileOptions(upsert: true);
104 | final uploadRes = await Supabase.instance.client.storage
105 | .from('avatars')
106 | .uploadBinary(fileName, bytes, fileOptions: fileOptions);
107 |
108 | if (uploadRes.error != null) {
109 | throw uploadRes.error!.message;
110 | }
111 |
112 | final updatedAt = DateTime.now().toString();
113 | final res = await Supabase.instance.client.from('profiles').upsert({
114 | 'id': user!.id,
115 | 'avatar_url': fileName,
116 | 'updated_at': updatedAt,
117 | }).execute();
118 | if (res.error != null) {
119 | throw res.error!.message;
120 | }
121 |
122 | setState(() {
123 | avatarUrl = fileName;
124 | avatarKey = '$fileName-$updatedAt';
125 | });
126 | showMessage("Avatar updated!");
127 | } catch (e) {
128 | showMessage(e.toString());
129 | }
130 | }
131 |
132 | Future _onUpdateProfilePress(BuildContext context) async {
133 | try {
134 | FocusScope.of(context).unfocus();
135 |
136 | final updates = {
137 | 'id': user?.id,
138 | 'username': username,
139 | 'website': website,
140 | 'updated_at': DateTime.now().toString(),
141 | };
142 |
143 | final response = await Supabase.instance.client
144 | .from('profiles')
145 | .upsert(updates)
146 | .execute();
147 | if (response.error != null) {
148 | throw "Update profile failed: ${response.error!.message}";
149 | }
150 |
151 | showMessage("Profile updated!");
152 | } catch (e) {
153 | showMessage(e.toString());
154 | } finally {
155 | _updateProfileBtnController.reset();
156 | }
157 | }
158 |
159 | void showMessage(String message) {
160 | final snackbar = SnackBar(content: Text(message));
161 | ScaffoldMessenger.of(scaffoldKey.currentContext!).showSnackBar(snackbar);
162 | }
163 |
164 | @override
165 | Widget build(BuildContext context) {
166 | if (loadingProfile) {
167 | return Scaffold(
168 | appBar: AppBar(
169 | title: Text(_appBarTitle),
170 | ),
171 | body: SizedBox(
172 | height: MediaQuery.of(context).size.height / 1.3,
173 | child: const Center(
174 | child: CircularProgressIndicator(),
175 | ),
176 | ),
177 | );
178 | } else {
179 | return Scaffold(
180 | key: scaffoldKey,
181 | resizeToAvoidBottomInset: false,
182 | appBar: AppBar(
183 | title: Text(_appBarTitle),
184 | ),
185 | body: Padding(
186 | padding: const EdgeInsets.all(15.0),
187 | child: Column(
188 | children: [
189 | AvatarContainer(
190 | url: avatarUrl,
191 | onUpdatePressed: () => _updateAvatar(context),
192 | key: Key(avatarKey),
193 | ),
194 | TextFormField(
195 | onChanged: (value) => setState(() {
196 | username = value;
197 | }),
198 | initialValue: username,
199 | keyboardType: TextInputType.emailAddress,
200 | decoration: const InputDecoration(
201 | labelText: 'Username',
202 | hintText: '',
203 | ),
204 | ),
205 | TextFormField(
206 | onChanged: (value) => setState(() {
207 | website = value;
208 | }),
209 | initialValue: website,
210 | keyboardType: TextInputType.emailAddress,
211 | decoration: const InputDecoration(
212 | labelText: 'Website',
213 | hintText: '',
214 | ),
215 | ),
216 | const SizedBox(
217 | height: 35.0,
218 | ),
219 | RoundedLoadingButton(
220 | color: Colors.green,
221 | controller: _updateProfileBtnController,
222 | onPressed: () {
223 | _onUpdateProfilePress(context);
224 | },
225 | child: const Text('Update profile',
226 | style: TextStyle(fontSize: 20, color: Colors.white)),
227 | ),
228 | const SizedBox(height: 15.0),
229 | TextButton(
230 | onPressed: () {
231 | stopAuthObserver();
232 | Navigator.pushNamed(context, '/profile/changePassword')
233 | .then((_) => startAuthObserver());
234 | },
235 | child: const Text("Change password"),
236 | ),
237 | const Expanded(child: SizedBox()),
238 | RoundedLoadingButton(
239 | color: Colors.red,
240 | controller: _signOutBtnController,
241 | onPressed: () {
242 | _onSignOutPress(context);
243 | },
244 | child: const Text('Sign out',
245 | style: TextStyle(fontSize: 20, color: Colors.white)),
246 | ),
247 | ],
248 | ),
249 | ),
250 | );
251 | }
252 | }
253 | }
254 |
255 | class AvatarContainer extends StatefulWidget {
256 | final String url;
257 | final void Function() onUpdatePressed;
258 | const AvatarContainer(
259 | {required this.url, required this.onUpdatePressed, Key? key})
260 | : super(key: key);
261 |
262 | @override
263 | _AvatarContainerState createState() => _AvatarContainerState();
264 | }
265 |
266 | class _AvatarContainerState extends State {
267 | _AvatarContainerState();
268 |
269 | bool loadingImage = false;
270 | Uint8List? image;
271 |
272 | @override
273 | void initState() {
274 | super.initState();
275 |
276 | if (widget.url != '') {
277 | downloadImage(widget.url);
278 | }
279 | }
280 |
281 | Future downloadImage(String path) async {
282 | setState(() {
283 | loadingImage = true;
284 | });
285 |
286 | final response =
287 | await Supabase.instance.client.storage.from('avatars').download(path);
288 | if (response.error == null) {
289 | setState(() {
290 | image = response.data;
291 | loadingImage = false;
292 | });
293 | } else {
294 | print(response.error!.message);
295 | setState(() {
296 | loadingImage = false;
297 | });
298 | }
299 | return true;
300 | }
301 |
302 | ImageProvider