Merge pull request #2 from timokz/refactor/flatten-layout
Refactor/flatten layout
46
README.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Wien Talks
|
||||
|
||||
**An app developed during the [2nd Flutter Vienna Hackathon](https://www.meetup.com/fluttervienna/events/310014357/).**
|
||||
|
||||
## Team
|
||||
|
||||
_Grätzel-Goblins_ — Timo, Max & Mike
|
||||
|
||||
## Description
|
||||
|
||||
_Wien Talks_ is an app to share the iconic and quotable lines you hear Viennese
|
||||
people drop throughout their day. It doesn't matter if it's a U6 train
|
||||
conductor's insults that he made during an announcement or the Spar cashier's
|
||||
funny retort to "Zweite Kassa bitte!", _Wien Talks_ is made to record, preserve
|
||||
and share Viennese quotes with others.
|
||||
|
||||
Quotes are community-moderated—users can up- or down-vote posts. Additionally,
|
||||
when creating a new quote, the location from which the user made it is added,
|
||||
too. This allows you to see what's going on near you.
|
||||
|
||||
## Screenshots
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<img src="unicorn/Screenshot_1755421875.png" width="300" alt="Default quotes list"/>
|
||||
<div><sub>Default quotes view</sub></div>
|
||||
</td>
|
||||
<td align="center">
|
||||
<img src="unicorn/Screenshot_1755421892.png" width="300" alt="Filtered quotes list"/>
|
||||
<div><sub>Filtered quotes</sub></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<img src="unicorn/Screenshot_1755421897.png" width="300" alt="Reuse location from quote"/>
|
||||
<div><sub>Tap a card → create with same location</sub></div>
|
||||
</td>
|
||||
<td align="center">
|
||||
<img src="unicorn/Screenshot_1755421907.png" width="300" alt="Custom location picker"/>
|
||||
<div><sub>Set a custom location</sub></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
---
|
||||
BIN
unicorn/Screenshot_1755421875.png
Normal file
|
After Width: | Height: | Size: 1,011 KiB |
BIN
unicorn/Screenshot_1755421892.png
Normal file
|
After Width: | Height: | Size: 930 KiB |
BIN
unicorn/Screenshot_1755421897.png
Normal file
|
After Width: | Height: | Size: 570 KiB |
BIN
unicorn/Screenshot_1755421907.png
Normal file
|
After Width: | Height: | Size: 566 KiB |
75
wien_talks/.github/workflows/deployment-aws.yml
vendored
|
|
@ -1,75 +0,0 @@
|
|||
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"
|
||||
99
wien_talks/.github/workflows/deployment-gcp.yml
vendored
|
|
@ -1,99 +0,0 @@
|
|||
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 }}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
id("dev.flutter.flutter-gradle-plugin")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.wien_talks"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_11.toString()
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "com.wien_talks"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = flutter.minSdkVersion
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
import 'package:go_router/go_router.dart';
|
||||
import 'package:wien_talks_flutter/screens/create_event_screen.dart';
|
||||
import 'package:wien_talks_flutter/screens/login_page.dart';
|
||||
import 'package:wien_talks_flutter/screens/news_screen.dart';
|
||||
|
||||
final router = GoRouter(
|
||||
routes: [
|
||||
GoRoute(path: '/login', builder: (c, s) => const LoginScreen()),
|
||||
GoRoute(path: '/', builder: (c, s) => NewsScreen()),
|
||||
GoRoute(
|
||||
path: '/create_event',
|
||||
name: 'create_event',
|
||||
builder: (c, s) => CreateEventScreen()),
|
||||
],
|
||||
);
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:location/location.dart';
|
||||
import 'package:wien_talks_client/wien_talks_client.dart';
|
||||
import 'package:wien_talks_flutter/widgets/get_location_widget.dart';
|
||||
import 'package:wien_talks_flutter/helper/funmap_mgr.dart';
|
||||
import 'package:wien_talks_flutter/mapfile_widget.dart';
|
||||
import 'package:wien_talks_flutter/widgets/news_input_form.dart';
|
||||
import 'package:wien_talks_flutter/widgets/screen_widget.dart';
|
||||
|
||||
import '../helper/location_mgr.dart';
|
||||
|
||||
class CreateEventScreen extends StatelessWidget {
|
||||
const CreateEventScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ScreenWidget(
|
||||
child: Column(
|
||||
children: [
|
||||
NewsInputForm(
|
||||
onSubmit: (CreateQuoteRequest request) async {
|
||||
await FunmapMgr().client.quote.createQuote(request);
|
||||
},
|
||||
),
|
||||
StreamBuilder(
|
||||
stream: LocationMgr().stream,
|
||||
builder:
|
||||
(BuildContext context, AsyncSnapshot<LocationData> snapshot) =>
|
||||
snapshot.data != null
|
||||
? Text(snapshot.data.toString())
|
||||
: SizedBox()),
|
||||
Expanded(
|
||||
child: GetLocationWidget(
|
||||
child: MapfileWidget(),
|
||||
),
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:wien_talks_flutter/helper/auth_service.dart';
|
||||
|
||||
class LoginScreen extends StatelessWidget {
|
||||
const LoginScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [Color(0xff2193b0), Color(0xff6dd5ed)],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text('Wien Talks',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 42,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white)),
|
||||
const SizedBox(height: 60),
|
||||
FilledButton.icon(
|
||||
onPressed: () async => await AuthService.signIn(),
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: Colors.white,
|
||||
foregroundColor: Colors.black87,
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(30)),
|
||||
elevation: 6,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.lock,
|
||||
),
|
||||
label: const Text('Sign in with Google'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import 'package:wien_talks_client/wien_talks_client.dart';
|
||||
import 'package:wien_talks_flutter/helper/funmap_mgr.dart';
|
||||
import 'package:wien_talks_flutter/helper/location_util.dart';
|
||||
import 'package:wien_talks_flutter/helper/time_util.dart';
|
||||
import 'package:wien_talks_flutter/widgets/flamboyant_quote_card.dart';
|
||||
|
||||
class LatestQuotesScreen extends StatefulWidget {
|
||||
const LatestQuotesScreen({super.key});
|
||||
|
||||
@override
|
||||
State<LatestQuotesScreen> createState() => _LatestQuotesScreenState();
|
||||
}
|
||||
|
||||
class _LatestQuotesScreenState extends State<LatestQuotesScreen> {
|
||||
final List<Quote> _quotes = [];
|
||||
StreamSubscription<Quote>? _sub;
|
||||
|
||||
Object? _error;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_connectStream();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_sub?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _connectStream() {
|
||||
_sub?.cancel();
|
||||
_sub = FunmapMgr().client.quote.streamAllQuotes(limit: 50).listen(
|
||||
(q) => setState(() => _upsert(q)),
|
||||
onError: (e) => setState(() => _error = e),
|
||||
onDone: () => Future.delayed(const Duration(seconds: 2), () {
|
||||
if (mounted) _connectStream();
|
||||
}),
|
||||
cancelOnError: false,
|
||||
);
|
||||
}
|
||||
|
||||
void _upsert(Quote q) {
|
||||
final i = _quotes.indexWhere((x) => x.id == q.id);
|
||||
if (i >= 0) {
|
||||
_quotes[i] = q;
|
||||
} else {
|
||||
_quotes.add(q);
|
||||
}
|
||||
_quotes.sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
||||
}
|
||||
|
||||
void _sortDesc() {
|
||||
_quotes.sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
||||
}
|
||||
|
||||
Future<void> _vote(Quote quote, bool up) async {
|
||||
final idx = _quotes.indexWhere((q) => q.id == quote.id);
|
||||
if (idx < 0) return;
|
||||
|
||||
final original = _quotes[idx];
|
||||
final updated = original.copyWith(
|
||||
upvotes: up ? original.upvotes + 1 : original.upvotes,
|
||||
downvotes: up ? original.downvotes : original.downvotes + 1,
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_quotes[idx] = updated;
|
||||
_sortDesc();
|
||||
});
|
||||
|
||||
try {
|
||||
await FunmapMgr().client.quote.updateQuote(updated);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
setState(() => _quotes[idx] = original);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Vote failed: $e')),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_quotes.isEmpty && _error == null) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
if (_error != null && _quotes.isEmpty) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Text('Error: $_error'),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (_quotes.isEmpty) {
|
||||
return const Center(child: Text('Nix da. Sag halt was'));
|
||||
}
|
||||
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return MasonryGridView.count(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 8,
|
||||
crossAxisSpacing: 8,
|
||||
padding: const EdgeInsets.fromLTRB(12, 8, 12, 12),
|
||||
itemCount: _quotes.length,
|
||||
itemBuilder: (context, i) {
|
||||
final q = _quotes[i];
|
||||
final author = (q.authorName ?? '').trim();
|
||||
final meta = [
|
||||
if (author.isNotEmpty) author,
|
||||
timeAgo(q.createdAt),
|
||||
].join(' · ');
|
||||
|
||||
return FlamboyantQuoteCard(
|
||||
quote: q,
|
||||
meta: meta,
|
||||
onVoteUp: () => _vote(q, true),
|
||||
onVoteDown: () => _vote(q, false),
|
||||
staticMapUrlBuilder: gStaticMap);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
import 'package:carousel_slider/carousel_slider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CarouselWidget extends StatelessWidget {
|
||||
const CarouselWidget({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return IgnorePointer(
|
||||
child: CarouselSlider(
|
||||
options: CarouselOptions(height: 300.0, autoPlay: true),
|
||||
items: ["houses.jpg", "kangaroos.jpg", "sightseeing.jpg", "tram.jpg", "fiaker.jpg", "falco.jpg", "wastebin.jpg"].map((i) {
|
||||
return Builder(
|
||||
builder: (BuildContext context) {
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
margin: EdgeInsets.symmetric(horizontal: 5.0),
|
||||
//decoration: BoxDecoration(color: Colors.amber),
|
||||
child: Image(image: AssetImage("assets/funny_images/$i")));
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
0
wien_talks/wien_talks_client/.idea/.gitignore → wien_talks_client/.idea/.gitignore
generated
vendored
|
|
@ -44,6 +44,7 @@ app.*.map.json
|
|||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
||||
android/key.properties
|
||||
|
||||
|
||||
.env
|
||||
72
wien_talks_flutter/android/app/build.gradle.kts
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import java.util.Properties
|
||||
import java.io.FileInputStream
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
id("dev.flutter.flutter-gradle-plugin")
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation("com.google.android.play:core:1.10.3")
|
||||
}
|
||||
|
||||
val keystoreProperties = Properties()
|
||||
val keystorePropertiesFile = rootProject.file("key.properties")
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
FileInputStream(keystorePropertiesFile).use { keystoreProperties.load(it) }
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.wien_talks"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
kotlinOptions { jvmTarget = "17" }
|
||||
|
||||
signingConfigs {
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
create("release") {
|
||||
keyAlias = keystoreProperties["keyAlias"] as String
|
||||
keyPassword = keystoreProperties["keyPassword"] as String
|
||||
val storePath = keystoreProperties["storeFile"] as String?
|
||||
storeFile = storePath?.let { file(it) }
|
||||
storePassword = keystoreProperties["storePassword"] as String
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.wien_talks"
|
||||
minSdk = flutter.minSdkVersion
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
signingConfig = signingConfigs.findByName("release")
|
||||
?: signingConfigs.getByName("debug")
|
||||
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
debug {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
8
wien_talks_flutter/android/app/proguard-rules.pro
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
-keep class io.flutter.embedding.** { *; }
|
||||
-keep class io.flutter.plugins.** { *; }
|
||||
-keep class io.flutter.** { *; }
|
||||
|
||||
-keep class com.google.android.gms.** { *; }
|
||||
-dontwarn com.google.android.gms.**
|
||||
|
||||
-dontwarn kotlinx.coroutines.**
|
||||
|
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 544 B |
|
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 442 B |
|
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 721 B |
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 295 B |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 406 B |
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 450 B |
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 282 B |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 462 B |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 704 B |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 406 B |
|
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 586 B |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 862 B |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 862 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 762 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |