Compare commits

..

51 commits

Author SHA1 Message Date
timokz
31491b79af
Merge pull request #1 from timokz/develop
merge develop changes for aequitosh deployment
2025-08-17 05:46:30 +02:00
tk
eb5264a553 display ubahn tapes on grid cards 2025-08-17 04:31:12 +02:00
tk
1f2934146e add map previews to grid cards 2025-08-17 04:30:47 +02:00
tk
75813426a1 add dotenv to client 2025-08-17 03:51:47 +02:00
tk
424722d31e admit defeat and use clanker code 2025-08-17 02:53:59 +02:00
tk
37fbaf4f72 address linter warnigns 2025-08-17 02:32:19 +02:00
tk
47cfb949ac improve quote list performance 2025-08-17 02:28:19 +02:00
tk
bf28ff429a introduce bottom modal for quote entry 2025-08-17 01:44:23 +02:00
tk
39e4f1142f restyle quote list 2025-08-17 01:10:22 +02:00
tk
595b4e730e resolved protocol resolution issue 2025-08-17 01:09:57 +02:00
tk
9219a04614 add auth skeleton 2025-08-17 01:09:57 +02:00
cbc788b33e readme: update readme in order to test deployment
Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 23:26:01 +02:00
9d1a61885c server: docker: fix traefik not being able to discover server
tl;dr: Since the server is in both the postgres instance's isolated
"backend" network and the public-facing "docker-net", traefik
unfortunately happened to decide to use the "backend" network for its
proxying purposes. This led to the server not being reachable at all.

This commit fixes that by explicitly telling traefik which network to
use.

Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 22:52:06 +02:00
mikes222
68e7a9720a powerpoint presentation 2025-08-16 19:47:26 +02:00
tk
83f773abe1 regenerate endpoint source 2025-08-16 19:37:06 +02:00
tk
be2a58cbd9 merge generated jank 2025-08-16 19:35:56 +02:00
c64fa677ac tree-wide: run serverpod generate
Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 19:23:11 +02:00
mikes222
5a8c072d64 A little refreshing ui change :-) 2025-08-16 18:58:17 +02:00
7631cfd326 server: docker: remove debug container from compose file
Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 18:48:34 +02:00
f87843785a server: make/docker: add deployment procedures
Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 18:48:34 +02:00
6786def063 server: dockerfile: fix broken ENTRYPOINT from generated project
This cost me an entire afternoon. I don't know whose bright idea it
was to just slap all arguments into the ENTRYPOINT, but here we are.

ENTRYPOINT now just runs the `server` executable, while COMMAND is
used to pass arguments / flags to it. This is useful for e.g. passing
`--apply-migrations` for deployments.

Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 18:48:34 +02:00
5b8b317e89 server: dockerfile: add todos for improvements
Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 18:48:34 +02:00
tk
33c98019bb regenerate stream endpoints 2025-08-16 18:39:33 +02:00
tk
9de633feb9 merge frontend changes 2025-08-16 18:10:28 +02:00
mikes222
1ef6e06329 carousel implemented 2025-08-16 17:55:23 +02:00
tk
642dddaaa3 type quote stream 2025-08-16 17:18:01 +02:00
tk
8967b1698e move client instantiation into main 2025-08-16 17:13:49 +02:00
mikes222
35edff13ef A little polishing 2025-08-16 17:06:04 +02:00
tk
5f686b7b96 increase client timeout 2025-08-16 16:58:47 +02:00
tk
07870891da rm serverpod templates 2025-08-16 16:13:51 +02:00
fb8ba7e6d1 make: fix PHONY target declarations
Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 16:12:06 +02:00
mikes222
c36081eddf Stub for creating and queriing from server implemented 2025-08-16 15:54:36 +02:00
tk
b427b44e4c rename android pkg, ignore client secrets 2025-08-16 15:47:46 +02:00
tk
707dfbd76c add sample http client call logic 2025-08-16 15:47:04 +02:00
aa20d32c27 server: make: add local-env target for convenience
Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 15:26:02 +02:00
68e940986d readme: update readme
Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 15:04:06 +02:00
2dd01b94a0 make: add top-level Makefile and defines.mk
Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 14:51:57 +02:00
82fcb683ba make: add compose file and make targets for local dev container
Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 14:51:57 +02:00
3684a0944e dockerfile: pin alpine image version to 3.22
Signed-off-by: Max R. Carrara <max@aequito.sh>
2025-08-16 14:51:57 +02:00
mikes222
4a7b426729 Location now working with map 2025-08-16 14:46:06 +02:00
tk
75724e4043 yield quote updates 2025-08-16 14:43:05 +02:00
tk
6f75132073 migrate db 2025-08-16 14:28:40 +02:00
tk
4ad511cc92 Merge branch 'develop' of https://github.com/timokz/flutter-vienna-hackathon-25 into develop 2025-08-16 14:16:40 +02:00
tk
ff8de67cbb define quote endpoint 2025-08-16 14:15:21 +02:00
tk
c952f17e30 add auth module 2025-08-16 14:04:53 +02:00
mikes222
b89bfd7bdc Input form created, location now working 2025-08-16 13:54:50 +02:00
mikes222
1f9af9183e Prepare for location-implementation 2025-08-16 13:09:22 +02:00
tk
6e78ac2665 introduce quote models 2025-08-16 13:08:10 +02:00
tk
6fd404fc88 rm env and redis 2025-08-16 12:06:10 +02:00
tk
89696dcd9b reinit as serverpod project 2025-08-16 11:58:34 +02:00
tk
3da7c7a83d init BE 2025-08-16 11:47:26 +02:00
298 changed files with 31450 additions and 305 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
wien_talks/wien_talks_flutter/pubspec.lock
wien_talks/wien_talks_flutter/android/app/google-services.json
*.pptx#

View file

@ -0,0 +1,75 @@
name: Deploy to AWS
on:
push:
branches: [ deployment-aws-production, deployment-aws-staging ]
workflow_dispatch:
inputs:
target:
description: 'Target'
required: true
default: 'production'
type: choice
options:
- 'staging'
- 'production'
jobs:
deploy:
name: Deploy to AWS
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: recursive
- name: Setup Dart SDK
uses: dart-lang/setup-dart@v1.6.5
with:
sdk: 3.5
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-2
- name: Create passwords file
working-directory: wien_talks_server
shell: bash
env:
SERVERPOD_PASSWORDS: ${{ secrets.SERVERPOD_PASSWORDS }}
run: |
pwd
echo "$SERVERPOD_PASSWORDS" > config/passwords.yaml
ls config/
- name: Get Dart packages
working-directory: wien_talks_server
run: dart pub get
- name: Compile server
working-directory: wien_talks_server
run: dart compile kernel bin/main.dart
- name: Create CodeDeploy Deployment
id: deploy
env:
PROJECT_NAME: wien_talks
AWS_NAME: wien-talks
DEPLOYMENT_BUCKET: wien-talks-deployment-6559518
TARGET: ${{ github.event.inputs.target }}
run: |
# Deploy server to AWS
TARGET="${TARGET:=${GITHUB_REF##*-}}"
echo "Deploying to target: $TARGET"
mkdir -p vendor
cp "${PROJECT_NAME}_server/deploy/aws/scripts/appspec.yml" appspec.yml
zip -r deployment.zip .
aws s3 cp deployment.zip "s3://${DEPLOYMENT_BUCKET}/deployment.zip"
aws deploy create-deployment \
--application-name "${AWS_NAME}-app" \
--deployment-group-name "${AWS_NAME}-${TARGET}-group" \
--deployment-config-name CodeDeployDefault.OneAtATime \
--s3-location "bucket=${DEPLOYMENT_BUCKET},key=deployment.zip,bundleType=zip"

View file

@ -0,0 +1,99 @@
name: Deploy to GCP
on:
push:
branches: [ deployment-gcp-production, deployment-gcp-staging ]
workflow_dispatch:
inputs:
target:
description: 'Target'
required: true
default: 'production'
type: choice
options:
- 'staging'
- 'production'
env:
# TODO: Update with your Google Cloud project id. If you have changed the
# region and zone in your Terraform configuration, you will need to change
# it here too.
PROJECT: "<PROJECT ID>"
REGION: us-central1
ZONE: us-central1-c
jobs:
deploy:
name: Deploy to Google Cloud Run
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
- name: Setting Target Mode from Input
if: ${{ github.event.inputs.target != '' }}
run: echo "TARGET=${{ github.event.inputs.target }}" >> $GITHUB_ENV
- name: Setting Target mode based on branch
if: ${{ github.event.inputs.target == '' }}
run: echo "TARGET=${GITHUB_REF##*-}" >> $GITHUB_ENV
- name: Set repository
run: echo "REPOSITORY=serverpod-${{ env.TARGET }}-container" >> $GITHUB_ENV
- name: Set Image Name
run: echo "IMAGE_NAME=serverpod" >> $GITHUB_ENV
- name: Set Service Name
run: echo "SERVICE_NAME=$(echo $IMAGE_NAME | sed 's/[^a-zA-Z0-9]/-/g')" >> $GITHUB_ENV
- name: Test
run: echo $SERVICE_NAME
- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@v1"
with:
credentials_json: "${{ secrets.GOOGLE_CREDENTIALS }}"
- name: Create passwords file
working-directory: wien_talks_server
shell: bash
env:
SERVERPOD_PASSWORDS: ${{ secrets.SERVERPOD_PASSWORDS }}
run: |
pwd
echo "$SERVERPOD_PASSWORDS" > config/passwords.yaml
ls config/
- name: Configure Docker
working-directory: wien_talks_server
run: gcloud auth configure-docker ${{ env.REGION }}-docker.pkg.dev
- name: Build the Docker image
working-directory: wien_talks_server
run: "docker build -t $IMAGE_NAME ."
- name: Tag the Docker image
working-directory: wien_talks_server
run: docker tag $IMAGE_NAME ${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT }}/${{ env.REPOSITORY }}/$IMAGE_NAME
- name: Push Docker image
working-directory: wien_talks_server
run: docker push ${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT }}/${{ env.REPOSITORY }}/$IMAGE_NAME
# Uncomment the following code to automatically restart the servers in the
# instance group when you push a new version of your code. Before doing
# this, make sure that you have successfully deployed a first version.
#
# - name: Restart servers in instance group
# run: |
# gcloud compute instance-groups managed rolling-action replace serverpod-${{ env.TARGET }}-group \
# --project=${{ env.PROJECT }} \
# --replacement-method='substitute' \
# --max-surge=1 \
# --max-unavailable=1 \
# --zone=${{ env.ZONE }}

Binary file not shown.

7
wien_talks/Makefile Normal file
View file

@ -0,0 +1,7 @@
include defines.mk
.PHONY: local
local:
$(MAKE) -C wien_talks_server local

View file

@ -1,16 +0,0 @@
# wien_talks
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

0
wien_talks/defines.mk Normal file
View file

View file

@ -1,122 +0,0 @@
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// TRY THIS: Try running your application with "flutter run". You'll see
// the application has a purple toolbar. Then, without quitting the app,
// try changing the seedColor in the colorScheme below to Colors.green
// and then invoke "hot reload" (save your changes or press the "hot
// reload" button in a Flutter-supported IDE, or press "r" if you used
// the command line to start the app).
//
// Notice that the counter didn't reset back to zero; the application
// state is not lost during the reload. To reset the state, use hot
// restart instead.
//
// This works for code too, not just values: Most code changes can be
// tested with just a hot reload.
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// TRY THIS: Try changing the color here to a specific color (to
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
// change color while the other colors stay the same.
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
//
// TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
// action in the IDE, or press "p" in the console), to see the
// wireframe for each widget.
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}

View file

@ -1,89 +0,0 @@
name: wien_talks
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 while build-number is used as the build suffix.
version: 1.0.0+1
environment:
sdk: ^3.8.1
# 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.8
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: ^5.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/to/resolution-aware-images
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/to/asset-from-package
# 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/to/font-from-package

View file

@ -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:wien_talks/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);
});
}

13
wien_talks/wien_talks_client/.gitignore vendored Normal file
View file

@ -0,0 +1,13 @@
# Files and directories created by pub
.dart_tool/
.packages
# Omit committing pubspec.lock for library packages:
# https://dart.dev/guides/libraries/private-files#pubspeclock
pubspec.lock
# Conventional directory for build outputs
build/
# Directory created by dartdoc
doc/api/

3
wien_talks/wien_talks_client/.idea/.gitignore generated vendored Normal file
View file

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

View file

@ -0,0 +1,835 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DeviceStreaming">
<option name="deviceSelectionList">
<list>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="Sony" />
<option name="codename" value="A402SO" />
<option name="id" value="A402SO" />
<option name="labId" value="google" />
<option name="manufacturer" value="Sony" />
<option name="name" value="Xperia 10" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2520" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="27" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="F01L" />
<option name="id" value="F01L" />
<option name="labId" value="google" />
<option name="manufacturer" value="FUJITSU" />
<option name="name" value="F-01L" />
<option name="screenDensity" value="360" />
<option name="screenX" value="720" />
<option name="screenY" value="1280" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="OnePlus" />
<option name="codename" value="OP535DL1" />
<option name="id" value="OP535DL1" />
<option name="labId" value="google" />
<option name="manufacturer" value="OnePlus" />
<option name="name" value="CPH2409" />
<option name="screenDensity" value="401" />
<option name="screenX" value="1080" />
<option name="screenY" value="2412" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="OnePlus" />
<option name="codename" value="OP5552L1" />
<option name="id" value="OP5552L1" />
<option name="labId" value="google" />
<option name="manufacturer" value="OnePlus" />
<option name="name" value="CPH2415" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2412" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="OPPO" />
<option name="codename" value="OP573DL1" />
<option name="id" value="OP573DL1" />
<option name="labId" value="google" />
<option name="manufacturer" value="OPPO" />
<option name="name" value="CPH2557" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="28" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="SH-01L" />
<option name="id" value="SH-01L" />
<option name="labId" value="google" />
<option name="manufacturer" value="SHARP" />
<option name="name" value="AQUOS sense2 SH-01L" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="a14m" />
<option name="id" value="a14m" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-A145R" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2408" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="a15" />
<option name="id" value="a15" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="A15" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="a15x" />
<option name="id" value="a15x" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="A15 5G" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="a16x" />
<option name="id" value="a16x" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="A16 5G" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="a35x" />
<option name="id" value="a35x" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="A35" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="akita" />
<option name="id" value="akita" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="35" />
<option name="brand" value="google" />
<option name="codename" value="akita" />
<option name="id" value="akita" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="motorola" />
<option name="codename" value="arcfox" />
<option name="id" value="arcfox" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="razr plus 2024" />
<option name="screenDensity" value="360" />
<option name="screenX" value="1080" />
<option name="screenY" value="1272" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="motorola" />
<option name="codename" value="austin" />
<option name="id" value="austin" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="moto g 5G (2022)" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="b0q" />
<option name="id" value="b0q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S22 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="b6q" />
<option name="id" value="b6q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Flip 6" />
<option name="screenDensity" value="340" />
<option name="screenX" value="1080" />
<option name="screenY" value="2640" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="32" />
<option name="brand" value="google" />
<option name="codename" value="bluejay" />
<option name="id" value="bluejay" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="caiman" />
<option name="id" value="caiman" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro" />
<option name="screenDensity" value="360" />
<option name="screenX" value="960" />
<option name="screenY" value="2142" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="35" />
<option name="brand" value="google" />
<option name="codename" value="caiman" />
<option name="id" value="caiman" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro" />
<option name="screenDensity" value="360" />
<option name="screenX" value="960" />
<option name="screenY" value="2142" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="comet" />
<option name="default" value="true" />
<option name="id" value="comet" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro Fold" />
<option name="screenDensity" value="390" />
<option name="screenX" value="2076" />
<option name="screenY" value="2152" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="35" />
<option name="brand" value="google" />
<option name="codename" value="comet" />
<option name="default" value="true" />
<option name="id" value="comet" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro Fold" />
<option name="screenDensity" value="390" />
<option name="screenX" value="2076" />
<option name="screenY" value="2152" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="29" />
<option name="brand" value="samsung" />
<option name="codename" value="crownqlteue" />
<option name="id" value="crownqlteue" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Note9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2220" />
<option name="screenY" value="1080" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="dm2q" />
<option name="id" value="dm2q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="S23 Plus" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="dm3q" />
<option name="id" value="dm3q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S23 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="motorola" />
<option name="codename" value="dubai" />
<option name="id" value="dubai" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="edge 30" />
<option name="screenDensity" value="405" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="e1q" />
<option name="default" value="true" />
<option name="id" value="e1q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S24" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="e3q" />
<option name="id" value="e3q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S24 Ultra" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1440" />
<option name="screenY" value="3120" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="eos" />
<option name="id" value="eos" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Eos" />
<option name="screenDensity" value="320" />
<option name="screenX" value="384" />
<option name="screenY" value="384" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="35" />
<option name="brand" value="motorola" />
<option name="codename" value="eqe" />
<option name="id" value="eqe" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="edge 50 pro" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1220" />
<option name="screenY" value="2712" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix" />
<option name="id" value="felix" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="felix" />
<option name="id" value="felix" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix_camera" />
<option name="id" value="felix_camera" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold (Camera-enabled)" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="motorola" />
<option name="codename" value="fogona" />
<option name="id" value="fogona" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="moto g play - 2024" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="motorola" />
<option name="codename" value="fogos" />
<option name="id" value="fogos" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="moto g34 5G" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="g0q" />
<option name="id" value="g0q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-S906U1" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="gta9pwifi" />
<option name="id" value="gta9pwifi" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-X210" />
<option name="screenDensity" value="240" />
<option name="screenX" value="1200" />
<option name="screenY" value="1920" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="gts7lwifi" />
<option name="id" value="gts7lwifi" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-T870" />
<option name="screenDensity" value="340" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="gts7xllite" />
<option name="id" value="gts7xllite" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-T738U" />
<option name="screenDensity" value="340" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="gts8uwifi" />
<option name="formFactor" value="Tablet" />
<option name="id" value="gts8uwifi" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Tab S8 Ultra" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1848" />
<option name="screenY" value="2960" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="gts8wifi" />
<option name="formFactor" value="Tablet" />
<option name="id" value="gts8wifi" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Tab S8" />
<option name="screenDensity" value="274" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="gts9fe" />
<option name="id" value="gts9fe" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Tab S9 FE 5G" />
<option name="screenDensity" value="280" />
<option name="screenX" value="1440" />
<option name="screenY" value="2304" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="gts9wifi" />
<option name="id" value="gts9wifi" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-X710" />
<option name="screenDensity" value="340" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="husky" />
<option name="id" value="husky" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8 Pro" />
<option name="screenDensity" value="390" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="motorola" />
<option name="codename" value="java" />
<option name="id" value="java" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="G20" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="komodo" />
<option name="id" value="komodo" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro XL" />
<option name="screenDensity" value="360" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="35" />
<option name="brand" value="google" />
<option name="codename" value="komodo" />
<option name="id" value="komodo" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro XL" />
<option name="screenDensity" value="360" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="motorola" />
<option name="codename" value="lion" />
<option name="id" value="lion" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="moto g04" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1612" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="lynx" />
<option name="id" value="lynx" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="motorola" />
<option name="codename" value="lyriq" />
<option name="id" value="lyriq" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="edge 40" />
<option name="screenDensity" value="400" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="motorola" />
<option name="codename" value="manaus" />
<option name="id" value="manaus" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="edge 40 neo" />
<option name="screenDensity" value="400" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="motorola" />
<option name="codename" value="maui" />
<option name="id" value="maui" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="moto g play - 2023" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="o1q" />
<option name="id" value="o1q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S21" />
<option name="screenDensity" value="421" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="google" />
<option name="codename" value="oriole" />
<option name="id" value="oriole" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="35" />
<option name="brand" value="samsung" />
<option name="codename" value="pa3q" />
<option name="id" value="pa3q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S25 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3120" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="panther" />
<option name="id" value="panther" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="q5q" />
<option name="id" value="q5q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Z Fold5" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1812" />
<option name="screenY" value="2176" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="q6q" />
<option name="id" value="q6q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Z Fold6" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1856" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="r11" />
<option name="formFactor" value="Wear OS" />
<option name="id" value="r11" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Watch" />
<option name="screenDensity" value="320" />
<option name="screenX" value="384" />
<option name="screenY" value="384" />
<option name="type" value="WEAR_OS" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="r11q" />
<option name="id" value="r11q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-S711U" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="redfin" />
<option name="id" value="redfin" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 5" />
<option name="screenDensity" value="440" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="shiba" />
<option name="id" value="shiba" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="t2q" />
<option name="id" value="t2q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S21 Plus" />
<option name="screenDensity" value="394" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="tangorpro" />
<option name="formFactor" value="Tablet" />
<option name="id" value="tangorpro" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Tablet" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="35" />
<option name="brand" value="google" />
<option name="codename" value="tegu" />
<option name="id" value="tegu" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2424" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="tokay" />
<option name="default" value="true" />
<option name="id" value="tokay" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2424" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="35" />
<option name="brand" value="google" />
<option name="codename" value="tokay" />
<option name="default" value="true" />
<option name="id" value="tokay" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2424" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="xcover7" />
<option name="id" value="xcover7" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-G556B" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2408" />
</PersistentDeviceSelectionData>
</list>
</option>
</component>
</project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/wien_talks_client.iml" filepath="$PROJECT_DIR$/.idea/wien_talks_client.iml" />
</modules>
</component>
</project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/.pub" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -0,0 +1,3 @@
## 1.0.0
- Initial version, created by Stagehand

View file

@ -0,0 +1,5 @@
# wien_talks_client
This is your Serverpod client. The code in here is mostly generated by
Serverpod, but you may want to make changes if you are adding modules to your
project.

View file

@ -0,0 +1,13 @@
# Defines a default set of lint rules enforced for
# projects at Google. For details and rationale,
# see https://github.com/dart-lang/pedantic#enabled-lints.
# For lint rules and documentation, see http://dart-lang.github.io/linter/lints.
# Uncomment to specify additional rules.
# linter:
# rules:
# - camel_case_types
analyzer:
exclude:
- lib/src/protocol/**

View file

@ -0,0 +1,5 @@
dartdoc:
categories:
"Endpoint":
markdown: doc/endpoint.md
name: Endpoint

View file

@ -0,0 +1,15 @@
# Callable endpoints
Each class contains callable methods that will call a method on the server side. These are normally defined in the `endpoint` directory in your server project. This client sends requests to these endpoints and returns the result.
Example usage:
```dart
// How to use GreetingEndpoint.
client.greeting.hello("world!");
// Generic format.
client.<endpoint>.<method>(...);
```
Please see the full official documentation [here](https://docs.serverpod.dev)

View file

@ -0,0 +1,165 @@
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
/* To generate run: "serverpod generate" */
// ignore_for_file: implementation_imports
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: public_member_api_docs
// ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_client/serverpod_client.dart' as _i1;
import 'dart:async' as _i2;
import 'package:wien_talks_client/src/protocol/health.dart' as _i3;
import 'package:wien_talks_client/src/protocol/quote.dart' as _i4;
import 'package:wien_talks_client/src/protocol/create_quote.dart' as _i5;
import 'package:wien_talks_client/src/protocol/vote.dart' as _i6;
import 'package:serverpod_auth_client/serverpod_auth_client.dart' as _i7;
import 'protocol.dart' as _i8;
/// {@category Endpoint}
class EndpointHealth extends _i1.EndpointRef {
EndpointHealth(_i1.EndpointCaller caller) : super(caller);
@override
String get name => 'health';
_i2.Future<_i3.Health> ping({String? note}) =>
caller.callServerEndpoint<_i3.Health>(
'health',
'ping',
{'note': note},
);
_i2.Future<List<_i3.Health>> all() =>
caller.callServerEndpoint<List<_i3.Health>>(
'health',
'all',
{},
);
}
/// {@category Endpoint}
class EndpointQuote extends _i1.EndpointRef {
EndpointQuote(_i1.EndpointCaller caller) : super(caller);
@override
String get name => 'quote';
_i2.Future<_i4.Quote> createQuote(_i5.CreateQuoteRequest req) =>
caller.callServerEndpoint<_i4.Quote>(
'quote',
'createQuote',
{'req': req},
);
_i2.Future<void> updateQuote(_i4.Quote quote) =>
caller.callServerEndpoint<void>(
'quote',
'updateQuote',
{'quote': quote},
);
_i2.Future<List<_i4.Quote>> getAllQuotes() =>
caller.callServerEndpoint<List<_i4.Quote>>(
'quote',
'getAllQuotes',
{},
);
_i2.Stream<_i4.Quote> streamAllQuotes({required int limit}) =>
caller.callStreamingServerEndpoint<_i2.Stream<_i4.Quote>, _i4.Quote>(
'quote',
'streamAllQuotes',
{'limit': limit},
{},
);
}
/// {@category Endpoint}
class EndpointVotes extends _i1.EndpointRef {
EndpointVotes(_i1.EndpointCaller caller) : super(caller);
@override
String get name => 'votes';
_i2.Future<List<_i6.Vote>> getAllVotes() =>
caller.callServerEndpoint<List<_i6.Vote>>(
'votes',
'getAllVotes',
{},
);
_i2.Future<String> createVote() => caller.callServerEndpoint<String>(
'votes',
'createVote',
{},
);
_i2.Future<String> sayHello() => caller.callServerEndpoint<String>(
'votes',
'sayHello',
{},
);
}
class Modules {
Modules(Client client) {
auth = _i7.Caller(client);
}
late final _i7.Caller auth;
}
class Client extends _i1.ServerpodClientShared {
Client(
String host, {
dynamic securityContext,
_i1.AuthenticationKeyManager? authenticationKeyManager,
Duration? streamingConnectionTimeout,
Duration? connectionTimeout,
Function(
_i1.MethodCallContext,
Object,
StackTrace,
)? onFailedCall,
Function(_i1.MethodCallContext)? onSucceededCall,
bool? disconnectStreamsOnLostInternetConnection,
}) : super(
host,
_i8.Protocol(),
securityContext: securityContext,
authenticationKeyManager: authenticationKeyManager,
streamingConnectionTimeout: streamingConnectionTimeout,
connectionTimeout: connectionTimeout,
onFailedCall: onFailedCall,
onSucceededCall: onSucceededCall,
disconnectStreamsOnLostInternetConnection:
disconnectStreamsOnLostInternetConnection,
) {
health = EndpointHealth(this);
quote = EndpointQuote(this);
votes = EndpointVotes(this);
modules = Modules(this);
}
late final EndpointHealth health;
late final EndpointQuote quote;
late final EndpointVotes votes;
late final Modules modules;
@override
Map<String, _i1.EndpointRef> get endpointRefLookup => {
'health': health,
'quote': quote,
'votes': votes,
};
@override
Map<String, _i1.ModuleEndpointCaller> get moduleLookup =>
{'auth': modules.auth};
}

