diff --git a/wien_talks/wien_talks_client/lib/src/protocol/client.dart b/wien_talks/wien_talks_client/lib/src/protocol/client.dart index 3440443..0d92249 100644 --- a/wien_talks/wien_talks_client/lib/src/protocol/client.dart +++ b/wien_talks/wien_talks_client/lib/src/protocol/client.dart @@ -42,6 +42,21 @@ class EndpointQuote extends _i1.EndpointRef { @override String get name => 'quote'; + _i2.Future updateQuote(_i4.Quote quote) => + caller.callServerEndpoint( + 'quote', + 'updateQuote', + {'quote': quote}, + ); + + _i2.Stream<_i4.Quote> quoteUpdates() => + caller.callStreamingServerEndpoint<_i2.Stream<_i4.Quote>, _i4.Quote>( + 'quote', + 'quoteUpdates', + {}, + {}, + ); + _i2.Future<_i4.Quote> createQuote(_i5.CreateQuoteRequest req) => caller.callServerEndpoint<_i4.Quote>( 'quote', diff --git a/wien_talks/wien_talks_flutter/lib/main.dart b/wien_talks/wien_talks_flutter/lib/main.dart index b1326db..d39a4a8 100644 --- a/wien_talks/wien_talks_flutter/lib/main.dart +++ b/wien_talks/wien_talks_flutter/lib/main.dart @@ -21,9 +21,13 @@ void main() { // You can set the variable when running or building your app like this: // E.g. `flutter run --dart-define=SERVER_URL=https://api.example.com/` const serverUrlFromEnv = String.fromEnvironment('SERVER_URL'); - final serverUrl = serverUrlFromEnv.isEmpty ? 'http://$localhost:8080/' : serverUrlFromEnv; + final serverUrl = + serverUrlFromEnv.isEmpty ? 'http://$localhost:8080/' : serverUrlFromEnv; - client = Client(serverUrl)..connectivityMonitor = FlutterConnectivityMonitor(); + client = Client(serverUrl) + ..connectivityMonitor = FlutterConnectivityMonitor(); + + client.openStreamingConnection(); runApp(const MyApp()); } diff --git a/wien_talks/wien_talks_flutter/lib/news_screen.dart b/wien_talks/wien_talks_flutter/lib/news_screen.dart index 5cdd782..4fcb635 100644 --- a/wien_talks/wien_talks_flutter/lib/news_screen.dart +++ b/wien_talks/wien_talks_flutter/lib/news_screen.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:wien_talks_flutter/main.dart'; import 'package:wien_talks_flutter/widgets/heading_text.dart'; import 'package:wien_talks_flutter/widgets/screen_widget.dart'; @@ -10,24 +11,32 @@ class NewsScreen extends StatelessWidget { @override Widget build(BuildContext context) { + var column = Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + HeadingText(text: "Latest news"), + ...[Text("News 1"), Text("News 2")], + SizedBox( + height: 30, + ), + OutlinedButton( + onPressed: () { + context.pushNamed("create_event"); + }, + child: Text("Submit your own event")), + ], + ); return ScreenWidget( child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - HeadingText(text: "Latest news"), - ...[Text("News 1"), Text("News 2")], - SizedBox( - height: 30, - ), - OutlinedButton( - onPressed: () { - context.pushNamed("create_event"); - }, - child: Text("Submit your own event")), - ], - ), - ), + child: StreamBuilder( + stream: client.quote.quoteUpdates(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.active) { + return Text(snapshot.data?.text ?? 'Empty Text'); + } + + return Text('Empty or Error'); + })), ); } } diff --git a/wien_talks/wien_talks_flutter/lib/widgets/add-quote-fab.dart b/wien_talks/wien_talks_flutter/lib/widgets/add-quote-fab.dart new file mode 100644 index 0000000..31750ef --- /dev/null +++ b/wien_talks/wien_talks_flutter/lib/widgets/add-quote-fab.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:wien_talks_client/wien_talks_client.dart'; +import 'package:wien_talks_flutter/main.dart'; + +class AddQuoteFab extends StatelessWidget { + const AddQuoteFab({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return FloatingActionButton(onPressed: () { + client.quote.createQuote( + CreateQuoteRequest(text: 'Quote Text', lat: 22, lng: 140)); + }); + } +} diff --git a/wien_talks/wien_talks_flutter/lib/widgets/screen_widget.dart b/wien_talks/wien_talks_flutter/lib/widgets/screen_widget.dart index 26638d4..3237ce3 100644 --- a/wien_talks/wien_talks_flutter/lib/widgets/screen_widget.dart +++ b/wien_talks/wien_talks_flutter/lib/widgets/screen_widget.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:wien_talks_flutter/widgets/add-quote-fab.dart'; class ScreenWidget extends StatelessWidget { final Widget child; @@ -11,6 +12,7 @@ class ScreenWidget extends StatelessWidget { appBar: AppBar( title: const Text('News'), ), + floatingActionButton: AddQuoteFab(), body: SafeArea( child: Padding( padding: const EdgeInsets.all(8.0), diff --git a/wien_talks/wien_talks_flutter/macos/Flutter/GeneratedPluginRegistrant.swift b/wien_talks/wien_talks_flutter/macos/Flutter/GeneratedPluginRegistrant.swift index 09409a5..407ec0f 100644 --- a/wien_talks/wien_talks_flutter/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/wien_talks/wien_talks_flutter/macos/Flutter/GeneratedPluginRegistrant.swift @@ -10,11 +10,8 @@ import file_picker import file_selector_macos import location import path_provider_foundation -<<<<<<< Updated upstream import shared_preferences_foundation import sqflite_darwin -======= ->>>>>>> Stashed changes func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) @@ -22,9 +19,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) -<<<<<<< Updated upstream SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) -======= ->>>>>>> Stashed changes } diff --git a/wien_talks/wien_talks_server/lib/src/generated/endpoints.dart b/wien_talks/wien_talks_server/lib/src/generated/endpoints.dart index 13b7730..b616e1a 100644 --- a/wien_talks/wien_talks_server/lib/src/generated/endpoints.dart +++ b/wien_talks/wien_talks_server/lib/src/generated/endpoints.dart @@ -12,9 +12,10 @@ import 'package:serverpod/serverpod.dart' as _i1; import '../greeting_endpoint.dart' as _i2; import '../quotes/quotes_endpoint.dart' as _i3; +import 'package:wien_talks_server/src/generated/quotes/quote.dart' as _i4; import 'package:wien_talks_server/src/generated/quotes/create_quote.dart' - as _i4; -import 'package:serverpod_auth_server/serverpod_auth_server.dart' as _i5; + as _i5; +import 'package:serverpod_auth_server/serverpod_auth_server.dart' as _i6; class Endpoints extends _i1.EndpointDispatch { @override @@ -61,12 +62,30 @@ class Endpoints extends _i1.EndpointDispatch { name: 'quote', endpoint: endpoints['quote']!, methodConnectors: { + 'updateQuote': _i1.MethodConnector( + name: 'updateQuote', + params: { + 'quote': _i1.ParameterDescription( + name: 'quote', + type: _i1.getType<_i4.Quote>(), + nullable: false, + ) + }, + call: ( + _i1.Session session, + Map params, + ) async => + (endpoints['quote'] as _i3.QuoteEndpoint).updateQuote( + session, + params['quote'], + ), + ), 'createQuote': _i1.MethodConnector( name: 'createQuote', params: { 'req': _i1.ParameterDescription( name: 'req', - type: _i1.getType<_i4.CreateQuoteRequest>(), + type: _i1.getType<_i5.CreateQuoteRequest>(), nullable: false, ) }, @@ -106,8 +125,20 @@ class Endpoints extends _i1.EndpointDispatch { ) async => (endpoints['quote'] as _i3.QuoteEndpoint).getAllQuotes(session), ), + 'quoteUpdates': _i1.MethodStreamConnector( + name: 'quoteUpdates', + params: {}, + streamParams: {}, + returnType: _i1.MethodStreamReturnType.streamType, + call: ( + _i1.Session session, + Map params, + Map streamParams, + ) => + (endpoints['quote'] as _i3.QuoteEndpoint).quoteUpdates(session), + ), }, ); - modules['serverpod_auth'] = _i5.Endpoints()..initializeEndpoints(server); + modules['serverpod_auth'] = _i6.Endpoints()..initializeEndpoints(server); } } diff --git a/wien_talks/wien_talks_server/lib/src/generated/protocol.yaml b/wien_talks/wien_talks_server/lib/src/generated/protocol.yaml index 5c2d35a..160b550 100644 --- a/wien_talks/wien_talks_server/lib/src/generated/protocol.yaml +++ b/wien_talks/wien_talks_server/lib/src/generated/protocol.yaml @@ -1,6 +1,8 @@ greeting: - hello: quote: + - updateQuote: + - quoteUpdates: - createQuote: - getQuoteById: - getAllQuotes: diff --git a/wien_talks/wien_talks_server/lib/src/quotes/quote_controller.dart b/wien_talks/wien_talks_server/lib/src/quotes/quote_util.dart similarity index 100% rename from wien_talks/wien_talks_server/lib/src/quotes/quote_controller.dart rename to wien_talks/wien_talks_server/lib/src/quotes/quote_util.dart diff --git a/wien_talks/wien_talks_server/lib/src/quotes/quotes_endpoint.dart b/wien_talks/wien_talks_server/lib/src/quotes/quotes_endpoint.dart index 5cfe820..6108211 100644 --- a/wien_talks/wien_talks_server/lib/src/quotes/quotes_endpoint.dart +++ b/wien_talks/wien_talks_server/lib/src/quotes/quotes_endpoint.dart @@ -1,6 +1,6 @@ import 'package:serverpod/serverpod.dart'; import 'package:wien_talks_server/src/generated/protocol.dart'; -import 'package:wien_talks_server/src/quotes/quote_controller.dart'; +import 'package:wien_talks_server/src/quotes/quote_util.dart'; class QuoteEndpoint extends Endpoint { static const _channelQuoteUpdates = 'quote-updates'; diff --git a/wien_talks/wien_talks_server/test/integration/test_tools/serverpod_test_tools.dart b/wien_talks/wien_talks_server/test/integration/test_tools/serverpod_test_tools.dart index e06e769..6c77e53 100644 --- a/wien_talks/wien_talks_server/test/integration/test_tools/serverpod_test_tools.dart +++ b/wien_talks/wien_talks_server/test/integration/test_tools/serverpod_test_tools.dart @@ -177,6 +177,64 @@ class _QuoteEndpoint { final _i2.SerializationManager _serializationManager; + _i3.Future updateQuote( + _i1.TestSessionBuilder sessionBuilder, + _i5.Quote quote, + ) async { + return _i1.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _i1.InternalTestSessionBuilder).internalBuild( + endpoint: 'quote', + method: 'updateQuote', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'quote', + methodName: 'updateQuote', + parameters: _i1.testObjectToJson({'quote': quote}), + serializationManager: _serializationManager, + ); + var _localReturnValue = await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) as _i3.Future); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _i3.Stream<_i5.Quote> quoteUpdates(_i1.TestSessionBuilder sessionBuilder) { + var _localTestStreamManager = _i1.TestStreamManager<_i5.Quote>(); + _i1.callStreamFunctionAndHandleExceptions( + () async { + var _localUniqueSession = + (sessionBuilder as _i1.InternalTestSessionBuilder).internalBuild( + endpoint: 'quote', + method: 'quoteUpdates', + ); + var _localCallContext = + await _endpointDispatch.getMethodStreamCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'quote', + methodName: 'quoteUpdates', + arguments: {}, + requestedInputStreams: [], + serializationManager: _serializationManager, + ); + await _localTestStreamManager.callStreamMethod( + _localCallContext, + _localUniqueSession, + {}, + ); + }, + _localTestStreamManager.outputStreamController, + ); + return _localTestStreamManager.outputStreamController.stream; + } + _i3.Future<_i5.Quote> createQuote( _i1.TestSessionBuilder sessionBuilder, _i6.CreateQuoteRequest req,