improve onboarding

This commit is contained in:
otsmr 2025-02-07 17:48:02 +01:00
parent 384bafe67b
commit aa000afaf4
25 changed files with 133 additions and 33 deletions

View file

@ -2,6 +2,39 @@
Don't be lonely, get twonly! Send pictures to a friend in real time and be sure you are the only two people who can see them.
## TODOS bevor first beta
- Flammen Problem fixen
- Add no_screenshot plugin: https://pub.dev/packages/no_screenshot
- Bei mehreren neu Empfangen Nachrichten fixen
- Settings
- Delete and Block active users
- Onboarding Slide, Text und Animationen
- MessageKind -> Ausbauen?
- Nachrichten nach 24h Stunden löschen
- Real deployment aufsetzen direkt auf Netcup?
- Pro Invitation codes
## Later todos
- Videos
- Sealed Sender
- Settings
- Profilbilder erstellen.
- Pro Version
- Media Shower -> Recap of the day
- Send normal images via twonly
## Pro Version
- Send and receive unlimited pictures
- This includes a free pro version for your twonly partner!
- Get up to 3 tokens
- Get for your twonly partner a second a additional pro version
## Features
This app was started because of the three main features I missed out by popular alternatives.

View file

@ -0,0 +1 @@
{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.0.2","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":77,"w":500,"h":500,"nm":"security tick","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"tick","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.094,0.094,0.094],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.067,0.067,-0.067]},"t":32,"s":[62,62,100]},{"t":56,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.947,0],[-17.649,35.298],[52.947,-35.298]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":25.537,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.178],"y":[1]},"o":{"x":[0.21],"y":[0]},"t":32,"s":[0]},{"t":62,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"shield","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":4,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.97],"y":[1]},"o":{"x":[0.03],"y":[0]},"t":0,"s":[250]},{"i":{"x":[0.97],"y":[1]},"o":{"x":[0.03],"y":[0]},"t":20,"s":[250]},{"t":40,"s":[250]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.174],"y":[0.822]},"t":0,"s":[319]},{"i":{"x":[0.334],"y":[1]},"o":{"x":[0.308],"y":[0]},"t":20,"s":[197]},{"t":40,"s":[250]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.174,0.174,0.174],"y":[0.822,0.822,-0.822]},"t":0,"s":[46,46,100]},{"t":20,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.094,"y":1},"o":{"x":0.252,"y":0},"t":25,"s":[{"i":[[-29.271,0],[0,-29.271],[29.271,0],[0,29.271]],"o":[[29.271,0],[0,29.271],[-29.271,0],[0,-29.271]],"v":[[0,-53],[53,0],[0,53],[-53,0]],"c":true}]},{"t":56,"s":[{"i":[[-2.504,1.787],[-85.122,-7.093],[120.419,-40.532],[0,158.319]],"o":[[2.504,1.787],[0,158.319],[-120.419,-40.532],[85.122,-7.093]],"v":[[0,-169.229],[141.87,-126.668],[0,169.229],[-141.87,-126.668]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.360784322023,0.800000011921,0.474509805441,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}],"markers":[]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 581 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 514 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

View file

@ -35,7 +35,7 @@ class MyApp extends StatefulWidget {
class _MyAppState extends State<MyApp> {
Future<bool> _isUserCreated = isUserCreated();
bool _showOnboarding = false;
bool _showOnboarding = true;
bool _isConnected = false;
int redColorOpacity = 0; // Start with dark red
bool redColorGoUp = true;

View file

@ -346,6 +346,11 @@ class DbMessages extends CvModelBase {
dynamic messageOpenedAt = fromDb[i][columnMessageOpenedAt];
if (messageOpenedAt != null) {
messageOpenedAt = DateTime.tryParse(fromDb[i][columnMessageOpenedAt]);
// if (messageOpenedAt != null) {
// if (messageOpenedAt.difference()) {
// }
// }
}
int? messageOtherId = fromDb[i][columnMessageOtherId];
MessageContent content = MessageContent.fromJson(

View file

@ -151,7 +151,8 @@ class _MediaViewerViewState extends State<MediaViewerView> {
children: [
Expanded(
child: Lottie.asset(
'assets/animations/present.lottie.json'),
'assets/animations/present.lottie.json',
),
),
Container(
padding: EdgeInsets.only(bottom: 200),

View file

@ -1,5 +1,22 @@
import 'package:introduction_screen/introduction_screen.dart';
import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';
// Slide 1: Welcome to [App Name]
// Text: "Experience a new way to connect with friends through secure, spontaneous image sharing."
// Image Idea: A vibrant, welcoming graphic featuring diverse groups of friends using the app in various settings (e.g., at a café, at a party, etc.).
// Slide 2: End-to-End Encryption
// Text: "Your privacy matters. Enjoy peace of mind with end-to-end encryption, ensuring only you and your friends can see your images."
// Image Idea: A lock symbol overlaying a smartphone screen displaying an encrypted message, symbolizing security and privacy.
// Slide 3: Local Processing
// Text: "Everything is done locally. Our servers only see encrypted bytes, keeping your data safe from prying eyes."
// Image Idea: A visual representation of local processing, such as a smartphone with a shield icon, indicating that data remains on the device.
// Slide 4: Focus on Images
// Text: "Say goodbye to clutter! Our app is designed for sharing images, not useless distractions."
// Image Idea: A clean, minimalist interface showcasing a user effortlessly sending an image, with a focus on the image itself.
class OnboardingView extends StatelessWidget {
const OnboardingView({super.key, required this.callbackOnSuccess});
@ -14,60 +31,93 @@ class OnboardingView extends StatelessWidget {
PageViewModel(
title: "Welcome to twonly!",
body:
"With twonly you can share pictures with friends that only you and the receiver can see!",
"Experience a new way to connect with friends through secure, spontaneous image sharing.",
image: Center(
child: Padding(
padding: const EdgeInsets.only(top: 100),
child: Image.asset("assets/images/onboarding/01.png"),
// child: Image.asset('assets/animations/messages.gif'),
child: Lottie.asset(
'assets/animations/messages.json',
),
),
),
),
PageViewModel(
title: "No ads, no tracking",
title: "End-to-End Encryption",
body:
"twonly is complete add free and does not collect any personal data. The server does not save any data of you.",
"Your privacy matters. Enjoy peace of mind with end-to-end encryption, ensuring only you and your friends can see your images.",
image: Center(
child: Padding(
padding: const EdgeInsets.only(top: 100),
child: Image.asset("assets/images/onboarding/02.png"),
child: Lottie.asset(
'assets/animations/e2e.json',
repeat: false,
),
),
),
),
PageViewModel(
title: "End-to-End protection",
title: "Focus on sharing moments",
body:
"twonly encrypts every message you send. For this it uses the Signal protocol which is currently the best way to encrypt messages with a minimum of metadata.",
"Say goodbye to addictive features! Our app is designed for sharing moments, no useless distractions or ads.",
image: Center(
child: Padding(
padding: const EdgeInsets.only(top: 100),
child: Image.asset("assets/images/onboarding/03.png"),
child: Lottie.asset(
'assets/animations/selfie2.json',
),
),
),
),
PageViewModel(
title: "Send twonlies",
body:
"Share moments securely with just one other person. twonly ensures that only you and your chosen friend can view the picture, keeping your moments private.",
image: Center(
child: Padding(
padding: const EdgeInsets.only(top: 100),
child: Lottie.asset(
'assets/animations/twonlies.json',
repeat: false,
),
),
),
),
// PageViewModel(
// title: "Hard work",
// body:
// "We try everything to give you the best experience but developing and maintaining is hard work and requires thousand of hours.",
// image: Center(
// child: Padding(
// padding: const EdgeInsets.only(top: 100),
// child: Image.asset("assets/images/onboarding/04.png"),
// ),
// ),
// ),
PageViewModel(
title: "You are not the product!",
body:
"Nothing is free. Either you pay with your personal informations or with money. Twonly gives you the chance to use an social media product without exploiting you by collection you personal data.",
"If you don't pay, your data is the product that is sold. So we decided to develop a sustainable business model where everyone wins. You can keep your data private and we can create a beautiful app.",
image: Center(
child: Padding(
padding: const EdgeInsets.only(top: 100),
child: Image.asset("assets/images/onboarding/05.png"),
child: Lottie.asset(
'assets/animations/product.json',
),
),
),
),
PageViewModel(
title: "Try for free!",
title: "Pricing",
bodyWidget: Column(
children: [
Text(
"To be able to create a sustainable privacy focused app which does not show ads, we have to rely on you! You can get twonly for only 0,99€ / monthly or 9,99€ / yearly. As twonly is for at least two, you get a second user for free, so your twonly partner does not have to pay!",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18),
),
],
),
image: Center(
child: Padding(
padding: const EdgeInsets.only(top: 100),
child: Lottie.asset(
'assets/animations/selfie.json',
),
),
),
),
PageViewModel(
title: "Let's get started!",
bodyWidget: Column(
children: [
Text(
@ -90,7 +140,9 @@ class OnboardingView extends StatelessWidget {
image: Center(
child: Padding(
padding: const EdgeInsets.only(top: 100),
child: Image.asset("assets/images/onboarding/06.png"),
child: Lottie.asset(
'assets/animations/rocket.json',
),
),
),
),

View file

@ -75,11 +75,11 @@ flutter:
# Add assets from the images directory to the application.
- assets/images/
- assets/animations/present.lottie.json
- assets/icons/
- assets/icons/flame.png
- assets/images/onboarding/01.png
- assets/images/onboarding/02.png
- assets/images/onboarding/03.png
- assets/images/onboarding/04.png
- assets/images/onboarding/05.png
- assets/images/onboarding/06.png
- assets/animations/selfie2.json
- assets/animations/messages.json
- assets/animations/local.json
- assets/animations/test.json
- assets/animations/product.json
- assets/animations/twonlies.json
- assets/animations/rocket.json
- assets/animations/e2e.json