View file

@ -0,0 +1,116 @@
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
/* To generate run: "serverpod generate" */
// ignore_for_file: implementation_imports
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: public_member_api_docs
// ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_client/serverpod_client.dart' as _i1;
abstract class CreateQuoteRequest implements _i1.SerializableModel {
CreateQuoteRequest._({
required this.text,
this.authorName,
required this.lat,
required this.lng,
this.tags,
});
factory CreateQuoteRequest({
required String text,
String? authorName,
required double lat,
required double lng,
List<String>? tags,
}) = _CreateQuoteRequestImpl;
factory CreateQuoteRequest.fromJson(Map<String, dynamic> jsonSerialization) {
return CreateQuoteRequest(
text: jsonSerialization['text'] as String,
authorName: jsonSerialization['authorName'] as String?,
lat: (jsonSerialization['lat'] as num).toDouble(),
lng: (jsonSerialization['lng'] as num).toDouble(),
tags: (jsonSerialization['tags'] as List?)
?.map((e) => e as String)
.toList(),
);
}
String text;
String? authorName;
double lat;
double lng;
List<String>? tags;
/// Returns a shallow copy of this [CreateQuoteRequest]
/// with some or all fields replaced by the given arguments.
@_i1.useResult
CreateQuoteRequest copyWith({
String? text,
String? authorName,
double? lat,
double? lng,
List<String>? tags,
});
@override
Map<String, dynamic> toJson() {
return {
'text': text,
if (authorName != null) 'authorName': authorName,
'lat': lat,
'lng': lng,
if (tags != null) 'tags': tags?.toJson(),
};
}
@override
String toString() {
return _i1.SerializationManager.encode(this);
}
}
class _Undefined {}
class _CreateQuoteRequestImpl extends CreateQuoteRequest {
_CreateQuoteRequestImpl({
required String text,
String? authorName,
required double lat,
required double lng,
List<String>? tags,
}) : super._(
text: text,
authorName: authorName,
lat: lat,
lng: lng,
tags: tags,
);
/// Returns a shallow copy of this [CreateQuoteRequest]
/// with some or all fields replaced by the given arguments.
@_i1.useResult
@override
CreateQuoteRequest copyWith({
String? text,
Object? authorName = _Undefined,
double? lat,
double? lng,
Object? tags = _Undefined,
}) {
return CreateQuoteRequest(
text: text ?? this.text,
authorName: authorName is String? ? authorName : this.authorName,
lat: lat ?? this.lat,
lng: lng ?? this.lng,
tags: tags is List<String>? ? tags : this.tags?.map((e0) => e0).toList(),
);
}
}

