mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
blog: update past Flutter blog content to use supabase_flutter v2 (#19634)
* update flutter quick start and example app to use flutter v2 * update examples and blog articles to use Flutter SDK v2 * fix versions used in examples * update image picker to 1.0.5 * minor code refactor for sample code
This commit is contained in:
1 parent
6ac489018e
commit
eae972b55a
19 files changed
+169
-344
No files matched your search
@@ -68,7 +68,7 @@ export const meta = {
|
||||
<StepHikeCompact.Code>
|
||||
|
||||
```yaml pubspec.yaml
|
||||
supabase_flutter: ^1.6.2
|
||||
supabase_flutter: ^2.0.0
|
||||
```
|
||||
|
||||
</StepHikeCompact.Code>
|
||||
@@ -138,7 +138,7 @@ export const meta = {
|
||||
class _HomePageState extends State<HomePage> {
|
||||
final _future = Supabase.instance.client
|
||||
.from('countries')
|
||||
.select<List<Map<String, dynamic>>>();
|
||||
.select();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
@@ -36,7 +36,7 @@ Then let's install the only additional dependency: [`supabase_flutter`](https://
|
||||
Copy and paste the following line in your pubspec.yaml to install the package:
|
||||
|
||||
```yaml
|
||||
supabase_flutter: ^1.10.3
|
||||
supabase_flutter: ^2.0.0
|
||||
```
|
||||
|
||||
Run `flutter pub get` to install the dependencies.
|
||||
@@ -136,7 +136,6 @@ Future<void> main() async {
|
||||
await Supabase.initialize(
|
||||
url: 'YOUR_SUPABASE_URL',
|
||||
anonKey: 'YOUR_SUPABASE_ANON_KEY',
|
||||
authFlowType: AuthFlowType.pkce,
|
||||
);
|
||||
runApp(MyApp());
|
||||
}
|
||||
@@ -144,8 +143,6 @@ Future<void> main() async {
|
||||
final supabase = Supabase.instance.client;
|
||||
```
|
||||
|
||||
`AuthFlowType.pkce` on `authFlowType` parameter indicates that we are using a secure [PKCE flow](https://supabase.com/blog/supabase-auth-sso-pkce#introducing-pkce) to perform our magic link login.
|
||||
|
||||
### Set up Splash Screen
|
||||
|
||||
Let's create a splash screen that will be shown to users right after they open the app.
|
||||
@@ -331,11 +328,8 @@ class _AccountPageState extends State<AccountPage> {
|
||||
|
||||
try {
|
||||
final userId = supabase.auth.currentUser!.id;
|
||||
final data = await supabase
|
||||
.from('profiles')
|
||||
.select<Map<String, dynamic>>()
|
||||
.eq('id', userId)
|
||||
.single();
|
||||
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) {
|
||||
@@ -547,7 +541,7 @@ We will use [`image_picker`](https://pub.dev/packages/image_picker) plugin to se
|
||||
Add the following line in your pubspec.yaml file to install `image_picker`:
|
||||
|
||||
```yaml
|
||||
image_picker: ^0.8.4
|
||||
image_picker: ^1.0.5
|
||||
```
|
||||
|
||||
Using [`image_picker`](https://pub.dev/packages/image_picker) requires some additional preparation depending on the platform.
|
||||
@@ -693,10 +687,10 @@ class _AccountPageState extends State<AccountPage> {
|
||||
});
|
||||
|
||||
try {
|
||||
final userId = supabase.auth.currentUser!.id;
|
||||
final userId = supabase.auth.currentSession!.user.id;
|
||||
final data = await supabase
|
||||
.from('profiles')
|
||||
.select<Map<String, dynamic>>()
|
||||
.select()
|
||||
.eq('id', userId)
|
||||
.single();
|
||||
_usernameController.text = (data['username'] ?? '') as String;
|
||||
|
||||
@@ -210,10 +210,10 @@ Now the fun part starts! We will start out by creating our game class. We create
|
||||
|
||||

|
||||
|
||||
Let’s add flame to our app by adding the following to our `pubspec.yaml` file to install flame.
|
||||
Let's add flame to our app. Run the following command:
|
||||
|
||||
```yaml
|
||||
flame: ^1.6.0
|
||||
```bash
|
||||
flutter pub add flame
|
||||
```
|
||||
|
||||
We can then create `MyGame` class. Add the following code in `lib/game.dart` file.
|
||||
@@ -567,23 +567,22 @@ class Bullet extends PositionComponent with CollisionCallbacks, HasGameRef {
|
||||
|
||||
At this point, we have a working shooting game except the opponent does not move, because we have not added any ways to communicate between clients. We will use Supabase’s [realtime features](https://supabase.com/docs/guides/realtime) for this, because it gives us an out of the box solution to handle low-latency real-time communication between players. If you do not have a Supabase project created yet, head over to [database.new](https://database.new/) to create one.
|
||||
|
||||
Before we get into any coding, let’s install the Supabase SDK into our app. We will also use the [uuid package](https://pub.dev/packages/uuid) to generate random unique ids for the users. Add the following to `pubspec.yaml` file.
|
||||
Before we get into any coding, let’s install the Supabase SDK into our app. We will also use the [uuid package](https://pub.dev/packages/uuid) to generate random unique ids for the users. Run the following command:
|
||||
|
||||
```yaml
|
||||
supabase_flutter: ^1.4.0
|
||||
uuid: ^3.0.7
|
||||
```bash
|
||||
flutter pub add supabase_flutter uuid
|
||||
```
|
||||
|
||||
Once `pub get` is complete, let’s initialize Supabase. We will override the `main` function to initialize Supabase. You can get your Supabase URL and Anon Key at `Project Setting` > `API`. Copy and paste them into the `Supabase.initialize` call.
|
||||
|
||||
```dart
|
||||
void main() async {
|
||||
await Supabase.initialize(
|
||||
url: 'YOUR_SUPABASE_URL',
|
||||
anonKey: 'YOUR_ANON_KEY',
|
||||
realtimeClientOptions: const RealtimeClientOptions(eventsPerSecond: 40),
|
||||
);
|
||||
runApp(const MyApp());
|
||||
await Supabase.initialize(
|
||||
url: 'YOUR_SUPABASE_URL',
|
||||
anonKey: 'YOUR_ANON_KEY',
|
||||
realtimeClientOptions: const RealtimeClientOptions(eventsPerSecond: 40),
|
||||
);
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
// Extract Supabase client for easy access to Supabase
|
||||
@@ -618,33 +617,36 @@ class _LobbyDialogState extends State<_LobbyDialog> {
|
||||
'lobby',
|
||||
opts: const RealtimeChannelConfig(self: true),
|
||||
);
|
||||
_lobbyChannel.on(RealtimeListenTypes.presence, ChannelFilter(event: 'sync'),
|
||||
(payload, [ref]) {
|
||||
// Update the lobby count
|
||||
final presenceState = _lobbyChannel.presenceState();
|
||||
_lobbyChannel
|
||||
.onPresenceSync((payload, [ref]) {
|
||||
// Update the lobby count
|
||||
final presenceStates = _lobbyChannel.presenceState();
|
||||
|
||||
setState(() {
|
||||
_userids = presenceState.values
|
||||
.map((presences) =>
|
||||
(presences.first as Presence).payload['user_id'] as String)
|
||||
.toList();
|
||||
});
|
||||
}).on(RealtimeListenTypes.broadcast, ChannelFilter(event: 'game_start'),
|
||||
(payload, [_]) {
|
||||
// Start the game if someone has started a game with you
|
||||
final participantIds = List<String>.from(payload['participants']);
|
||||
if (participantIds.contains(myUserId)) {
|
||||
final gameId = payload['game_id'] as String;
|
||||
widget.onGameStarted(gameId);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}).subscribe(
|
||||
(status, [ref]) async {
|
||||
if (status == 'SUBSCRIBED') {
|
||||
await _lobbyChannel.track({'user_id': myUserId});
|
||||
}
|
||||
},
|
||||
);
|
||||
setState(() {
|
||||
_userids = presenceStates
|
||||
.map((presenceState) => (presenceState.presences.first)
|
||||
.payload['user_id'] as String)
|
||||
.toList();
|
||||
});
|
||||
})
|
||||
.onBroadcast(
|
||||
event: 'game_start',
|
||||
callback: (payload, [_]) {
|
||||
// Start the game if someone has started a game with you
|
||||
final participantIds = List<String>.from(payload['participants']);
|
||||
if (participantIds.contains(myUserId)) {
|
||||
final gameId = payload['game_id'] as String;
|
||||
widget.onGameStarted(gameId);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
})
|
||||
.subscribe(
|
||||
(status, _) async {
|
||||
if (status == RealtimeSubscribeStatus.subscribed) {
|
||||
await _lobbyChannel.track({'user_id': myUserId});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -675,8 +677,7 @@ class _LobbyDialogState extends State<_LobbyDialog> {
|
||||
final opponentId =
|
||||
_userids.firstWhere((userId) => userId != myUserId);
|
||||
final gameId = const Uuid().v4();
|
||||
await _lobbyChannel.send(
|
||||
type: RealtimeListenTypes.broadcast,
|
||||
await _lobbyChannel.sendBroadcastMessage(
|
||||
event: 'game_start',
|
||||
payload: {
|
||||
'participants': [
|
||||
@@ -738,10 +739,8 @@ class _GamePageState extends State<GamePage> {
|
||||
_game = MyGame(
|
||||
onGameStateUpdate: (position, health) async {
|
||||
ChannelResponse response;
|
||||
// Loop until the send succeeds if the payload is to notify defeat.
|
||||
do {
|
||||
response = await _gameChannel!.send(
|
||||
type: RealtimeListenTypes.broadcast,
|
||||
response = await _gameChannel!.sendBroadcastMessage(
|
||||
event: 'game_state',
|
||||
payload: {'x': position.x, 'y': position.y, 'health': health},
|
||||
);
|
||||
@@ -799,23 +798,27 @@ class _GamePageState extends State<GamePage> {
|
||||
_gameChannel = supabase.channel(gameId,
|
||||
opts: const RealtimeChannelConfig(ack: true));
|
||||
|
||||
_gameChannel!.on(RealtimeListenTypes.broadcast,
|
||||
ChannelFilter(event: 'game_state'), (payload, [_]) {
|
||||
final position =
|
||||
Vector2(payload['x'] as double, payload['y'] as double);
|
||||
final opponentHealth = payload['health'] as int;
|
||||
_game.updateOpponent(
|
||||
position: position,
|
||||
health: opponentHealth,
|
||||
);
|
||||
_gameChannel!
|
||||
.onBroadcast(
|
||||
event: 'game_state',
|
||||
callback: (payload, [_]) {
|
||||
final position = Vector2(
|
||||
payload['x'] as double, payload['y'] as double);
|
||||
final opponentHealth = payload['health'] as int;
|
||||
_game.updateOpponent(
|
||||
position: position,
|
||||
health: opponentHealth,
|
||||
);
|
||||
|
||||
if (opponentHealth <= 0) {
|
||||
if (!_game.isGameOver) {
|
||||
_game.isGameOver = true;
|
||||
_game.onGameOver(true);
|
||||
}
|
||||
}
|
||||
}).subscribe();
|
||||
if (opponentHealth <= 0) {
|
||||
if (!_game.isGameOver) {
|
||||
_game.isGameOver = true;
|
||||
_game.onGameOver(true);
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
.subscribe();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -668,8 +668,7 @@ class HomePage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final privatePostsFuture =
|
||||
supabase.from('private_posts').select<List<Map<String, dynamic>>>();
|
||||
final privatePostsFuture = supabase.from('private_posts').select();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
|
||||
@@ -208,7 +208,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
}
|
||||
|
||||
return supabase.auth.signInWithIdToken(
|
||||
provider: Provider.google,
|
||||
provider: OAuthProvider.google,
|
||||
idToken: idToken,
|
||||
accessToken: accessToken,
|
||||
);
|
||||
|
||||
@@ -11,8 +11,7 @@ class HomePage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final privatePostsFuture =
|
||||
supabase.from('private_posts').select<List<Map<String, dynamic>>>();
|
||||
final privatePostsFuture = supabase.from('private_posts').select();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
|
||||
@@ -1,40 +1,18 @@
|
||||
name: mfa_app
|
||||
description: A new Flutter project.
|
||||
# The following line prevents the package from being accidentally published to
|
||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
# The following defines the version and build number for your application.
|
||||
# A version number is three numbers separated by dots, like 1.2.43
|
||||
# followed by an optional build number separated by a +.
|
||||
# Both the version and the builder number may be overridden in flutter
|
||||
# build by specifying --build-name and --build-number, respectively.
|
||||
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions whie build-number is used as the build suffix.
|
||||
publish_to: 'none'
|
||||
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: '>=2.19.6 <4.0.0'
|
||||
|
||||
# Dependencies specify other packages that your package needs in order to work.
|
||||
# To automatically upgrade your package dependencies to the latest versions
|
||||
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
||||
# dependencies can be manually updated by changing the version numbers below to
|
||||
# the latest version available on pub.dev. To see which dependencies have newer
|
||||
# versions available, run `flutter pub outdated`.
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.2
|
||||
supabase_flutter: ^1.8.1
|
||||
supabase_flutter: ^2.0.0
|
||||
go_router: ^7.0.0
|
||||
flutter_svg: ^2.0.5
|
||||
|
||||
@@ -42,50 +20,7 @@ dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
# The "flutter_lints" package below contains a set of recommended lints to
|
||||
# encourage good coding practices. The lint set provided by the package is
|
||||
# activated in the `analysis_options.yaml` file located at the root of your
|
||||
# package. See that file for information about deactivating specific lint
|
||||
# rules and activating additional ones.
|
||||
flutter_lints: ^2.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
# The following line ensures that the Material Icons font is
|
||||
# included with your application, so that you can use the icons in
|
||||
# the material Icons class.
|
||||
uses-material-design: true
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
|
||||
# For details regarding adding assets from package dependencies, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
|
||||
# To add custom fonts to your application, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts from package dependencies,
|
||||
# see https://flutter.dev/custom-fonts/#from-packages
|
||||
@@ -62,7 +62,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
}
|
||||
|
||||
return supabase.auth.signInWithIdToken(
|
||||
provider: Provider.google,
|
||||
provider: OAuthProvider.google,
|
||||
idToken: idToken,
|
||||
accessToken: accessToken,
|
||||
);
|
||||
|
||||
@@ -69,10 +69,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.2"
|
||||
version: "1.18.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -140,10 +140,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: functions_client
|
||||
sha256: "3b157b4d3ae9e38614fd80fab76d1ef1e0e39ff3412a45de2651f27cecb9d2d2"
|
||||
sha256: "57c383e82d9e66c1781918117d32a3b01581478cb0be883ec0cc394402cb7449"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
version: "2.0.0-dev.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -204,10 +204,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: gotrue
|
||||
sha256: "3d15ee24bd05c6b4e5587f6dba727a7c031e5513424aa2ab4fb35b42f8c45ba7"
|
||||
sha256: "64a20fb8897838b9bf3e265c57c9c343c21a8e73bf8877de9e2a66228594dbe5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.12.2"
|
||||
version: "2.0.0-dev.2"
|
||||
hive:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -284,10 +284,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
version: "1.10.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -388,10 +388,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: postgrest
|
||||
sha256: "87e35d3a59e327188321befbfbfcc5a7a2e71f0d0a13d975cbc7d169387ec712"
|
||||
sha256: "38ab04fc739bc02e407c26bee05e9981122aa4a9b08e188f46dffac16dca776e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
version: "2.0.0-dev.2"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -412,10 +412,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: realtime_client
|
||||
sha256: bf25420988263ba3811f65756685bf4813a527277a784150b8b7de0a583e122f
|
||||
sha256: aabb7de6051a0621c30640784fefd034676a2057ac17b5d5c84d099564363bec
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.3"
|
||||
version: "2.0.0-dev.3"
|
||||
retry:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -488,30 +488,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
sign_in_with_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sign_in_with_apple
|
||||
sha256: "0975c23b9f8b30a80e27d5659a75993a093d4cb5f4eb7d23a9ccc586fea634e0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
sign_in_with_apple_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sign_in_with_apple_platform_interface
|
||||
sha256: a5883edee09ed6be19de19e7d9f618a617fe41a6fa03f76d082dfb787e9ea18d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
sign_in_with_apple_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sign_in_with_apple_web
|
||||
sha256: "44b66528f576e77847c14999d5e881e17e7223b7b0625a185417829e5306f47a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@@ -529,26 +505,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.11.1"
|
||||
storage_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: storage_client
|
||||
sha256: "4bf2fc76f09c3698f0ba3f1a44d567995796f6aef76501f194631d0c03752ab7"
|
||||
sha256: "8803864e1ca8157ab88c7fd292e3182d75b19553198da5e0760f433fcd633784"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.2"
|
||||
version: "2.0.0-dev.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -561,18 +537,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: supabase
|
||||
sha256: ee6ab8aa31438de59027888f87e53df97e138cdd00c0125d4f6f5244c31fc21e
|
||||
sha256: "627fba3c0727b4285e2bc26f36f07746021c9997ab7a273c3628e152a1243ae8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.6"
|
||||
version: "2.0.0-dev.4"
|
||||
supabase_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: supabase_flutter
|
||||
sha256: "27ae595efb3ef6612be1270bd368237916e41b2ba20ea99fedd2df220b424888"
|
||||
sha256: d6b17ea4c8437e1e648039b68ee2ddf48a5ab66e66f83b90b6b5f3e44c980d1d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.19"
|
||||
version: "2.0.0-dev.4"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -585,10 +561,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
version: "0.6.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -597,14 +573,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
universal_io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: universal_io
|
||||
sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.2"
|
||||
url_launcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -689,10 +657,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.4-beta"
|
||||
version: "0.3.0"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -701,38 +669,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
webview_flutter:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter
|
||||
sha256: c1ab9b81090705c6069197d9fdc1625e587b52b8d70cdde2339d177ad0dbb98e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.4.1"
|
||||
webview_flutter_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_android
|
||||
sha256: b0cd33dd7d3dd8e5f664e11a19e17ba12c352647269921a3b568406b001f1dff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.12.0"
|
||||
webview_flutter_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_platform_interface
|
||||
sha256: "6d9213c65f1060116757a7c473247c60f3f7f332cac33dc417c9e362a9a13e4f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.0"
|
||||
webview_flutter_wkwebview:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_wkwebview
|
||||
sha256: "30b9af6bdd457b44c08748b9190d23208b5165357cc2eb57914fee1366c42974"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.9.1"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -761,10 +697,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yet_another_json_isolate
|
||||
sha256: "86fad76026c4241a32831d6c7febd8f9bded5019e2cd36c5b148499808d8307d"
|
||||
sha256: b1de9d553a20c7d47077b8ba388319194365ccc4890ee6fdea9e845a6e7e4164
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
version: "2.0.0-dev.0"
|
||||
sdks:
|
||||
dart: ">=3.1.0 <4.0.0"
|
||||
dart: ">=3.2.0-194.0.dev <4.0.0"
|
||||
flutter: ">=3.13.0"
|
||||
@@ -12,7 +12,7 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
supabase_flutter: ^1.10.19
|
||||
supabase_flutter: ^2.0.0
|
||||
google_sign_in: ^6.1.5
|
||||
|
||||
dev_dependencies:
|
||||
|
||||
@@ -65,8 +65,7 @@ class _GamePageState extends State<GamePage> {
|
||||
onGameStateUpdate: (position, health) async {
|
||||
ChannelResponse response;
|
||||
do {
|
||||
response = await _gameChannel!.send(
|
||||
type: RealtimeListenTypes.broadcast,
|
||||
response = await _gameChannel!.sendBroadcastMessage(
|
||||
event: 'game_state',
|
||||
payload: {'x': position.x, 'y': position.y, 'health': health},
|
||||
);
|
||||
@@ -124,23 +123,27 @@ class _GamePageState extends State<GamePage> {
|
||||
_gameChannel = supabase.channel(gameId,
|
||||
opts: const RealtimeChannelConfig(ack: true));
|
||||
|
||||
_gameChannel!.on(RealtimeListenTypes.broadcast,
|
||||
ChannelFilter(event: 'game_state'), (payload, [_]) {
|
||||
final position =
|
||||
Vector2(payload['x'] as double, payload['y'] as double);
|
||||
final opponentHealth = payload['health'] as int;
|
||||
_game.updateOpponent(
|
||||
position: position,
|
||||
health: opponentHealth,
|
||||
);
|
||||
_gameChannel!
|
||||
.onBroadcast(
|
||||
event: 'game_state',
|
||||
callback: (payload, [_]) {
|
||||
final position = Vector2(
|
||||
payload['x'] as double, payload['y'] as double);
|
||||
final opponentHealth = payload['health'] as int;
|
||||
_game.updateOpponent(
|
||||
position: position,
|
||||
health: opponentHealth,
|
||||
);
|
||||
|
||||
if (opponentHealth <= 0) {
|
||||
if (!_game.isGameOver) {
|
||||
_game.isGameOver = true;
|
||||
_game.onGameOver(true);
|
||||
}
|
||||
}
|
||||
}).subscribe();
|
||||
if (opponentHealth <= 0) {
|
||||
if (!_game.isGameOver) {
|
||||
_game.isGameOver = true;
|
||||
_game.onGameOver(true);
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
.subscribe();
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -175,33 +178,36 @@ class _LobbyDialogState extends State<_LobbyDialog> {
|
||||
'lobby',
|
||||
opts: const RealtimeChannelConfig(self: true),
|
||||
);
|
||||
_lobbyChannel.on(RealtimeListenTypes.presence, ChannelFilter(event: 'sync'),
|
||||
(payload, [ref]) {
|
||||
// Update the lobby count
|
||||
final presenceState = _lobbyChannel.presenceState();
|
||||
_lobbyChannel
|
||||
.onPresenceSync((payload, [ref]) {
|
||||
// Update the lobby count
|
||||
final presenceStates = _lobbyChannel.presenceState();
|
||||
|
||||
setState(() {
|
||||
_userids = presenceState.values
|
||||
.map((presences) =>
|
||||
(presences.first as Presence).payload['user_id'] as String)
|
||||
.toList();
|
||||
});
|
||||
}).on(RealtimeListenTypes.broadcast, ChannelFilter(event: 'game_start'),
|
||||
(payload, [_]) {
|
||||
// Start the game if someone has started a game with you
|
||||
final participantIds = List<String>.from(payload['participants']);
|
||||
if (participantIds.contains(myUserId)) {
|
||||
final gameId = payload['game_id'] as String;
|
||||
widget.onGameStarted(gameId);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}).subscribe(
|
||||
(status, [ref]) async {
|
||||
if (status == 'SUBSCRIBED') {
|
||||
await _lobbyChannel.track({'user_id': myUserId});
|
||||
}
|
||||
},
|
||||
);
|
||||
setState(() {
|
||||
_userids = presenceStates
|
||||
.map((presenceState) => (presenceState.presences.first)
|
||||
.payload['user_id'] as String)
|
||||
.toList();
|
||||
});
|
||||
})
|
||||
.onBroadcast(
|
||||
event: 'game_start',
|
||||
callback: (payload, [_]) {
|
||||
// Start the game if someone has started a game with you
|
||||
final participantIds = List<String>.from(payload['participants']);
|
||||
if (participantIds.contains(myUserId)) {
|
||||
final gameId = payload['game_id'] as String;
|
||||
widget.onGameStarted(gameId);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
})
|
||||
.subscribe(
|
||||
(status, _) async {
|
||||
if (status == RealtimeSubscribeStatus.subscribed) {
|
||||
await _lobbyChannel.track({'user_id': myUserId});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -232,8 +238,7 @@ class _LobbyDialogState extends State<_LobbyDialog> {
|
||||
final opponentId =
|
||||
_userids.firstWhere((userId) => userId != myUserId);
|
||||
final gameId = const Uuid().v4();
|
||||
await _lobbyChannel.send(
|
||||
type: RealtimeListenTypes.broadcast,
|
||||
await _lobbyChannel.sendBroadcastMessage(
|
||||
event: 'game_start',
|
||||
payload: {
|
||||
'participants': [
|
||||
|
||||
@@ -12,9 +12,9 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
supabase_flutter: ^1.4.0
|
||||
flame: ^1.6.0
|
||||
uuid: ^3.0.7
|
||||
supabase_flutter: ^2.0.0
|
||||
flame: ^1.12.0
|
||||
uuid: ^4.2.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// This is a basic Flutter widget test.
|
||||
//
|
||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:flame_realtime_shooting/main.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const MyApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
expect(find.text('1'), findsNothing);
|
||||
|
||||
// Tap the '+' icon and trigger a frame.
|
||||
await tester.tap(find.byIcon(Icons.add));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that our counter has incremented.
|
||||
expect(find.text('0'), findsNothing);
|
||||
expect(find.text('1'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
@@ -10,12 +10,8 @@ PODS:
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sign_in_with_apple (0.0.1):
|
||||
- Flutter
|
||||
- url_launcher_ios (0.0.1):
|
||||
- Flutter
|
||||
- webview_flutter_wkwebview (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- app_links (from `.symlinks/plugins/app_links/ios`)
|
||||
@@ -23,9 +19,7 @@ DEPENDENCIES:
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
app_links:
|
||||
@@ -38,12 +32,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
sign_in_with_apple:
|
||||
:path: ".symlinks/plugins/sign_in_with_apple/ios"
|
||||
url_launcher_ios:
|
||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||
webview_flutter_wkwebview:
|
||||
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
app_links: 5ef33d0d295a89d9d16bb81b0e3b0d5f70d6c875
|
||||
@@ -51,9 +41,7 @@ SPEC CHECKSUMS:
|
||||
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c
|
||||
sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440
|
||||
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
||||
webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
|
||||
|
||||
PODFILE CHECKSUM: 7368163408c647b7eb699d0d788ba6718e18fb8d
|
||||
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1300;
|
||||
LastUpgradeCheck = 1430;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
97C146ED1CF9000F007C117D = {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1300"
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -9,7 +9,6 @@ Future<void> main() async {
|
||||
// TODO: Replace credentials with your own
|
||||
url: 'YOUR_SUPABASE_URL',
|
||||
anonKey: 'YOUR_SUPABASE_ANON_KEY',
|
||||
authFlowType: AuthFlowType.pkce,
|
||||
);
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
@@ -24,12 +24,9 @@ class _AccountPageState extends State<AccountPage> {
|
||||
});
|
||||
|
||||
try {
|
||||
final userId = supabase.auth.currentUser!.id;
|
||||
final data = await supabase
|
||||
.from('profiles')
|
||||
.select<Map<String, dynamic>>()
|
||||
.eq('id', userId)
|
||||
.single();
|
||||
final userId = supabase.auth.currentSession!.user.id;
|
||||
final data =
|
||||
await supabase.from('profiles').select().eq('id', userId).single();
|
||||
_usernameController.text = (data['username'] ?? '') as String;
|
||||
_websiteController.text = (data['website'] ?? '') as String;
|
||||
_avatarUrl = (data['avatar_url'] ?? '') as String;
|
||||
|
||||
@@ -12,8 +12,8 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
image_picker: ^0.8.4
|
||||
supabase_flutter: ^1.10.3
|
||||
image_picker: ^1.0.5
|
||||
supabase_flutter: ^2.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Reference in new issue
Block a user