add fastlane data and github action
1
.github/FUNDING.yml
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
github: otsmr
|
||||||
58
.github/workflows/release_github.yml
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
name: Github Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*.*.*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Clone repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Flutter
|
||||||
|
uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
- run: flutter pub get
|
||||||
|
- run: flutter analyze
|
||||||
|
- run: flutter test
|
||||||
|
|
||||||
|
- name: Create key.properties file
|
||||||
|
run: |
|
||||||
|
echo "storePassword=${{ secrets.STORE_PASSWORD }}" >> ./android/key.properties
|
||||||
|
echo "keyPassword=${{ secrets.ALIAS_PASSWORD }}" >> ./android/key.properties
|
||||||
|
echo "keyAlias=androidreleasekey" >> key.properties
|
||||||
|
echo "storeFile=./android/keystore.jks" >> ./android/key.properties
|
||||||
|
run: base64 -d <<< $KEYSTORE_FILE > ./android/keystore.jks
|
||||||
|
|
||||||
|
- name: Build Android APK
|
||||||
|
- run: flutter build apk --release --split-per-abi
|
||||||
|
|
||||||
|
- name: Create Github Release
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-apk
|
||||||
|
path: build/app/outputs/flutter-apk/*.apk
|
||||||
|
|
||||||
|
- name: Generate Checksums
|
||||||
|
run: |
|
||||||
|
tree .
|
||||||
|
find app -type f -exec md5sum {} \; >> RELEASE.md5sum
|
||||||
|
find app -type f -exec sha256sum {} \; >> RELEASE.sha256sum
|
||||||
|
sed -i 's|app/.*/\([^/]*\)$|\1|' RELEASE.sha256sum RELEASE.md5sum
|
||||||
|
sed -i 's|app/||' RELEASE.sha256sum RELEASE.md5sum
|
||||||
|
|
||||||
|
- name: Upload Release Binaries (stable)
|
||||||
|
if: ${{ !inputs.dry_run && inputs.channel == 'stable' }}
|
||||||
|
uses: ncipollo/release-action@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
tag: v${{ env.PUBSPEC_VERSION }} # mind the "v" prefix
|
||||||
|
omitBodyDuringUpdate: true
|
||||||
|
omitNameDuringUpdate: true
|
||||||
|
omitPrereleaseDuringUpdate: true
|
||||||
|
allowUpdates: true
|
||||||
|
artifacts: app_*/**/*,RELEASE.sha256sum,RELEASE.md5sum
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
|
||||||
import 'package:cryptography_plus/cryptography_plus.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
|
@ -16,7 +12,6 @@ import 'package:twonly/src/views/components/app_outdated.dart';
|
||||||
import 'package:twonly/src/views/home.view.dart';
|
import 'package:twonly/src/views/home.view.dart';
|
||||||
import 'package:twonly/src/views/onboarding/onboarding.view.dart';
|
import 'package:twonly/src/views/onboarding/onboarding.view.dart';
|
||||||
import 'package:twonly/src/views/onboarding/register.view.dart';
|
import 'package:twonly/src/views/onboarding/register.view.dart';
|
||||||
import 'package:twonly/src/views/settings/help/changelog.view.dart';
|
|
||||||
|
|
||||||
class App extends StatefulWidget {
|
class App extends StatefulWidget {
|
||||||
const App({super.key});
|
const App({super.key});
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ class ConnectSignedPreKeyStore extends SignedPreKeyStore {
|
||||||
}
|
}
|
||||||
final storeHashMap = json.decode(storeSerialized) as List<dynamic>;
|
final storeHashMap = json.decode(storeSerialized) as List<dynamic>;
|
||||||
for (final item in storeHashMap) {
|
for (final item in storeHashMap) {
|
||||||
|
// ignore: avoid_dynamic_calls
|
||||||
store[item[0] as int] = base64Decode(item[1] as String);
|
store[item[0] as int] = base64Decode(item[1] as String);
|
||||||
}
|
}
|
||||||
return store;
|
return store;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ class ChatDateChip extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var formattedDate = item.isTime
|
final formattedDate = item.isTime
|
||||||
? DateFormat.Hm(Localizations.localeOf(context).toLanguageTag())
|
? DateFormat.Hm(Localizations.localeOf(context).toLanguageTag())
|
||||||
.format(item.time!)
|
.format(item.time!)
|
||||||
: '${DateFormat.Hm(Localizations.localeOf(context).toLanguageTag()).format(item.date!)} ${DateFormat.yMd(Localizations.localeOf(context).toLanguageTag()).format(item.date!)}';
|
: '${DateFormat.Hm(Localizations.localeOf(context).toLanguageTag()).format(item.date!)} ${DateFormat.yMd(Localizations.localeOf(context).toLanguageTag()).format(item.date!)}';
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ class _MemoriesPhotoSliderViewState extends State<MemoriesPhotoSliderView> {
|
||||||
alignment: Alignment.bottomRight,
|
alignment: Alignment.bottomRight,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
MediaViewSizing(
|
MediaViewSizing(
|
||||||
bottomNavigation: Container(
|
bottomNavigation: ColoredBox(
|
||||||
color: context.color.surface,
|
color: context.color.surface,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
|
|
||||||
List<Widget> parseMarkdown(BuildContext context, String markdown) {
|
List<Widget> parseMarkdown(BuildContext context, String markdown) {
|
||||||
List<Widget> widgets = [];
|
final widgets = <Widget>[];
|
||||||
// Split the string into lines
|
// Split the string into lines
|
||||||
final lines = markdown.split('\n');
|
final lines = markdown.split('\n');
|
||||||
|
|
||||||
|
|
@ -37,7 +37,7 @@ List<Widget> parseMarkdown(BuildContext context, String markdown) {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 7),
|
padding: const EdgeInsets.only(top: 7),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.brightness_1,
|
Icons.brightness_1,
|
||||||
size: 7,
|
size: 7,
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ class HelpView extends StatelessWidget {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text("Open Source"),
|
title: const Text('Open Source'),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
launchUrl(Uri.parse('https://github.com/twonlyapp/twonly-app'));
|
launchUrl(Uri.parse('https://github.com/twonlyapp/twonly-app'));
|
||||||
},
|
},
|
||||||
|
|
@ -127,17 +127,17 @@ class HelpView extends StatelessWidget {
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
onLongPress: () async {
|
onLongPress: () async {
|
||||||
bool? okay = await showAlertDialog(
|
final okay = await showAlertDialog(
|
||||||
context,
|
context,
|
||||||
"Delete Retransmission messages",
|
'Delete Retransmission messages',
|
||||||
"Only do this if you know what you are doing :)",
|
'Only do this if you know what you are doing :)',
|
||||||
);
|
);
|
||||||
if (okay == true) {
|
if (okay == true) {
|
||||||
await twonlyDB.messageRetransmissionDao
|
await twonlyDB.messageRetransmissionDao
|
||||||
.clearRetransmissionTable();
|
.clearRetransmissionTable();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
title: Text(
|
title: const Text(
|
||||||
'Copyright twonly',
|
'Copyright twonly',
|
||||||
style: TextStyle(color: Colors.grey, fontSize: 13),
|
style: TextStyle(color: Colors.grey, fontSize: 13),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
13
metadata/de-DE/full_description.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
twonly, eine datenschutzfreundliche Möglichkeit sich mit Freunden durch sichere, spontane Bildübertragung zu verbinden.
|
||||||
|
|
||||||
|
=> Unbeschwertes Teilen <=
|
||||||
|
Mit Ende-zu-Ende-Verschlüsselung genieße die Gewissheit, dass nur du und deine Freunde die Momente sehen können, die du teilst.
|
||||||
|
|
||||||
|
=> Konzentriere dich auf das Teilen von Momenten <=
|
||||||
|
Verabschiede dich von süchtig machenden Funktionen! twonly wurde für das Teilen von Momenten geschaffen, frei von nutzlosen Ablenkungen oder Werbung.
|
||||||
|
|
||||||
|
=> In Europa ansässig <=
|
||||||
|
twonly wird ausschließlich in Europa entwickelt und gehostet. Erstellt von einem Studenten, nicht von einem großen Tech-Unternehmen, das deine persönlichen Daten zum Profit verkauft.
|
||||||
|
|
||||||
|
=> Du bist nicht das Produkt! <=
|
||||||
|
twonly wird klar und transparent durch eine monatliche Gebühr finanziert und nicht durch den Verkauf deiner Daten.
|
||||||
BIN
metadata/de-DE/images/featureGraphic.png
Normal file
|
After Width: | Height: | Size: 198 KiB |
BIN
metadata/de-DE/images/logo.png
Normal file
|
After Width: | Height: | Size: 7 KiB |
BIN
metadata/de-DE/images/phoneScreenshots/1.png
Normal file
|
After Width: | Height: | Size: 322 KiB |
BIN
metadata/de-DE/images/phoneScreenshots/2.png
Normal file
|
After Width: | Height: | Size: 2.7 MiB |
1
metadata/de-DE/short_description.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Privat in Kontakt bleiben.
|
||||||
1
metadata/de-DE/title.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
twonly
|
||||||
13
metadata/en-US/full_description.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
twonly, a privacy-friendly way to connect with friends through secure, spontaneous image sharing.
|
||||||
|
|
||||||
|
=> Carefree sharing <=
|
||||||
|
With end-to-end encryption, enjoy the peace of mind that only you and your friends can see the moments you share.
|
||||||
|
|
||||||
|
=> Focus on sharing moments <=
|
||||||
|
Say goodbye to addictive features! twonly was created for sharing moments, free from useless distractions or ads.
|
||||||
|
|
||||||
|
=> Based in Europe <=
|
||||||
|
twonly is developed and hosted exclusively in Europe. Created by a student, not a big tech company selling your personal data for profit.
|
||||||
|
|
||||||
|
=> You are not the product! <=
|
||||||
|
twonly is clearly and transparently funded by a monthly fee and not by selling your data.
|
||||||
BIN
metadata/en-US/images/featureGraphic.png
Normal file
|
After Width: | Height: | Size: 198 KiB |
BIN
metadata/en-US/images/logo.png
Normal file
|
After Width: | Height: | Size: 7 KiB |
BIN
metadata/en-US/images/phoneScreenshots/1.png
Normal file
|
After Width: | Height: | Size: 318 KiB |
BIN
metadata/en-US/images/phoneScreenshots/2.png
Normal file
|
After Width: | Height: | Size: 2.7 MiB |
1
metadata/en-US/short_description.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Stay in touch privately.
|
||||||
1
metadata/en-US/title.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
twonly
|
||||||