View file

@ -0,0 +1,96 @@
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
/* To generate run: "serverpod generate" */
// ignore_for_file: implementation_imports
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: public_member_api_docs
// ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_client/serverpod_client.dart' as _i1;
abstract class Health implements _i1.SerializableModel {
Health._({
this.id,
required this.createdAt,
this.note,
});
factory Health({
int? id,
required DateTime createdAt,
String? note,
}) = _HealthImpl;
factory Health.fromJson(Map<String, dynamic> jsonSerialization) {
return Health(
id: jsonSerialization['id'] as int?,
createdAt:
_i1.DateTimeJsonExtension.fromJson(jsonSerialization['createdAt']),
note: jsonSerialization['note'] as String?,
);
}
/// The database id, set if the object has been inserted into the
/// database or if it has been fetched from the database. Otherwise,
/// the id will be null.
int? id;
DateTime createdAt;
String? note;
/// Returns a shallow copy of this [Health]
/// with some or all fields replaced by the given arguments.
@_i1.useResult
Health copyWith({
int? id,
DateTime? createdAt,
String? note,
});
@override
Map<String, dynamic> toJson() {
return {
if (id != null) 'id': id,
'createdAt': createdAt.toJson(),
if (note != null) 'note': note,
};
}
@override
String toString() {
return _i1.SerializationManager.encode(this);
}
}
class _Undefined {}
class _HealthImpl extends Health {
_HealthImpl({
int? id,
required DateTime createdAt,
String? note,
}) : super._(
id: id,
createdAt: createdAt,
note: note,
);
/// Returns a shallow copy of this [Health]
/// with some or all fields replaced by the given arguments.
@_i1.useResult
@override
Health copyWith({
Object? id = _Undefined,
DateTime? createdAt,
Object? note = _Undefined,
}) {
return Health(
id: id is int? ? id : this.id,
createdAt: createdAt ?? this.createdAt,
note: note is String? ? note : this.note,
);
}
}

View file

@ -0,0 +1,137 @@
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
/* To generate run: "serverpod generate" */
// ignore_for_file: implementation_imports
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: public_member_api_docs
// ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_client/serverpod_client.dart' as _i1;
import 'create_quote.dart' as _i2;
import 'health.dart' as _i3;
import 'quote.dart' as _i4;
import 'vote.dart' as _i5;
import 'package:wien_talks_client/src/protocol/health.dart' as _i6;
import 'package:wien_talks_client/src/protocol/quote.dart' as _i7;
import 'package:wien_talks_client/src/protocol/vote.dart' as _i8;
import 'package:serverpod_auth_client/serverpod_auth_client.dart' as _i9;
export 'create_quote.dart';
export 'health.dart';
export 'quote.dart';
export 'vote.dart';
export 'client.dart';
class Protocol extends _i1.SerializationManager {
Protocol._();
factory Protocol() => _instance;
static final Protocol _instance = Protocol._();
@override
T deserialize<T>(
dynamic data, [
Type? t,
]) {
t ??= T;
if (t == _i2.CreateQuoteRequest) {
return _i2.CreateQuoteRequest.fromJson(data) as T;
}
if (t == _i3.Health) {
return _i3.Health.fromJson(data) as T;
}
if (t == _i4.Quote) {
return _i4.Quote.fromJson(data) as T;
}
if (t == _i5.Vote) {
return _i5.Vote.fromJson(data) as T;
}
if (t == _i1.getType<_i2.CreateQuoteRequest?>()) {
return (data != null ? _i2.CreateQuoteRequest.fromJson(data) : null) as T;
}
if (t == _i1.getType<_i3.Health?>()) {
return (data != null ? _i3.Health.fromJson(data) : null) as T;
}
if (t == _i1.getType<_i4.Quote?>()) {
return (data != null ? _i4.Quote.fromJson(data) : null) as T;
}
if (t == _i1.getType<_i5.Vote?>()) {
return (data != null ? _i5.Vote.fromJson(data) : null) as T;
}
if (t == _i1.getType<List<String>?>()) {
return (data != null
? (data as List).map((e) => deserialize<String>(e)).toList()
: null) as T;
}
if (t == _i1.getType<List<String>?>()) {
return (data != null
? (data as List).map((e) => deserialize<String>(e)).toList()
: null) as T;
}
if (t == List<_i6.Health>) {
return (data as List).map((e) => deserialize<_i6.Health>(e)).toList()
as T;
}
if (t == List<_i7.Quote>) {
return (data as List).map((e) => deserialize<_i7.Quote>(e)).toList() as T;
}
if (t == List<_i8.Vote>) {
return (data as List).map((e) => deserialize<_i8.Vote>(e)).toList() as T;
}
try {
return _i9.Protocol().deserialize<T>(data, t);
} on _i1.DeserializationTypeNotFoundException catch (_) {}
return super.deserialize<T>(data, t);
}
@override
String? getClassNameForObject(Object? data) {
String? className = super.getClassNameForObject(data);
if (className != null) return className;
if (data is _i2.CreateQuoteRequest) {
return 'CreateQuoteRequest';
}
if (data is _i3.Health) {
return 'Health';
}
if (data is _i4.Quote) {
return 'Quote';
}
if (data is _i5.Vote) {
return 'Vote';
}
className = _i9.Protocol().getClassNameForObject(data);
if (className != null) {
return 'serverpod_auth.$className';
}
return null;
}
@override
dynamic deserializeByClassName(Map<String, dynamic> data) {
var dataClassName = data['className'];
if (dataClassName is! String) {
return super.deserializeByClassName(data);
}
if (dataClassName == 'CreateQuoteRequest') {
return deserialize<_i2.CreateQuoteRequest>(data['data']);
}
if (dataClassName == 'Health') {
return deserialize<_i3.Health>(data['data']);
}
if (dataClassName == 'Quote') {
return deserialize<_i4.Quote>(data['data']);
}
if (dataClassName == 'Vote') {
return deserialize<_i5.Vote>(data['data']);
}
if (dataClassName.startsWith('serverpod_auth.')) {
data['className'] = dataClassName.substring(15);
return _i9.Protocol().deserializeByClassName(data);
}
return super.deserializeByClassName(data);
}
}

View file

@ -0,0 +1,186 @@
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
/* To generate run: "serverpod generate" */
// ignore_for_file: implementation_imports
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: public_member_api_docs
// ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_client/serverpod_client.dart' as _i1;
abstract class Quote implements _i1.SerializableModel {
Quote._({
this.id,
required this.userId,
required this.text,
this.authorName,
required this.lat,
required this.long,
required this.createdAt,
required this.visibility,
required this.upvotes,
required this.downvotes,
this.tags,
});
factory Quote({
int? id,
required int userId,
required String text,
String? authorName,
required double lat,
required double long,
required DateTime createdAt,
required int visibility,
required int upvotes,
required int downvotes,
List<String>? tags,
}) = _QuoteImpl;
factory Quote.fromJson(Map<String, dynamic> jsonSerialization) {
return Quote(
id: jsonSerialization['id'] as int?,
userId: jsonSerialization['userId'] as int,
text: jsonSerialization['text'] as String,
authorName: jsonSerialization['authorName'] as String?,
lat: (jsonSerialization['lat'] as num).toDouble(),
long: (jsonSerialization['long'] as num).toDouble(),
createdAt:
_i1.DateTimeJsonExtension.fromJson(jsonSerialization['createdAt']),
visibility: jsonSerialization['visibility'] as int,
upvotes: jsonSerialization['upvotes'] as int,
downvotes: jsonSerialization['downvotes'] as int,
tags: (jsonSerialization['tags'] as List?)
?.map((e) => e as String)
.toList(),
);
}
/// The database id, set if the object has been inserted into the
/// database or if it has been fetched from the database. Otherwise,
/// the id will be null.
int? id;
int userId;
String text;
String? authorName;
double lat;
double long;
DateTime createdAt;
int visibility;
int upvotes;
int downvotes;
List<String>? tags;
/// Returns a shallow copy of this [Quote]
/// with some or all fields replaced by the given arguments.
@_i1.useResult
Quote copyWith({
int? id,
int? userId,
String? text,
String? authorName,
double? lat,
double? long,
DateTime? createdAt,
int? visibility,
int? upvotes,
int? downvotes,
List<String>? tags,
});
@override
Map<String, dynamic> toJson() {
return {
if (id != null) 'id': id,
'userId': userId,
'text': text,
if (authorName != null) 'authorName': authorName,
'lat': lat,
'long': long,
'createdAt': createdAt.toJson(),
'visibility': visibility,
'upvotes': upvotes,
'downvotes': downvotes,
if (tags != null) 'tags': tags?.toJson(),
};
}
@override
String toString() {
return _i1.SerializationManager.encode(this);
}
}
class _Undefined {}
class _QuoteImpl extends Quote {
_QuoteImpl({
int? id,
required int userId,
required String text,
String? authorName,
required double lat,
required double long,
required DateTime createdAt,
required int visibility,
required int upvotes,
required int downvotes,
List<String>? tags,
}) : super._(
id: id,
userId: userId,
text: text,
authorName: authorName,
lat: lat,
long: long,
createdAt: createdAt,
visibility: visibility,
upvotes: upvotes,
downvotes: downvotes,
tags: tags,
);
/// Returns a shallow copy of this [Quote]
/// with some or all fields replaced by the given arguments.
@_i1.useResult
@override
Quote copyWith({
Object? id = _Undefined,
int? userId,
String? text,
Object? authorName = _Undefined,
double? lat,
double? long,
DateTime? createdAt,
int? visibility,
int? upvotes,
int? downvotes,
Object? tags = _Undefined,
}) {
return Quote(
id: id is int? ? id : this.id,
userId: userId ?? this.userId,
text: text ?? this.text,
authorName: authorName is String? ? authorName : this.authorName,
lat: lat ?? this.lat,
long: long ?? this.long,
createdAt: createdAt ?? this.createdAt,
visibility: visibility ?? this.visibility,
upvotes: upvotes ?? this.upvotes,
downvotes: downvotes ?? this.downvotes,
tags: tags is List<String>? ? tags : this.tags?.map((e0) => e0).toList(),
);
}
}

View file

@ -0,0 +1,118 @@
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
/* To generate run: "serverpod generate" */
// ignore_for_file: implementation_imports
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: public_member_api_docs
// ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_client/serverpod_client.dart' as _i1;
abstract class Vote implements _i1.SerializableModel {
Vote._({
this.id,
required this.userId,
required this.createdAt,
required this.quoteId,
required this.upvote,
});
factory Vote({
int? id,
required int userId,
required DateTime createdAt,
required int quoteId,
required bool upvote,
}) = _VoteImpl;
factory Vote.fromJson(Map<String, dynamic> jsonSerialization) {
return Vote(
id: jsonSerialization['id'] as int?,
userId: jsonSerialization['userId'] as int,
createdAt:
_i1.DateTimeJsonExtension.fromJson(jsonSerialization['createdAt']),
quoteId: jsonSerialization['quoteId'] as int,
upvote: jsonSerialization['upvote'] as bool,
);
}
/// The database id, set if the object has been inserted into the
/// database or if it has been fetched from the database. Otherwise,
/// the id will be null.
int? id;
int userId;
DateTime createdAt;
int quoteId;
bool upvote;
/// Returns a shallow copy of this [Vote]
/// with some or all fields replaced by the given arguments.
@_i1.useResult
Vote copyWith({
int? id,
int? userId,
DateTime? createdAt,
int? quoteId,
bool? upvote,
});
@override
Map<String, dynamic> toJson() {
return {
if (id != null) 'id': id,
'userId': userId,
'createdAt': createdAt.toJson(),
'quoteId': quoteId,
'upvote': upvote,
};
}
@override
String toString() {
return _i1.SerializationManager.encode(this);
}
}
class _Undefined {}
class _VoteImpl extends Vote {
_VoteImpl({
int? id,
required int userId,
required DateTime createdAt,
required int quoteId,
required bool upvote,
}) : super._(
id: id,
userId: userId,
createdAt: createdAt,
quoteId: quoteId,
upvote: upvote,
);
/// Returns a shallow copy of this [Vote]
/// with some or all fields replaced by the given arguments.
@_i1.useResult
@override
Vote copyWith({
Object? id = _Undefined,
int? userId,
DateTime? createdAt,
int? quoteId,
bool? upvote,
}) {
return Vote(
id: id is int? ? id : this.id,
userId: userId ?? this.userId,
createdAt: createdAt ?? this.createdAt,
quoteId: quoteId ?? this.quoteId,
upvote: upvote ?? this.upvote,
);
}
}

View file

@ -0,0 +1,2 @@
export 'src/protocol/protocol.dart';
export 'package:serverpod_client/serverpod_client.dart';

View file

@ -0,0 +1,10 @@
name: wien_talks_client
description: Starting point for a Serverpod client.
environment:
sdk: '>=3.5.0 <4.0.0'
dependencies:
serverpod_client: 2.9.1
serverpod_auth_server: ^2.9.1

View file

@ -5,12 +5,9 @@
*.swp *.swp
.DS_Store .DS_Store
.atom/ .atom/
.build/
.buildlog/ .buildlog/
.history .history
.svn/ .svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related # IntelliJ related
*.iml *.iml
@ -29,11 +26,15 @@ migrate_working_dir/
.dart_tool/ .dart_tool/
.flutter-plugins .flutter-plugins
.flutter-plugins-dependencies .flutter-plugins-dependencies
.packages
.pub-cache/ .pub-cache/
.pub/ .pub/
/build/ /build/
# Symbolication related # Web related
lib/generated_plugin_registrant.dart
# Symbolization related
app.*.symbols app.*.symbols
# Obfuscation related # Obfuscation related
@ -43,3 +44,6 @@ app.*.map.json
/android/app/debug /android/app/debug
/android/app/profile /android/app/profile
/android/app/release /android/app/release
.env

View file

@ -0,0 +1,27 @@
# wien_talks_flutter
A new Flutter project with Serverpod.
## Getting Started
This project is a starting point for a Flutter application that is using
Serverpod.
A great starting point for learning Serverpod is our documentation site at:
[https://docs.serverpod.dev](https://docs.serverpod.dev).
To run the project, first make sure that the server is running, then do:
flutter run
## Flutter start:
add environment variable in the Additional arguments field in Android Studio:
--dart-define=SERVER_URL=http://localhost:5432/
Note: Host MUST end with a slash
## docker start:
wien_talks_server>docker compose -f docker-compose.local.yaml up -d

View file

@ -13,7 +13,8 @@ linter:
# The lint rules applied to this project can be customized in the # The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml` # section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints # included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints. # and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
# #
# Instead of disabling a lint rule for the entire project in the # Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code # section below, it can also be suppressed for a single line of code
@ -23,6 +24,5 @@ linter:
rules: rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule # avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at # Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options # https://dart.dev/guides/language/analysis-options

View file

@ -6,7 +6,7 @@ plugins {
} }
android { android {
namespace = "com.example.wien_talks" namespace = "com.wien_talks"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion ndkVersion = flutter.ndkVersion
@ -21,7 +21,7 @@ android {
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.wien_talks" applicationId = "com.wien_talks"
// You can update the following values to match your application needs. // You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config. // For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion minSdk = flutter.minSdkVersion

View file

@ -1,6 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application <application
android:label="wien_talks" android:label="wien_talks_flutter"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity
@ -42,4 +42,7 @@
<data android:mimeType="text/plain"/> <data android:mimeType="text/plain"/>
</intent> </intent>
</queries> </queries>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
</manifest> </manifest>

View file

@ -1,4 +1,4 @@
package com.example.wien_talks package com.wien_talks
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,3 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:

View file

@ -368,7 +368,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.example.wienTalks; PRODUCT_BUNDLE_IDENTIFIER = com.example.wienTalksFlutter;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@ -384,7 +384,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.wienTalks.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.example.wienTalksFlutter.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -401,7 +401,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.wienTalks.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.example.wienTalksFlutter.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@ -416,7 +416,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.wienTalks.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.example.wienTalksFlutter.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@ -547,7 +547,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.example.wienTalks; PRODUCT_BUNDLE_IDENTIFIER = com.example.wienTalksFlutter;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -569,7 +569,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.example.wienTalks; PRODUCT_BUNDLE_IDENTIFIER = com.example.wienTalksFlutter;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;

View file

@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>Wien Talks</string> <string>Wien Talks Flutter</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@ -13,7 +13,7 @@
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>wien_talks</string> <string>wien_talks_flutter</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>

Some files were not shown because too many files have changed in this diff Show more