mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-03-03 12:16:47 +00:00
switch to go_router
This commit is contained in:
parent
dbc3ee62d0
commit
61a5352bb8
42 changed files with 632 additions and 793 deletions
|
|
@ -5,7 +5,6 @@
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:enableOnBackInvokedCallback="true"
|
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:taskAffinity=""
|
android:taskAffinity=""
|
||||||
|
|
|
||||||
45
lib/app.dart
45
lib/app.dart
|
|
@ -7,8 +7,11 @@ import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/localization/generated/app_localizations.dart';
|
import 'package:twonly/src/localization/generated/app_localizations.dart';
|
||||||
import 'package:twonly/src/providers/connection.provider.dart';
|
import 'package:twonly/src/providers/connection.provider.dart';
|
||||||
import 'package:twonly/src/providers/purchases.provider.dart';
|
import 'package:twonly/src/providers/purchases.provider.dart';
|
||||||
|
import 'package:twonly/src/providers/routing.provider.dart';
|
||||||
import 'package:twonly/src/providers/settings.provider.dart';
|
import 'package:twonly/src/providers/settings.provider.dart';
|
||||||
import 'package:twonly/src/services/subscription.service.dart';
|
import 'package:twonly/src/services/subscription.service.dart';
|
||||||
|
import 'package:twonly/src/themes/dark.dart';
|
||||||
|
import 'package:twonly/src/themes/light.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
import 'package:twonly/src/utils/pow.dart';
|
import 'package:twonly/src/utils/pow.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
|
|
@ -16,7 +19,7 @@ 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/backup/twonly_safe_backup.view.dart';
|
import 'package:twonly/src/views/settings/backup/setup_backup.view.dart';
|
||||||
import 'package:twonly/src/views/updates/62_database_migration.view.dart';
|
import 'package:twonly/src/views/updates/62_database_migration.view.dart';
|
||||||
|
|
||||||
class App extends StatefulWidget {
|
class App extends StatefulWidget {
|
||||||
|
|
@ -93,50 +96,24 @@ class _AppState extends State<App> with WidgetsBindingObserver {
|
||||||
return ListenableBuilder(
|
return ListenableBuilder(
|
||||||
listenable: context.watch<SettingsChangeProvider>(),
|
listenable: context.watch<SettingsChangeProvider>(),
|
||||||
builder: (BuildContext context, Widget? child) {
|
builder: (BuildContext context, Widget? child) {
|
||||||
return MaterialApp(
|
return MaterialApp.router(
|
||||||
|
routerConfig: routerProvider,
|
||||||
scaffoldMessengerKey: globalRootScaffoldMessengerKey,
|
scaffoldMessengerKey: globalRootScaffoldMessengerKey,
|
||||||
restorationScopeId: 'app',
|
|
||||||
localizationsDelegates: const [
|
localizationsDelegates: const [
|
||||||
AppLocalizations.delegate,
|
AppLocalizations.delegate,
|
||||||
GlobalMaterialLocalizations.delegate,
|
GlobalMaterialLocalizations.delegate,
|
||||||
GlobalWidgetsLocalizations.delegate,
|
GlobalWidgetsLocalizations.delegate,
|
||||||
GlobalCupertinoLocalizations.delegate,
|
GlobalCupertinoLocalizations.delegate,
|
||||||
],
|
],
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
supportedLocales: const [
|
supportedLocales: const [
|
||||||
Locale('en', ''),
|
Locale('en', ''),
|
||||||
Locale('de', ''),
|
Locale('de', ''),
|
||||||
],
|
],
|
||||||
onGenerateTitle: (BuildContext context) => 'twonly',
|
title: 'twonly',
|
||||||
theme: ThemeData(
|
theme: lightTheme,
|
||||||
colorScheme: ColorScheme.fromSeed(
|
darkTheme: darkTheme,
|
||||||
seedColor: const Color(0xFF57CC99),
|
|
||||||
),
|
|
||||||
pageTransitionsTheme: const PageTransitionsTheme(
|
|
||||||
builders: {
|
|
||||||
TargetPlatform.android: PredictiveBackPageTransitionsBuilder(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
inputDecorationTheme: const InputDecorationTheme(
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
darkTheme: ThemeData.dark().copyWith(
|
|
||||||
colorScheme: ColorScheme.fromSeed(
|
|
||||||
brightness: Brightness.dark,
|
|
||||||
seedColor: const Color(0xFF57CC99),
|
|
||||||
surface: const Color.fromARGB(255, 20, 18, 23),
|
|
||||||
surfaceContainer: const Color.fromARGB(255, 33, 30, 39),
|
|
||||||
),
|
|
||||||
inputDecorationTheme: const InputDecorationTheme(
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
themeMode: context.watch<SettingsChangeProvider>().themeMode,
|
themeMode: context.watch<SettingsChangeProvider>().themeMode,
|
||||||
initialRoute: '/',
|
|
||||||
routes: {
|
|
||||||
'/': (context) => const AppMainWidget(initialPage: 1),
|
|
||||||
'/chats': (context) => const AppMainWidget(initialPage: 0),
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -213,7 +190,7 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
||||||
child = const DatabaseMigrationView();
|
child = const DatabaseMigrationView();
|
||||||
} else if (_isUserCreated) {
|
} else if (_isUserCreated) {
|
||||||
if (gUser.twonlySafeBackup == null && !_skipBackup && kReleaseMode) {
|
if (gUser.twonlySafeBackup == null && !_skipBackup && kReleaseMode) {
|
||||||
child = TwonlyIdentityBackupView(
|
child = SetupBackupView(
|
||||||
callBack: () {
|
callBack: () {
|
||||||
_skipBackup = true;
|
_skipBackup = true;
|
||||||
setState(() {});
|
setState(() {});
|
||||||
|
|
|
||||||
55
lib/src/constants/routes.keys.dart
Normal file
55
lib/src/constants/routes.keys.dart
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
class Routes {
|
||||||
|
static const String home = '/';
|
||||||
|
static const String chats = '/chats';
|
||||||
|
static const String chatsAddNewUser = '/chats/add_new_user';
|
||||||
|
static const String chatsArchived = '/chats/archived';
|
||||||
|
static const String chatsStartNewChat = '/chats/start_new_chat';
|
||||||
|
static const String chatsCameraSendTo = '/chats/camera_send_to';
|
||||||
|
static const String chatsMediaViewer = '/chats/media_viewer';
|
||||||
|
static const String chatsMessages = '/chats/messages';
|
||||||
|
|
||||||
|
static String groupCreateSelectMember(String? groupId) =>
|
||||||
|
'/group/create/select_member${groupId == null ? '' : '/$groupId'}';
|
||||||
|
|
||||||
|
static String profileGroup(String groupId) => '/profile/group/$groupId';
|
||||||
|
static String profileContact(int contactId) => '/profile/contact/$contactId';
|
||||||
|
|
||||||
|
static const String cameraQRScanner = '/camera/qr_scanner';
|
||||||
|
|
||||||
|
static const String settings = '/settings';
|
||||||
|
static const String settingsProfile = '/settings/profile';
|
||||||
|
static const String settingsPublicProfile = '/settings/public_profile';
|
||||||
|
static const String settingsProfileModifyAvatar =
|
||||||
|
'/settings/profile/modify_avatar';
|
||||||
|
static const String settingsAccount = '/settings/account';
|
||||||
|
static const String settingsSubscription = '/settings/subscription';
|
||||||
|
static const String settingsBackup = '/settings/backup';
|
||||||
|
static const String settingsBackupServer = '/settings/backup/server';
|
||||||
|
static const String settingsBackupRecovery = '/settings/backup/recovery';
|
||||||
|
static const String settingsBackupSetup = '/settings/backup/setup';
|
||||||
|
static const String settingsAppearance = '/settings/appearance';
|
||||||
|
static const String settingsChats = '/settings/chats';
|
||||||
|
static const String settingsChatsReactions = '/settings/chats/reactions';
|
||||||
|
static const String settingsPrivacy = '/settings/privacy';
|
||||||
|
static const String settingsPrivacyBlockUsers =
|
||||||
|
'/settings/privacy/block_users';
|
||||||
|
static const String settingsNotification = '/settings/notification';
|
||||||
|
static const String settingsStorage = '/settings/storage_data';
|
||||||
|
static const String settingsStorageImport = '/settings/storage_data/import';
|
||||||
|
static const String settingsStorageExport = '/settings/storage_data/export';
|
||||||
|
static const String settingsHelp = '/settings/help';
|
||||||
|
static const String settingsHelpFaq = '/settings/help/faq';
|
||||||
|
static const String settingsHelpContactUs = '/settings/help/contact_us';
|
||||||
|
static const String settingsHelpDiagnostics = '/settings/help/diagnostics';
|
||||||
|
static const String settingsHelpUserStudy = '/settings/help/user_study';
|
||||||
|
static const String settingsHelpUserStudyQuestionnaire =
|
||||||
|
'/settings/help/user_study/questionnaire';
|
||||||
|
static const String settingsHelpCredits = '/settings/help/credits';
|
||||||
|
static const String settingsHelpChangelog = '/settings/help/changelog';
|
||||||
|
static const String settingsDeveloper = '/settings/developer';
|
||||||
|
static const String settingsDeveloperRetransmissionDatabase =
|
||||||
|
'/settings/developer/retransmission_database';
|
||||||
|
static const String settingsDeveloperAutomatedTesting =
|
||||||
|
'/settings/developer/automated_testing';
|
||||||
|
static const String settingsInvite = '/settings/invite';
|
||||||
|
}
|
||||||
285
lib/src/providers/routing.provider.dart
Normal file
285
lib/src/providers/routing.provider.dart
Normal file
|
|
@ -0,0 +1,285 @@
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:twonly/app.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/views/camera/camera_qr_scanner.view.dart';
|
||||||
|
import 'package:twonly/src/views/camera/camera_send_to.view.dart';
|
||||||
|
import 'package:twonly/src/views/chats/add_new_user.view.dart';
|
||||||
|
import 'package:twonly/src/views/chats/archived_chats.view.dart';
|
||||||
|
import 'package:twonly/src/views/chats/chat_messages.view.dart';
|
||||||
|
import 'package:twonly/src/views/chats/media_viewer.view.dart';
|
||||||
|
import 'package:twonly/src/views/chats/start_new_chat.view.dart';
|
||||||
|
import 'package:twonly/src/views/contact/contact.view.dart';
|
||||||
|
import 'package:twonly/src/views/groups/group.view.dart';
|
||||||
|
import 'package:twonly/src/views/groups/group_create_select_members.view.dart';
|
||||||
|
import 'package:twonly/src/views/onboarding/recover.view.dart';
|
||||||
|
import 'package:twonly/src/views/public_profile.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/account.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/appearance.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/backup/backup.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/backup/backup_server.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/backup/setup_backup.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/chat/chat_reactions.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/chat/chat_settings.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/data_and_storage.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/data_and_storage/export_media.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/data_and_storage/import_media.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/developer/automated_testing.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/developer/developer.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/developer/retransmission_data.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/help/changelog.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/help/contact_us.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/help/credits.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/help/diagnostics.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/help/faq.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/help/help.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/notification.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/privacy.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/privacy_view_block.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/profile/modify_avatar.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/profile/profile.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/settings_main.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/share_with_friends.view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/subscription/subscription.view.dart';
|
||||||
|
import 'package:twonly/src/views/user_study/user_study_questionnaire.view.dart';
|
||||||
|
import 'package:twonly/src/views/user_study/user_study_welcome.view.dart';
|
||||||
|
|
||||||
|
final routerProvider = GoRouter(
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.home,
|
||||||
|
builder: (context, state) => const AppMainWidget(initialPage: 1),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Chats
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.chats,
|
||||||
|
builder: (context, state) => const AppMainWidget(initialPage: 0),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: 'add_new_user',
|
||||||
|
builder: (context, state) => const AddNewUserView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'archived',
|
||||||
|
builder: (context, state) => const ArchivedChatsView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'start_new_chat',
|
||||||
|
builder: (context, state) => const StartNewChatView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'camera_send_to',
|
||||||
|
builder: (context, state) {
|
||||||
|
final group = state.extra! as Group;
|
||||||
|
return CameraSendToView(group);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'media_viewer',
|
||||||
|
builder: (context, state) {
|
||||||
|
final group = state.extra! as Group;
|
||||||
|
return MediaViewerView(group);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'messages',
|
||||||
|
builder: (context, state) {
|
||||||
|
final group = state.extra! as Group;
|
||||||
|
return ChatMessagesView(group);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
GoRoute(
|
||||||
|
path: '/profile/contact/:contactId',
|
||||||
|
builder: (context, state) {
|
||||||
|
final contactId = state.pathParameters['contactId']!;
|
||||||
|
return ContactView(int.parse(contactId));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
GoRoute(
|
||||||
|
path: '/profile/group/:groupId',
|
||||||
|
builder: (context, state) {
|
||||||
|
final groupId = state.pathParameters['groupId']!;
|
||||||
|
return GroupView(groupId);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
GoRoute(
|
||||||
|
path: '/group/create/select_member',
|
||||||
|
builder: (context, state) {
|
||||||
|
return const GroupCreateSelectMembersView();
|
||||||
|
},
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: ':groupId',
|
||||||
|
builder: (context, state) {
|
||||||
|
final groupId = state.pathParameters['groupId'];
|
||||||
|
return GroupCreateSelectMembersView(groupId: groupId);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.cameraQRScanner,
|
||||||
|
builder: (context, state) {
|
||||||
|
return const QrCodeScannerView();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
// settings
|
||||||
|
GoRoute(
|
||||||
|
path: Routes.settings,
|
||||||
|
builder: (context, state) => const SettingsMainView(),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: 'profile',
|
||||||
|
builder: (context, state) => const ProfileView(),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: 'modify_avatar',
|
||||||
|
builder: (context, state) => const ModifyAvatarView(),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'public_profile',
|
||||||
|
builder: (context, state) => const PublicProfileView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'account',
|
||||||
|
builder: (context, state) => const AccountView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'subscription',
|
||||||
|
builder: (context, state) => const SubscriptionView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'backup',
|
||||||
|
builder: (context, state) => const BackupView(),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: 'server',
|
||||||
|
builder: (context, state) => const BackupServerView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'recovery',
|
||||||
|
builder: (context, state) => const BackupRecoveryView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'setup',
|
||||||
|
builder: (context, state) => SetupBackupView(
|
||||||
|
isPasswordChangeOnly: state.extra as bool? ?? false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'appearance',
|
||||||
|
builder: (context, state) => const AppearanceView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'chats',
|
||||||
|
builder: (context, state) => const ChatSettingsView(),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: 'reactions',
|
||||||
|
builder: (context, state) => const ChatReactionSelectionView(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'privacy',
|
||||||
|
builder: (context, state) => const PrivacyView(),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: 'block_users',
|
||||||
|
builder: (context, state) => const PrivacyViewBlockUsersView(),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'notification',
|
||||||
|
builder: (context, state) => const NotificationView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'storage_data',
|
||||||
|
builder: (context, state) => const DataAndStorageView(),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: 'import',
|
||||||
|
builder: (context, state) => const ImportMediaView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'export',
|
||||||
|
builder: (context, state) => const ExportMediaView(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'help',
|
||||||
|
builder: (context, state) => const HelpView(),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: 'faq',
|
||||||
|
builder: (context, state) => const FaqView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'contact_us',
|
||||||
|
builder: (context, state) => const ContactUsView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'diagnostics',
|
||||||
|
builder: (context, state) => const DiagnosticsView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'user_study',
|
||||||
|
builder: (context, state) => UserStudyWelcomeView(
|
||||||
|
wasOpenedAutomatic: state.extra as bool? ?? false,
|
||||||
|
),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: 'questionnaire',
|
||||||
|
builder: (context, state) =>
|
||||||
|
const UserStudyQuestionnaireView(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'credits',
|
||||||
|
builder: (context, state) => const CreditsView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'changelog',
|
||||||
|
builder: (context, state) => ChangeLogView(
|
||||||
|
changeLog: state.extra as String?,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'developer',
|
||||||
|
builder: (context, state) => const DeveloperSettingsView(),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: 'retransmission_database',
|
||||||
|
builder: (context, state) => const RetransmissionDataView(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'automated_testing',
|
||||||
|
builder: (context, state) => const AutomatedTestingView(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'invite',
|
||||||
|
builder: (context, state) => const ShareWithFriendsView(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
@ -5,8 +5,11 @@ import 'dart:typed_data';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:drift/drift.dart' show Value;
|
import 'package:drift/drift.dart' show Value;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_sharing_intent/flutter_sharing_intent.dart';
|
||||||
import 'package:flutter_sharing_intent/model/sharing_file.dart';
|
import 'package:flutter_sharing_intent/model/sharing_file.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/services/api/mediafiles/upload.service.dart';
|
import 'package:twonly/src/services/api/mediafiles/upload.service.dart';
|
||||||
|
|
@ -16,8 +19,6 @@ import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/camera/share_image_editor.view.dart';
|
import 'package:twonly/src/views/camera/share_image_editor.view.dart';
|
||||||
import 'package:twonly/src/views/chats/add_new_user.view.dart';
|
import 'package:twonly/src/views/chats/add_new_user.view.dart';
|
||||||
import 'package:twonly/src/views/components/alert_dialog.dart';
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
import 'package:twonly/src/views/contact/contact.view.dart';
|
|
||||||
import 'package:twonly/src/views/public_profile.view.dart';
|
|
||||||
|
|
||||||
Future<bool> handleIntentUrl(BuildContext context, Uri uri) async {
|
Future<bool> handleIntentUrl(BuildContext context, Uri uri) async {
|
||||||
if (!uri.scheme.startsWith('http')) return false;
|
if (!uri.scheme.startsWith('http')) return false;
|
||||||
|
|
@ -32,14 +33,7 @@ Future<bool> handleIntentUrl(BuildContext context, Uri uri) async {
|
||||||
if (!context.mounted) return false;
|
if (!context.mounted) return false;
|
||||||
|
|
||||||
if (username == gUser.username) {
|
if (username == gUser.username) {
|
||||||
await Navigator.push(
|
await context.push(Routes.settingsPublicProfile);
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const PublicProfileView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,14 +85,7 @@ Future<bool> handleIntentUrl(BuildContext context, Uri uri) async {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await Navigator.push(
|
await context.push(Routes.profileContact(contact.userId));
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return ContactView(contact.userId);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await showAlertDialog(
|
await showAlertDialog(
|
||||||
|
|
@ -149,6 +136,27 @@ Future<void> handleIntentMediaFile(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StreamSubscription<List<SharedFile>> initIntentStreams(
|
||||||
|
BuildContext context,
|
||||||
|
void Function(Uri) onUrlCallBack,
|
||||||
|
) {
|
||||||
|
FlutterSharingIntent.instance.getInitialSharing().then((f) {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
handleIntentSharedFile(context, f, onUrlCallBack);
|
||||||
|
});
|
||||||
|
|
||||||
|
return FlutterSharingIntent.instance.getMediaStream().listen(
|
||||||
|
(f) {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
handleIntentSharedFile(context, f, onUrlCallBack);
|
||||||
|
},
|
||||||
|
// ignore: inference_failure_on_untyped_parameter
|
||||||
|
onError: (err) {
|
||||||
|
Log.error('getIntentDataStream error: $err');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> handleIntentSharedFile(
|
Future<void> handleIntentSharedFile(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
List<SharedFile> files,
|
List<SharedFile> files,
|
||||||
|
|
|
||||||
13
lib/src/themes/dark.dart
Normal file
13
lib/src/themes/dark.dart
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
final ThemeData darkTheme = ThemeData.dark().copyWith(
|
||||||
|
colorScheme: ColorScheme.fromSeed(
|
||||||
|
brightness: Brightness.dark,
|
||||||
|
seedColor: const Color(0xFF57CC99),
|
||||||
|
surface: const Color.fromARGB(255, 20, 18, 23),
|
||||||
|
surfaceContainer: const Color.fromARGB(255, 33, 30, 39),
|
||||||
|
),
|
||||||
|
inputDecorationTheme: const InputDecorationTheme(
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
);
|
||||||
10
lib/src/themes/light.dart
Normal file
10
lib/src/themes/light.dart
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
final ThemeData lightTheme = ThemeData(
|
||||||
|
colorScheme: ColorScheme.fromSeed(
|
||||||
|
seedColor: const Color(0xFF57CC99),
|
||||||
|
),
|
||||||
|
inputDecorationTheme: const InputDecorationTheme(
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
@ -4,13 +4,13 @@ import 'package:twonly/src/views/camera/camera_preview_components/camera_preview
|
||||||
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview_controller_view.dart';
|
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview_controller_view.dart';
|
||||||
import 'package:twonly/src/views/camera/camera_preview_components/main_camera_controller.dart';
|
import 'package:twonly/src/views/camera/camera_preview_components/main_camera_controller.dart';
|
||||||
|
|
||||||
class QrCodeScanner extends StatefulWidget {
|
class QrCodeScannerView extends StatefulWidget {
|
||||||
const QrCodeScanner({super.key});
|
const QrCodeScannerView({super.key});
|
||||||
@override
|
@override
|
||||||
State<QrCodeScanner> createState() => QrCodeScannerState();
|
State<QrCodeScannerView> createState() => QrCodeScannerViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class QrCodeScannerState extends State<QrCodeScanner> {
|
class QrCodeScannerViewState extends State<QrCodeScannerView> {
|
||||||
final MainCameraController _mainCameraController = MainCameraController();
|
final MainCameraController _mainCameraController = MainCameraController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -4,28 +4,21 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/providers/connection.provider.dart';
|
import 'package:twonly/src/providers/connection.provider.dart';
|
||||||
import 'package:twonly/src/providers/purchases.provider.dart';
|
import 'package:twonly/src/providers/purchases.provider.dart';
|
||||||
import 'package:twonly/src/services/subscription.service.dart';
|
import 'package:twonly/src/services/subscription.service.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:twonly/src/views/chats/add_new_user.view.dart';
|
|
||||||
import 'package:twonly/src/views/chats/archived_chats.view.dart';
|
|
||||||
import 'package:twonly/src/views/chats/chat_list_components/connection_info.comp.dart';
|
import 'package:twonly/src/views/chats/chat_list_components/connection_info.comp.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_list_components/feedback_btn.dart';
|
import 'package:twonly/src/views/chats/chat_list_components/feedback_btn.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_list_components/group_list_item.dart';
|
import 'package:twonly/src/views/chats/chat_list_components/group_list_item.dart';
|
||||||
import 'package:twonly/src/views/chats/start_new_chat.view.dart';
|
|
||||||
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
||||||
import 'package:twonly/src/views/components/notification_badge.dart';
|
import 'package:twonly/src/views/components/notification_badge.dart';
|
||||||
import 'package:twonly/src/views/public_profile.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/help/changelog.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/profile/profile.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/settings_main.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/subscription/subscription.view.dart';
|
|
||||||
import 'package:twonly/src/views/user_study/user_study_welcome.view.dart';
|
|
||||||
|
|
||||||
class ChatListView extends StatefulWidget {
|
class ChatListView extends StatefulWidget {
|
||||||
const ChatListView({super.key});
|
const ChatListView({super.key});
|
||||||
|
|
@ -64,15 +57,9 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
if (gUser.subscriptionPlan == SubscriptionPlan.Tester.name &&
|
if (gUser.subscriptionPlan == SubscriptionPlan.Tester.name &&
|
||||||
!gUser.askedForUserStudyPermission) {
|
!gUser.askedForUserStudyPermission) {
|
||||||
await Navigator.push(
|
await context.push(
|
||||||
context,
|
Routes.settingsHelpUserStudy,
|
||||||
MaterialPageRoute(
|
extra: true,
|
||||||
builder: (context) {
|
|
||||||
return const UserStudyWelcomeView(
|
|
||||||
wasOpenedAutomatic: true,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,15 +76,9 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
// only show changelog to people who already have contacts
|
// only show changelog to people who already have contacts
|
||||||
// this prevents that this is shown directly after the user registered
|
// this prevents that this is shown directly after the user registered
|
||||||
if (_groupsNotPinned.isNotEmpty) {
|
if (_groupsNotPinned.isNotEmpty) {
|
||||||
await Navigator.push(
|
await context.push(
|
||||||
context,
|
Routes.settingsHelpChangelog,
|
||||||
MaterialPageRoute(
|
extra: changeLog,
|
||||||
builder: (context) {
|
|
||||||
return ChangeLogView(
|
|
||||||
changeLog: changeLog,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -120,14 +101,7 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await Navigator.push(
|
await context.push(Routes.settingsProfile);
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const ProfileView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
setState(() {}); // gUser has updated
|
setState(() {}); // gUser has updated
|
||||||
},
|
},
|
||||||
|
|
@ -141,16 +115,7 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
const Text('twonly '),
|
const Text('twonly '),
|
||||||
if (plan != SubscriptionPlan.Free)
|
if (plan != SubscriptionPlan.Free)
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () => context.push(Routes.settingsSubscription),
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const SubscriptionView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: context.color.primary,
|
color: context.color.primary,
|
||||||
|
|
@ -184,28 +149,15 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
key: searchForOtherUsers,
|
key: searchForOtherUsers,
|
||||||
icon: const FaIcon(FontAwesomeIcons.userPlus, size: 18),
|
icon: const FaIcon(FontAwesomeIcons.userPlus, size: 18),
|
||||||
onPressed: () {
|
onPressed: () => context.push(Routes.chatsAddNewUser),
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const AddNewUserView(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await Navigator.push(
|
await context.push(Routes.settings);
|
||||||
context,
|
if (mounted) setState(() {}); // gUser may has changed...
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const SettingsMainView(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (!mounted) return;
|
|
||||||
setState(() {}); // gUser may has changed...
|
|
||||||
},
|
},
|
||||||
icon: const FaIcon(FontAwesomeIcons.gear, size: 19),
|
icon: const FaIcon(FontAwesomeIcons.gear, size: 19),
|
||||||
),
|
),
|
||||||
|
|
@ -234,14 +186,7 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
child: OutlinedButton.icon(
|
child: OutlinedButton.icon(
|
||||||
icon: const Icon(Icons.person_add),
|
icon: const Icon(Icons.person_add),
|
||||||
onPressed: () {
|
onPressed: () => context.push(Routes.chatsAddNewUser),
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const AddNewUserView(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
label: Text(
|
label: Text(
|
||||||
context.lang.chatListViewSearchUserNameBtn,
|
context.lang.chatListViewSearchUserNameBtn,
|
||||||
),
|
),
|
||||||
|
|
@ -265,16 +210,7 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: const TextStyle(fontSize: 13),
|
style: const TextStyle(fontSize: 13),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () => context.push(Routes.chatsArchived),
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const ArchivedChatsView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Check if the index is for the pinned users
|
// Check if the index is for the pinned users
|
||||||
|
|
@ -320,16 +256,7 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
color: context.color.primary,
|
color: context.color.primary,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
onTap: () {
|
onTap: () => context.push(Routes.settingsPublicProfile),
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const PublicProfileView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 45,
|
width: 45,
|
||||||
height: 45,
|
height: 45,
|
||||||
|
|
@ -345,16 +272,7 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
backgroundColor: context.color.primary,
|
backgroundColor: context.color.primary,
|
||||||
onPressed: () {
|
onPressed: () => context.push(Routes.chatsStartNewChat),
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const StartNewChatView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: FaIcon(
|
child: FaIcon(
|
||||||
FontAwesomeIcons.penToSquare,
|
FontAwesomeIcons.penToSquare,
|
||||||
color: isDarkMode(context) ? Colors.black : Colors.white,
|
color: isDarkMode(context) ? Colors.black : Colors.white,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:twonly/src/views/settings/help/contact_us.view.dart';
|
|
||||||
|
|
||||||
class FeedbackIconButton extends StatefulWidget {
|
class FeedbackIconButton extends StatefulWidget {
|
||||||
const FeedbackIconButton({super.key});
|
const FeedbackIconButton({super.key});
|
||||||
|
|
@ -37,14 +37,7 @@ class _FeedbackIconButtonState extends State<FeedbackIconButton> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return IconButton(
|
return IconButton(
|
||||||
onPressed: () async {
|
onPressed: () => context.push(Routes.settingsHelpContactUs),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const ContactUsView(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
tooltip: context.lang.feedbackTooltip,
|
tooltip: context.lang.feedbackTooltip,
|
||||||
icon: const FaIcon(FontAwesomeIcons.commentDots, size: 19),
|
icon: const FaIcon(FontAwesomeIcons.commentDots, size: 19),
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,22 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:mutex/mutex.dart';
|
import 'package:mutex/mutex.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||||
import 'package:twonly/src/database/tables/messages.table.dart';
|
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/services/api/mediafiles/download.service.dart';
|
import 'package:twonly/src/services/api/mediafiles/download.service.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/camera/camera_send_to.view.dart';
|
|
||||||
import 'package:twonly/src/views/chats/chat_list_components/last_message_time.dart';
|
import 'package:twonly/src/views/chats/chat_list_components/last_message_time.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages.view.dart';
|
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/message_send_state_icon.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/message_send_state_icon.dart';
|
||||||
import 'package:twonly/src/views/chats/media_viewer.view.dart';
|
|
||||||
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
||||||
import 'package:twonly/src/views/components/flame.dart';
|
import 'package:twonly/src/views/components/flame.dart';
|
||||||
import 'package:twonly/src/views/components/group_context_menu.component.dart';
|
import 'package:twonly/src/views/components/group_context_menu.component.dart';
|
||||||
import 'package:twonly/src/views/contact/contact.view.dart';
|
|
||||||
import 'package:twonly/src/views/groups/group.view.dart';
|
|
||||||
|
|
||||||
class GroupListItem extends StatefulWidget {
|
class GroupListItem extends StatefulWidget {
|
||||||
const GroupListItem({
|
const GroupListItem({
|
||||||
|
|
@ -161,13 +159,9 @@ class _UserListItem extends State<GroupListItem> {
|
||||||
|
|
||||||
Future<void> onTap() async {
|
Future<void> onTap() async {
|
||||||
if (_currentMessage == null && widget.group.totalMediaCounter == 0) {
|
if (_currentMessage == null && widget.group.totalMediaCounter == 0) {
|
||||||
await Navigator.push(
|
await context.push(
|
||||||
context,
|
Routes.chatsCameraSendTo,
|
||||||
MaterialPageRoute(
|
extra: widget.group,
|
||||||
builder: (context) {
|
|
||||||
return CameraSendToView(widget.group);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -185,26 +179,18 @@ class _UserListItem extends State<GroupListItem> {
|
||||||
}
|
}
|
||||||
if (mediaFile.downloadState! == DownloadState.ready) {
|
if (mediaFile.downloadState! == DownloadState.ready) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
await Navigator.push(
|
await context.push(
|
||||||
context,
|
Routes.chatsMediaViewer,
|
||||||
MaterialPageRoute(
|
extra: widget.group,
|
||||||
builder: (context) {
|
|
||||||
return MediaViewerView(widget.group);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
await Navigator.push(
|
await context.push(
|
||||||
context,
|
Routes.chatsMessages,
|
||||||
MaterialPageRoute(
|
extra: widget.group,
|
||||||
builder: (context) {
|
|
||||||
return ChatMessagesView(widget.group);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,42 +236,27 @@ class _UserListItem extends State<GroupListItem> {
|
||||||
),
|
),
|
||||||
leading: GestureDetector(
|
leading: GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
Widget pushWidget = GroupView(widget.group);
|
|
||||||
|
|
||||||
if (widget.group.isDirectChat) {
|
if (widget.group.isDirectChat) {
|
||||||
final contacts = await twonlyDB.groupsDao
|
final contacts = await twonlyDB.groupsDao
|
||||||
.getGroupContact(widget.group.groupId);
|
.getGroupContact(widget.group.groupId);
|
||||||
pushWidget = ContactView(contacts.first.userId);
|
if (!context.mounted) return;
|
||||||
|
await context.push(Routes.profileContact(contacts.first.userId));
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
await context.push(Routes.profileGroup(widget.group.groupId));
|
||||||
}
|
}
|
||||||
if (!context.mounted) return;
|
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return pushWidget;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: AvatarIcon(group: widget.group),
|
child: AvatarIcon(group: widget.group),
|
||||||
),
|
),
|
||||||
trailing: (widget.group.leftGroup)
|
trailing: (widget.group.leftGroup)
|
||||||
? null
|
? null
|
||||||
: IconButton(
|
: IconButton(
|
||||||
onPressed: () {
|
onPressed: () => context.push(
|
||||||
Navigator.push(
|
_hasNonOpenedMediaFile
|
||||||
context,
|
? Routes.chatsMessages
|
||||||
MaterialPageRoute(
|
: Routes.chatsCameraSendTo,
|
||||||
builder: (context) {
|
extra: widget.group,
|
||||||
if (_hasNonOpenedMediaFile) {
|
),
|
||||||
return ChatMessagesView(widget.group);
|
|
||||||
} else {
|
|
||||||
return CameraSendToView(widget.group);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: FaIcon(
|
icon: FaIcon(
|
||||||
_hasNonOpenedMediaFile
|
_hasNonOpenedMediaFile
|
||||||
? FontAwesomeIcons.solidComments
|
? FontAwesomeIcons.solidComments
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:mutex/mutex.dart';
|
import 'package:mutex/mutex.dart';
|
||||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/tables/messages.table.dart';
|
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
|
@ -21,8 +22,6 @@ import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
||||||
import 'package:twonly/src/views/components/blink.component.dart';
|
import 'package:twonly/src/views/components/blink.component.dart';
|
||||||
import 'package:twonly/src/views/components/flame.dart';
|
import 'package:twonly/src/views/components/flame.dart';
|
||||||
import 'package:twonly/src/views/components/verified_shield.dart';
|
import 'package:twonly/src/views/components/verified_shield.dart';
|
||||||
import 'package:twonly/src/views/contact/contact.view.dart';
|
|
||||||
import 'package:twonly/src/views/groups/group.view.dart';
|
|
||||||
|
|
||||||
Color getMessageColor(Message message) {
|
Color getMessageColor(Message message) {
|
||||||
return (message.senderId == null)
|
return (message.senderId == null)
|
||||||
|
|
@ -291,23 +290,10 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
||||||
await twonlyDB.groupsDao.getAllGroupMembers(group.groupId);
|
await twonlyDB.groupsDao.getAllGroupMembers(group.groupId);
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
if (member.isEmpty) return;
|
if (member.isEmpty) return;
|
||||||
await Navigator.push(
|
await context
|
||||||
context,
|
.push(Routes.profileContact(member.first.contactId));
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return ContactView(member.first.contactId);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
await Navigator.push(
|
await context.push(Routes.profileGroup(group.groupId));
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return GroupView(group);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||||
import 'package:twonly/src/database/tables/messages.table.dart'
|
import 'package:twonly/src/database/tables/messages.table.dart'
|
||||||
hide MessageActions;
|
hide MessageActions;
|
||||||
|
|
@ -17,7 +19,6 @@ import 'package:twonly/src/views/chats/chat_messages_components/message_actions.
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/message_context_menu.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/message_context_menu.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/response_container.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/response_container.dart';
|
||||||
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
||||||
import 'package:twonly/src/views/contact/contact.view.dart';
|
|
||||||
|
|
||||||
class ChatListEntry extends StatefulWidget {
|
class ChatListEntry extends StatefulWidget {
|
||||||
const ChatListEntry({
|
const ChatListEntry({
|
||||||
|
|
@ -204,15 +205,9 @@ class _ChatListEntryState extends State<ChatListEntry> {
|
||||||
hideContactAvatar
|
hideContactAvatar
|
||||||
? const SizedBox(width: 24)
|
? const SizedBox(width: 24)
|
||||||
: GestureDetector(
|
: GestureDetector(
|
||||||
onTap: () async {
|
onTap: () => context.push(
|
||||||
await Navigator.push(
|
Routes.profileContact(widget.message.senderId!),
|
||||||
context,
|
),
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) =>
|
|
||||||
ContactView(widget.message.senderId!),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: AvatarIcon(
|
child: AvatarIcon(
|
||||||
contactId: widget.message.senderId,
|
contactId: widget.message.senderId,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,14 @@ import 'dart:collection';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||||
import 'package:twonly/src/database/tables/messages.table.dart';
|
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/components/animate_icon.dart';
|
import 'package:twonly/src/views/components/animate_icon.dart';
|
||||||
import 'package:twonly/src/views/settings/subscription/subscription.view.dart';
|
|
||||||
|
|
||||||
enum MessageSendState {
|
enum MessageSendState {
|
||||||
received,
|
received,
|
||||||
|
|
@ -163,16 +164,7 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
|
||||||
style: const TextStyle(fontSize: 9),
|
style: const TextStyle(fontSize: 9),
|
||||||
);
|
);
|
||||||
|
|
||||||
onTap = () async {
|
onTap = () => context.push(Routes.settingsSubscription);
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const SubscriptionView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
if (mediaFile.uploadState == UploadState.preprocessing ||
|
if (mediaFile.uploadState == UploadState.preprocessing ||
|
||||||
mediaFile.uploadState == UploadState.initialized) {
|
mediaFile.uploadState == UploadState.initialized) {
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,17 @@ import 'dart:async';
|
||||||
import 'package:drift/drift.dart' hide Column;
|
import 'package:drift/drift.dart' hide Column;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/chats/add_new_user.view.dart';
|
|
||||||
import 'package:twonly/src/views/chats/chat_messages.view.dart';
|
import 'package:twonly/src/views/chats/chat_messages.view.dart';
|
||||||
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
||||||
import 'package:twonly/src/views/components/flame.dart';
|
import 'package:twonly/src/views/components/flame.dart';
|
||||||
import 'package:twonly/src/views/components/group_context_menu.component.dart';
|
import 'package:twonly/src/views/components/group_context_menu.component.dart';
|
||||||
import 'package:twonly/src/views/components/user_context_menu.component.dart';
|
import 'package:twonly/src/views/components/user_context_menu.component.dart';
|
||||||
import 'package:twonly/src/views/groups/group_create_select_members.view.dart';
|
|
||||||
|
|
||||||
class StartNewChatView extends StatefulWidget {
|
class StartNewChatView extends StatefulWidget {
|
||||||
const StartNewChatView({super.key});
|
const StartNewChatView({super.key});
|
||||||
|
|
@ -165,15 +165,8 @@ class _StartNewChatView extends State<StartNewChatView> {
|
||||||
size: 13,
|
size: 13,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () async {
|
onTap: () => context
|
||||||
await Navigator.push(
|
.push(Routes.groupCreateSelectMember(null)),
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) =>
|
|
||||||
const GroupCreateSelectMembersView(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (i == 1) {
|
if (i == 1) {
|
||||||
|
|
@ -185,14 +178,7 @@ class _StartNewChatView extends State<StartNewChatView> {
|
||||||
size: 13,
|
size: 13,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.chatsAddNewUser),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const AddNewUserView(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (i == 2) {
|
if (i == 2) {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import 'package:drift/drift.dart' hide Column;
|
import 'package:drift/drift.dart' hide Column;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages.view.dart';
|
|
||||||
import 'package:twonly/src/views/components/alert_dialog.dart';
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
import 'package:twonly/src/views/components/context_menu.component.dart';
|
import 'package:twonly/src/views/components/context_menu.component.dart';
|
||||||
|
|
||||||
|
|
@ -45,16 +46,10 @@ class GroupContextMenu extends StatelessWidget {
|
||||||
),
|
),
|
||||||
ContextMenuItem(
|
ContextMenuItem(
|
||||||
title: context.lang.contextMenuOpenChat,
|
title: context.lang.contextMenuOpenChat,
|
||||||
onTap: () async {
|
onTap: () => context.push(
|
||||||
await Navigator.push(
|
Routes.chatsMessages,
|
||||||
context,
|
extra: group,
|
||||||
MaterialPageRoute(
|
),
|
||||||
builder: (context) {
|
|
||||||
return ChatMessagesView(group);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: FontAwesomeIcons.comments,
|
icon: FontAwesomeIcons.comments,
|
||||||
),
|
),
|
||||||
if (!group.archived)
|
if (!group.archived)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ import 'dart:async';
|
||||||
import 'package:clock/clock.dart';
|
import 'package:clock/clock.dart';
|
||||||
import 'package:drift/drift.dart' show Value;
|
import 'package:drift/drift.dart' show Value;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/services/flame.service.dart';
|
import 'package:twonly/src/services/flame.service.dart';
|
||||||
import 'package:twonly/src/services/subscription.service.dart';
|
import 'package:twonly/src/services/subscription.service.dart';
|
||||||
|
|
@ -10,7 +12,6 @@ import 'package:twonly/src/utils/log.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/components/animate_icon.dart';
|
import 'package:twonly/src/views/components/animate_icon.dart';
|
||||||
import 'package:twonly/src/views/components/better_list_title.dart';
|
import 'package:twonly/src/views/components/better_list_title.dart';
|
||||||
import 'package:twonly/src/views/settings/subscription/subscription.view.dart';
|
|
||||||
|
|
||||||
class MaxFlameListTitle extends StatefulWidget {
|
class MaxFlameListTitle extends StatefulWidget {
|
||||||
const MaxFlameListTitle({
|
const MaxFlameListTitle({
|
||||||
|
|
@ -46,14 +47,7 @@ class _MaxFlameListTitleState extends State<MaxFlameListTitle> {
|
||||||
|
|
||||||
Future<void> _restoreFlames() async {
|
Future<void> _restoreFlames() async {
|
||||||
if (!isPayingUser(getCurrentPlan())) {
|
if (!isPayingUser(getCurrentPlan())) {
|
||||||
await Navigator.push(
|
await context.push(Routes.settingsSubscription);
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const SubscriptionView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.info(
|
Log.info(
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/components/context_menu.component.dart';
|
import 'package:twonly/src/views/components/context_menu.component.dart';
|
||||||
import 'package:twonly/src/views/contact/contact.view.dart';
|
|
||||||
|
|
||||||
class UserContextMenu extends StatelessWidget {
|
class UserContextMenu extends StatelessWidget {
|
||||||
const UserContextMenu({
|
const UserContextMenu({
|
||||||
|
|
@ -20,16 +21,7 @@ class UserContextMenu extends StatelessWidget {
|
||||||
items: [
|
items: [
|
||||||
ContextMenuItem(
|
ContextMenuItem(
|
||||||
title: context.lang.contextMenuUserProfile,
|
title: context.lang.contextMenuUserProfile,
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.profileContact(contact.userId)),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return ContactView(contact.userId);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: FontAwesomeIcons.user,
|
icon: FontAwesomeIcons.user,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/views/public_profile.view.dart';
|
|
||||||
|
|
||||||
class VerifiedShield extends StatefulWidget {
|
class VerifiedShield extends StatefulWidget {
|
||||||
const VerifiedShield({
|
const VerifiedShield({
|
||||||
|
|
@ -58,16 +59,7 @@ class _VerifiedShieldState extends State<VerifiedShield> {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: (contact == null)
|
onTap: (contact == null)
|
||||||
? null
|
? null
|
||||||
: () async {
|
: () => context.push(Routes.settingsPublicProfile),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const PublicProfileView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
message: isVerified
|
message: isVerified
|
||||||
? 'You verified this contact'
|
? 'You verified this contact'
|
||||||
|
|
|
||||||
|
|
@ -19,16 +19,16 @@ import 'package:twonly/src/views/groups/group_member.context.dart';
|
||||||
import 'package:twonly/src/views/settings/profile/profile.view.dart';
|
import 'package:twonly/src/views/settings/profile/profile.view.dart';
|
||||||
|
|
||||||
class GroupView extends StatefulWidget {
|
class GroupView extends StatefulWidget {
|
||||||
const GroupView(this.group, {super.key});
|
const GroupView(this.groupId, {super.key});
|
||||||
|
|
||||||
final Group group;
|
final String groupId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GroupView> createState() => _GroupViewState();
|
State<GroupView> createState() => _GroupViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GroupViewState extends State<GroupView> {
|
class _GroupViewState extends State<GroupView> {
|
||||||
late Group group;
|
Group? _group;
|
||||||
|
|
||||||
List<(Contact, GroupMember)> members = [];
|
List<(Contact, GroupMember)> members = [];
|
||||||
|
|
||||||
|
|
@ -37,7 +37,6 @@ class _GroupViewState extends State<GroupView> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
group = widget.group;
|
|
||||||
initAsync();
|
initAsync();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
@ -50,16 +49,15 @@ class _GroupViewState extends State<GroupView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initAsync() async {
|
Future<void> initAsync() async {
|
||||||
final groupStream = twonlyDB.groupsDao.watchGroup(widget.group.groupId);
|
final groupStream = twonlyDB.groupsDao.watchGroup(widget.groupId);
|
||||||
groupSub = groupStream.listen((update) {
|
groupSub = groupStream.listen((update) {
|
||||||
if (update != null) {
|
if (update != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
group = update;
|
_group = update;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
final membersStream =
|
final membersStream = twonlyDB.groupsDao.watchGroupMembers(widget.groupId);
|
||||||
twonlyDB.groupsDao.watchGroupMembers(widget.group.groupId);
|
|
||||||
membersSub = membersStream.listen((update) {
|
membersSub = membersStream.listen((update) {
|
||||||
setState(() {
|
setState(() {
|
||||||
members = update;
|
members = update;
|
||||||
|
|
@ -71,13 +69,13 @@ class _GroupViewState extends State<GroupView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateGroupName() async {
|
Future<void> _updateGroupName() async {
|
||||||
final newGroupName = await showGroupNameChangeDialog(context, group);
|
final newGroupName = await showGroupNameChangeDialog(context, _group!);
|
||||||
|
|
||||||
if (context.mounted &&
|
if (context.mounted &&
|
||||||
newGroupName != null &&
|
newGroupName != null &&
|
||||||
newGroupName != '' &&
|
newGroupName != '' &&
|
||||||
newGroupName != group.groupName) {
|
newGroupName != _group!.groupName) {
|
||||||
if (!await updateGroupName(group, newGroupName)) {
|
if (!await updateGroupName(_group!, newGroupName)) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
showNetworkIssue(context);
|
showNetworkIssue(context);
|
||||||
}
|
}
|
||||||
|
|
@ -89,11 +87,13 @@ class _GroupViewState extends State<GroupView> {
|
||||||
final selectedUserIds = await Navigator.push(
|
final selectedUserIds = await Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => GroupCreateSelectMembersView(group: group),
|
builder: (context) => GroupCreateSelectMembersView(
|
||||||
|
groupId: _group?.groupId,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
) as List<int>?;
|
) as List<int>?;
|
||||||
if (selectedUserIds == null) return;
|
if (selectedUserIds == null) return;
|
||||||
if (!await addNewGroupMembers(group, selectedUserIds)) {
|
if (!await addNewGroupMembers(_group!, selectedUserIds)) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
showNetworkIssue(context);
|
showNetworkIssue(context);
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +115,7 @@ class _GroupViewState extends State<GroupView> {
|
||||||
if (members.isNotEmpty) {
|
if (members.isNotEmpty) {
|
||||||
// In case there are other members, check that there is at least one other admin before I leave the group.
|
// In case there are other members, check that there is at least one other admin before I leave the group.
|
||||||
|
|
||||||
if (group.isGroupAdmin) {
|
if (_group!.isGroupAdmin) {
|
||||||
if (!members.any((m) => m.$2.memberState == MemberState.admin)) {
|
if (!members.any((m) => m.$2.memberState == MemberState.admin)) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
await showAlertDialog(
|
await showAlertDialog(
|
||||||
|
|
@ -131,16 +131,17 @@ class _GroupViewState extends State<GroupView> {
|
||||||
|
|
||||||
late bool success;
|
late bool success;
|
||||||
|
|
||||||
if (group.isGroupAdmin) {
|
if (_group!.isGroupAdmin) {
|
||||||
// Current user is a admin, to the state can be updated by the user him self.
|
// Current user is a admin, to the state can be updated by the user him self.
|
||||||
final keyPair = IdentityKeyPair.fromSerialized(group.myGroupPrivateKey!);
|
final keyPair =
|
||||||
|
IdentityKeyPair.fromSerialized(_group!.myGroupPrivateKey!);
|
||||||
success = await removeMemberFromGroup(
|
success = await removeMemberFromGroup(
|
||||||
group,
|
_group!,
|
||||||
keyPair.getPublicKey().serialize(),
|
keyPair.getPublicKey().serialize(),
|
||||||
gUser.userId,
|
gUser.userId,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
success = await leaveAsNonAdminFromGroup(group);
|
success = await leaveAsNonAdminFromGroup(_group!);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
|
@ -153,6 +154,9 @@ class _GroupViewState extends State<GroupView> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
if (_group == null) {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text(''),
|
title: const Text(''),
|
||||||
|
|
@ -162,7 +166,7 @@ class _GroupViewState extends State<GroupView> {
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
child: AvatarIcon(
|
child: AvatarIcon(
|
||||||
group: group,
|
group: _group,
|
||||||
fontSize: 30,
|
fontSize: 30,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -171,24 +175,24 @@ class _GroupViewState extends State<GroupView> {
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(right: 10),
|
padding: const EdgeInsets.only(right: 10),
|
||||||
child: VerifiedShield(key: Key(group.groupId), group: group),
|
child: VerifiedShield(key: Key(_group!.groupId), group: _group),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
substringBy(group.groupName, 25),
|
substringBy(_group!.groupName, 25),
|
||||||
style: const TextStyle(fontSize: 20),
|
style: const TextStyle(fontSize: 20),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 50),
|
const SizedBox(height: 50),
|
||||||
if (group.isGroupAdmin && !group.leftGroup)
|
if (_group!.isGroupAdmin && !_group!.leftGroup)
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.pencil,
|
icon: FontAwesomeIcons.pencil,
|
||||||
text: context.lang.groupNameInput,
|
text: context.lang.groupNameInput,
|
||||||
onTap: _updateGroupName,
|
onTap: _updateGroupName,
|
||||||
),
|
),
|
||||||
SelectChatDeletionTimeListTitle(
|
SelectChatDeletionTimeListTitle(
|
||||||
groupId: widget.group.groupId,
|
groupId: widget.groupId,
|
||||||
disabled: !group.isGroupAdmin,
|
disabled: !_group!.isGroupAdmin,
|
||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
ListTile(
|
ListTile(
|
||||||
|
|
@ -203,7 +207,7 @@ class _GroupViewState extends State<GroupView> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (group.isGroupAdmin && !group.leftGroup)
|
if (_group!.isGroupAdmin && !_group!.leftGroup)
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.plus,
|
icon: FontAwesomeIcons.plus,
|
||||||
text: context.lang.addMember,
|
text: context.lang.addMember,
|
||||||
|
|
@ -216,7 +220,7 @@ class _GroupViewState extends State<GroupView> {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
text: context.lang.you,
|
text: context.lang.you,
|
||||||
trailing: (group.isGroupAdmin) ? Text(context.lang.admin) : null,
|
trailing: (_group!.isGroupAdmin) ? Text(context.lang.admin) : null,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await Navigator.push(
|
await Navigator.push(
|
||||||
context,
|
context,
|
||||||
|
|
@ -229,7 +233,7 @@ class _GroupViewState extends State<GroupView> {
|
||||||
...members.map((member) {
|
...members.map((member) {
|
||||||
return GroupMemberContextMenu(
|
return GroupMemberContextMenu(
|
||||||
key: ValueKey(member.$1.userId),
|
key: ValueKey(member.$1.userId),
|
||||||
group: group,
|
group: _group!,
|
||||||
contact: member.$1,
|
contact: member.$1,
|
||||||
member: member.$2,
|
member: member.$2,
|
||||||
child: BetterListTile(
|
child: BetterListTile(
|
||||||
|
|
@ -256,7 +260,7 @@ class _GroupViewState extends State<GroupView> {
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
if (!group.leftGroup)
|
if (!_group!.leftGroup)
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.rightFromBracket,
|
icon: FontAwesomeIcons.rightFromBracket,
|
||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ import 'package:twonly/src/views/components/user_context_menu.component.dart';
|
||||||
import 'package:twonly/src/views/groups/group_create_select_group_name.view.dart';
|
import 'package:twonly/src/views/groups/group_create_select_group_name.view.dart';
|
||||||
|
|
||||||
class GroupCreateSelectMembersView extends StatefulWidget {
|
class GroupCreateSelectMembersView extends StatefulWidget {
|
||||||
const GroupCreateSelectMembersView({this.group, super.key});
|
const GroupCreateSelectMembersView({this.groupId, super.key});
|
||||||
final Group? group;
|
final String? groupId;
|
||||||
@override
|
@override
|
||||||
State<GroupCreateSelectMembersView> createState() => _StartNewChatView();
|
State<GroupCreateSelectMembersView> createState() => _StartNewChatView();
|
||||||
}
|
}
|
||||||
|
|
@ -46,9 +46,8 @@ class _StartNewChatView extends State<GroupCreateSelectMembersView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initAsync() async {
|
Future<void> initAsync() async {
|
||||||
if (widget.group != null) {
|
if (widget.groupId != null) {
|
||||||
final members =
|
final members = await twonlyDB.groupsDao.getGroupContact(widget.groupId!);
|
||||||
await twonlyDB.groupsDao.getGroupContact(widget.group!.groupId);
|
|
||||||
for (final member in members) {
|
for (final member in members) {
|
||||||
alreadyInGroup.add(member.userId);
|
alreadyInGroup.add(member.userId);
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +100,7 @@ class _StartNewChatView extends State<GroupCreateSelectMembersView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> submitChanges() async {
|
Future<void> submitChanges() async {
|
||||||
if (widget.group != null) {
|
if (widget.groupId != null) {
|
||||||
Navigator.pop(context, selectedUsers.toList());
|
Navigator.pop(context, selectedUsers.toList());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +124,7 @@ class _StartNewChatView extends State<GroupCreateSelectMembersView> {
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(
|
title: Text(
|
||||||
widget.group == null
|
widget.groupId == null
|
||||||
? context.lang.selectMembers
|
? context.lang.selectMembers
|
||||||
: context.lang.addMember,
|
: context.lang.addMember,
|
||||||
),
|
),
|
||||||
|
|
@ -133,7 +132,9 @@ class _StartNewChatView extends State<GroupCreateSelectMembersView> {
|
||||||
floatingActionButton: FilledButton.icon(
|
floatingActionButton: FilledButton.icon(
|
||||||
onPressed: selectedUsers.isEmpty ? null : submitChanges,
|
onPressed: selectedUsers.isEmpty ? null : submitChanges,
|
||||||
label: Text(
|
label: Text(
|
||||||
widget.group == null ? context.lang.next : context.lang.updateGroup,
|
widget.groupId == null
|
||||||
|
? context.lang.next
|
||||||
|
: context.lang.updateGroup,
|
||||||
),
|
),
|
||||||
icon: const FaIcon(FontAwesomeIcons.penToSquare),
|
icon: const FaIcon(FontAwesomeIcons.penToSquare),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
import 'package:drift/drift.dart' show Value;
|
import 'package:drift/drift.dart' show Value;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/tables/groups.table.dart';
|
import 'package:twonly/src/database/tables/groups.table.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
|
@ -9,7 +11,6 @@ import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
import 'package:twonly/src/services/api/messages.dart';
|
import 'package:twonly/src/services/api/messages.dart';
|
||||||
import 'package:twonly/src/services/group.services.dart';
|
import 'package:twonly/src/services/group.services.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages.view.dart';
|
|
||||||
import 'package:twonly/src/views/components/alert_dialog.dart';
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
import 'package:twonly/src/views/components/context_menu.component.dart';
|
import 'package:twonly/src/views/components/context_menu.component.dart';
|
||||||
import 'package:twonly/src/views/groups/group.view.dart';
|
import 'package:twonly/src/views/groups/group.view.dart';
|
||||||
|
|
@ -128,12 +129,7 @@ class GroupMemberContextMenu extends StatelessWidget {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
await Navigator.push(
|
await context.push(Routes.chatsMessages, extra: directChat);
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => ChatMessagesView(directChat),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
icon: FontAwesomeIcons.message,
|
icon: FontAwesomeIcons.message,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import 'dart:async';
|
||||||
import 'package:app_links/app_links.dart';
|
import 'package:app_links/app_links.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
import 'package:flutter_sharing_intent/flutter_sharing_intent.dart';
|
|
||||||
import 'package:flutter_sharing_intent/model/sharing_file.dart';
|
import 'package:flutter_sharing_intent/model/sharing_file.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
|
@ -126,31 +125,10 @@ class HomeViewState extends State<HomeView> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_intentStreamSub = FlutterSharingIntent.instance.getMediaStream().listen(
|
_intentStreamSub = initIntentStreams(
|
||||||
(f) {
|
context,
|
||||||
if (mounted) {
|
_mainCameraController.setSharedLinkForPreview,
|
||||||
handleIntentSharedFile(
|
|
||||||
context,
|
|
||||||
f,
|
|
||||||
_mainCameraController.setSharedLinkForPreview,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// ignore: inference_failure_on_untyped_parameter
|
|
||||||
onError: (err) {
|
|
||||||
Log.error('getIntentDataStream error: $err');
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
FlutterSharingIntent.instance.getInitialSharing().then((f) {
|
|
||||||
if (mounted) {
|
|
||||||
handleIntentSharedFile(
|
|
||||||
context,
|
|
||||||
f,
|
|
||||||
_mainCameraController.setSharedLinkForPreview,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:restart_app/restart_app.dart';
|
import 'package:restart_app/restart_app.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/model/json/userdata.dart';
|
import 'package:twonly/src/model/json/userdata.dart';
|
||||||
import 'package:twonly/src/services/twonly_safe/restore.twonly_safe.dart';
|
import 'package:twonly/src/services/twonly_safe/restore.twonly_safe.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/components/alert_dialog.dart';
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
import 'package:twonly/src/views/settings/backup/twonly_safe_server.view.dart';
|
|
||||||
|
|
||||||
class BackupRecoveryView extends StatefulWidget {
|
class BackupRecoveryView extends StatefulWidget {
|
||||||
const BackupRecoveryView({super.key});
|
const BackupRecoveryView({super.key});
|
||||||
|
|
@ -135,14 +136,8 @@ class _BackupRecoveryViewState extends State<BackupRecoveryView> {
|
||||||
Center(
|
Center(
|
||||||
child: OutlinedButton(
|
child: OutlinedButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
backupServer = await Navigator.push(
|
backupServer =
|
||||||
context,
|
await context.push(Routes.settingsBackupServer);
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const TwonlySafeServerView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
child: Text(context.lang.backupExpertSettings),
|
child: Text(context.lang.backupExpertSettings),
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,12 @@
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/constants/secure_storage_keys.dart';
|
import 'package:twonly/src/constants/secure_storage_keys.dart';
|
||||||
import 'package:twonly/src/model/json/userdata.dart';
|
import 'package:twonly/src/model/json/userdata.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
||||||
|
|
@ -17,7 +18,6 @@ import 'package:twonly/src/utils/pow.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:twonly/src/views/components/alert_dialog.dart';
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
import 'package:twonly/src/views/groups/group.view.dart';
|
import 'package:twonly/src/views/groups/group.view.dart';
|
||||||
import 'package:twonly/src/views/onboarding/recover.view.dart';
|
|
||||||
|
|
||||||
class RegisterView extends StatefulWidget {
|
class RegisterView extends StatefulWidget {
|
||||||
const RegisterView({
|
const RegisterView({
|
||||||
|
|
@ -302,16 +302,8 @@ class _RegisterViewState extends State<RegisterView> {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
OutlinedButton.icon(
|
OutlinedButton.icon(
|
||||||
onPressed: () async {
|
onPressed: () =>
|
||||||
await Navigator.push(
|
context.push(Routes.settingsBackupRecovery),
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const BackupRecoveryView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
label: Text(context.lang.twonlySafeRecoverBtn),
|
label: Text(context.lang.twonlySafeRecoverBtn),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:qr_flutter/qr_flutter.dart';
|
import 'package:qr_flutter/qr_flutter.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/utils/avatars.dart';
|
import 'package:twonly/src/utils/avatars.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/qr.dart';
|
import 'package:twonly/src/utils/qr.dart';
|
||||||
import 'package:twonly/src/views/camera/camera_qr_scanner.view.dart';
|
|
||||||
import 'package:twonly/src/views/components/better_list_title.dart';
|
import 'package:twonly/src/views/components/better_list_title.dart';
|
||||||
|
|
||||||
class PublicProfileView extends StatefulWidget {
|
class PublicProfileView extends StatefulWidget {
|
||||||
|
|
@ -96,14 +96,7 @@ class _PublicProfileViewState extends State<PublicProfileView> {
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
leading: const FaIcon(FontAwesomeIcons.qrcode),
|
leading: const FaIcon(FontAwesomeIcons.qrcode),
|
||||||
text: context.lang.scanOtherProfile,
|
text: context.lang.scanOtherProfile,
|
||||||
onTap: () {
|
onTap: () => context.push(Routes.cameraQRScanner),
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const QrCodeScanner(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
leading: const FaIcon(
|
leading: const FaIcon(
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/model/json/userdata.dart';
|
import 'package:twonly/src/model/json/userdata.dart';
|
||||||
import 'package:twonly/src/services/twonly_safe/create_backup.twonly_safe.dart';
|
import 'package:twonly/src/services/twonly_safe/create_backup.twonly_safe.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/settings/backup/twonly_safe_backup.view.dart';
|
|
||||||
|
|
||||||
void Function() gUpdateBackupView = () {};
|
void Function() gUpdateBackupView = () {};
|
||||||
|
|
||||||
|
|
@ -60,16 +61,7 @@ class _BackupViewState extends State<BackupView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> changeTwonlySafePassword() async {
|
Future<void> changeTwonlySafePassword() async {
|
||||||
await Navigator.push(
|
await context.push(Routes.settingsBackupSetup, extra: true);
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const TwonlyIdentityBackupView(
|
|
||||||
isPasswordChangeOnly: true,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
setState(() {
|
setState(() {
|
||||||
// gUser was updated
|
// gUser was updated
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,14 @@ import 'package:twonly/src/utils/log.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
|
|
||||||
class TwonlySafeServerView extends StatefulWidget {
|
class BackupServerView extends StatefulWidget {
|
||||||
const TwonlySafeServerView({super.key});
|
const BackupServerView({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<TwonlySafeServerView> createState() => _TwonlySafeServerViewState();
|
State<BackupServerView> createState() => _BackupServerViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TwonlySafeServerViewState extends State<TwonlySafeServerView> {
|
class _BackupServerViewState extends State<BackupServerView> {
|
||||||
final TextEditingController _urlController = TextEditingController();
|
final TextEditingController _urlController = TextEditingController();
|
||||||
final TextEditingController _usernameController = TextEditingController();
|
final TextEditingController _usernameController = TextEditingController();
|
||||||
final TextEditingController _passwordController = TextEditingController();
|
final TextEditingController _passwordController = TextEditingController();
|
||||||
|
|
@ -2,13 +2,14 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart' show rootBundle;
|
import 'package:flutter/services.dart' show rootBundle;
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/services/twonly_safe/common.twonly_safe.dart';
|
import 'package:twonly/src/services/twonly_safe/common.twonly_safe.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/components/alert_dialog.dart';
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
import 'package:twonly/src/views/settings/backup/twonly_safe_server.view.dart';
|
|
||||||
|
|
||||||
class TwonlyIdentityBackupView extends StatefulWidget {
|
class SetupBackupView extends StatefulWidget {
|
||||||
const TwonlyIdentityBackupView({
|
const SetupBackupView({
|
||||||
this.isPasswordChangeOnly = false,
|
this.isPasswordChangeOnly = false,
|
||||||
this.callBack,
|
this.callBack,
|
||||||
super.key,
|
super.key,
|
||||||
|
|
@ -20,11 +21,10 @@ class TwonlyIdentityBackupView extends StatefulWidget {
|
||||||
final bool isPasswordChangeOnly;
|
final bool isPasswordChangeOnly;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<TwonlyIdentityBackupView> createState() =>
|
State<SetupBackupView> createState() => _SetupBackupViewState();
|
||||||
_TwonlyIdentityBackupViewState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
class _SetupBackupViewState extends State<SetupBackupView> {
|
||||||
bool obscureText = true;
|
bool obscureText = true;
|
||||||
bool isLoading = false;
|
bool isLoading = false;
|
||||||
final TextEditingController passwordCtrl = TextEditingController();
|
final TextEditingController passwordCtrl = TextEditingController();
|
||||||
|
|
@ -179,16 +179,7 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Center(
|
Center(
|
||||||
child: OutlinedButton(
|
child: OutlinedButton(
|
||||||
onPressed: () async {
|
onPressed: () => context.push(Routes.settingsBackupServer),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const TwonlySafeServerView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Text(context.lang.backupExpertSettings),
|
child: Text(context.lang.backupExpertSettings),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/settings/chat/chat_reactions.view.dart';
|
|
||||||
|
|
||||||
class ChatSettingsView extends StatefulWidget {
|
class ChatSettingsView extends StatefulWidget {
|
||||||
const ChatSettingsView({super.key});
|
const ChatSettingsView({super.key});
|
||||||
|
|
@ -25,16 +26,7 @@ class _ChatSettingsViewState extends State<ChatSettingsView> {
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(context.lang.settingsPreSelectedReactions),
|
title: Text(context.lang.settingsPreSelectedReactions),
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsChatsReactions),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const ChatReactionSelectionView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/services/api/mediafiles/download.service.dart';
|
import 'package:twonly/src/services/api/mediafiles/download.service.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:twonly/src/views/settings/data_and_storage/export_media.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/data_and_storage/import_media.view.dart';
|
|
||||||
|
|
||||||
class DataAndStorageView extends StatefulWidget {
|
class DataAndStorageView extends StatefulWidget {
|
||||||
const DataAndStorageView({super.key});
|
const DataAndStorageView({super.key});
|
||||||
|
|
@ -91,32 +90,14 @@ class _DataAndStorageViewState extends State<DataAndStorageView> {
|
||||||
title: Text(
|
title: Text(
|
||||||
context.lang.exportMemories,
|
context.lang.exportMemories,
|
||||||
),
|
),
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsStorageExport),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (_) {
|
|
||||||
return const ExportMediaView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
if (Platform.isAndroid)
|
if (Platform.isAndroid)
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
context.lang.importMemories,
|
context.lang.importMemories,
|
||||||
),
|
),
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsStorageImport),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (_) {
|
|
||||||
return const ImportMediaView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
ListTile(
|
ListTile(
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:restart_app/restart_app.dart';
|
import 'package:restart_app/restart_app.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:twonly/src/views/components/alert_dialog.dart';
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
import 'package:twonly/src/views/settings/developer/automated_testing.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/developer/retransmission_data.view.dart';
|
|
||||||
|
|
||||||
class DeveloperSettingsView extends StatefulWidget {
|
class DeveloperSettingsView extends StatefulWidget {
|
||||||
const DeveloperSettingsView({super.key});
|
const DeveloperSettingsView({super.key});
|
||||||
|
|
@ -55,16 +55,8 @@ class _DeveloperSettingsViewState extends State<DeveloperSettingsView> {
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Show Retransmission Database'),
|
title: const Text('Show Retransmission Database'),
|
||||||
onTap: () async {
|
onTap: () =>
|
||||||
await Navigator.push(
|
context.push(Routes.settingsDeveloperRetransmissionDatabase),
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const RetransmissionDataView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Delete all (!) app data'),
|
title: const Text('Delete all (!) app data'),
|
||||||
|
|
@ -97,16 +89,8 @@ class _DeveloperSettingsViewState extends State<DeveloperSettingsView> {
|
||||||
if (!kReleaseMode)
|
if (!kReleaseMode)
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Automated Testing'),
|
title: const Text('Automated Testing'),
|
||||||
onTap: () async {
|
onTap: () =>
|
||||||
await Navigator.push(
|
context.push(Routes.settingsDeveloperAutomatedTesting),
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const AutomatedTestingView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,13 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:twonly/src/views/components/alert_dialog.dart';
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
import 'package:twonly/src/views/settings/help/changelog.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/help/contact_us.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/help/credits.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/help/diagnostics.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/help/faq.view.dart';
|
|
||||||
import 'package:twonly/src/views/user_study/user_study_welcome.view.dart';
|
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class HelpView extends StatefulWidget {
|
class HelpView extends StatefulWidget {
|
||||||
|
|
@ -40,50 +36,12 @@ class _HelpViewState extends State<HelpView> {
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(context.lang.settingsHelpFAQ),
|
title: Text(context.lang.settingsHelpFAQ),
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsHelpFaq),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const FaqView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(context.lang.settingsHelpContactUs),
|
title: Text(context.lang.settingsHelpContactUs),
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsHelpContactUs),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const ContactUsView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
// ListTile(
|
|
||||||
// title: Text(context.lang.settingsResetTutorials),
|
|
||||||
// subtitle: Text(
|
|
||||||
// context.lang.settingsResetTutorialsDesc,
|
|
||||||
// style: const TextStyle(fontSize: 12),
|
|
||||||
// ),
|
|
||||||
// onTap: () async {
|
|
||||||
// await updateUserdata((user) {
|
|
||||||
// user.tutorialDisplayed = [];
|
|
||||||
// return user;
|
|
||||||
// });
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
// SnackBar(
|
|
||||||
// content: Text(context.lang.settingsResetTutorialsSuccess),
|
|
||||||
// duration: const Duration(seconds: 3),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
const Divider(),
|
const Divider(),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(context.lang.allowErrorTracking),
|
title: Text(context.lang.allowErrorTracking),
|
||||||
|
|
@ -99,32 +57,13 @@ class _HelpViewState extends State<HelpView> {
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(context.lang.settingsHelpDiagnostics),
|
title: Text(context.lang.settingsHelpDiagnostics),
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsHelpDiagnostics),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const DiagnosticsView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
if (gUser.userStudyParticipantsToken == null || kDebugMode)
|
if (gUser.userStudyParticipantsToken == null || kDebugMode)
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Teilnahme an Nutzerstudie'),
|
title: const Text('Teilnahme an Nutzerstudie'),
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsHelpUserStudy),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const UserStudyWelcomeView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
setState(() {}); // gUser has changed
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: PackageInfo.fromPlatform(),
|
future: PackageInfo.fromPlatform(),
|
||||||
|
|
@ -141,59 +80,34 @@ class _HelpViewState extends State<HelpView> {
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(context.lang.settingsHelpLicenses),
|
title: Text(context.lang.settingsHelpLicenses),
|
||||||
onTap: () {
|
onTap: () => showLicensePage(context: context),
|
||||||
showLicensePage(context: context);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(context.lang.settingsHelpCredits),
|
title: Text(context.lang.settingsHelpCredits),
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsHelpCredits),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const CreditsView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Changelog'),
|
title: const Text('Changelog'),
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsHelpChangelog),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const ChangeLogView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Open Source'),
|
title: const Text('Open Source'),
|
||||||
onTap: () async {
|
onTap: () => launchUrl(
|
||||||
await launchUrl(
|
Uri.parse('https://github.com/twonlyapp/twonly-app'),
|
||||||
Uri.parse('https://github.com/twonlyapp/twonly-app'),
|
),
|
||||||
);
|
|
||||||
},
|
|
||||||
trailing:
|
trailing:
|
||||||
const FaIcon(FontAwesomeIcons.arrowUpRightFromSquare, size: 15),
|
const FaIcon(FontAwesomeIcons.arrowUpRightFromSquare, size: 15),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(context.lang.settingsHelpImprint),
|
title: Text(context.lang.settingsHelpImprint),
|
||||||
onTap: () async {
|
onTap: () => launchUrl(Uri.parse('https://twonly.eu/de/legal/')),
|
||||||
await launchUrl(Uri.parse('https://twonly.eu/de/legal/'));
|
|
||||||
},
|
|
||||||
trailing:
|
trailing:
|
||||||
const FaIcon(FontAwesomeIcons.arrowUpRightFromSquare, size: 15),
|
const FaIcon(FontAwesomeIcons.arrowUpRightFromSquare, size: 15),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(context.lang.settingsHelpTerms),
|
title: Text(context.lang.settingsHelpTerms),
|
||||||
onTap: () async {
|
onTap: () =>
|
||||||
await launchUrl(Uri.parse('https://twonly.eu/de/legal/agb.html'));
|
launchUrl(Uri.parse('https://twonly.eu/de/legal/agb.html')),
|
||||||
},
|
|
||||||
trailing:
|
trailing:
|
||||||
const FaIcon(FontAwesomeIcons.arrowUpRightFromSquare, size: 15),
|
const FaIcon(FontAwesomeIcons.arrowUpRightFromSquare, size: 15),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/settings/privacy_view_block.users.dart';
|
|
||||||
|
|
||||||
class PrivacyView extends StatefulWidget {
|
class PrivacyView extends StatefulWidget {
|
||||||
const PrivacyView({super.key});
|
const PrivacyView({super.key});
|
||||||
|
|
@ -40,16 +41,7 @@ class _PrivacyViewState extends State<PrivacyView> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsPrivacyBlockUsers),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const PrivacyViewBlockUsers();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,14 @@ import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
||||||
import 'package:twonly/src/views/components/user_context_menu.component.dart';
|
import 'package:twonly/src/views/components/user_context_menu.component.dart';
|
||||||
|
|
||||||
class PrivacyViewBlockUsers extends StatefulWidget {
|
class PrivacyViewBlockUsersView extends StatefulWidget {
|
||||||
const PrivacyViewBlockUsers({super.key});
|
const PrivacyViewBlockUsersView({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PrivacyViewBlockUsers> createState() => _PrivacyViewBlockUsers();
|
State<PrivacyViewBlockUsersView> createState() => _PrivacyViewBlockUsers();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PrivacyViewBlockUsers extends State<PrivacyViewBlockUsers> {
|
class _PrivacyViewBlockUsers extends State<PrivacyViewBlockUsersView> {
|
||||||
late Stream<List<Contact>> allUsers;
|
late Stream<List<Contact>> allUsers;
|
||||||
List<Contact> filteredUsers = [];
|
List<Contact> filteredUsers = [];
|
||||||
String filter = '';
|
String filter = '';
|
||||||
|
|
@ -6,14 +6,14 @@ import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
|
|
||||||
class ModifyAvatar extends StatefulWidget {
|
class ModifyAvatarView extends StatefulWidget {
|
||||||
const ModifyAvatar({super.key});
|
const ModifyAvatarView({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ModifyAvatar> createState() => _ModifyAvatarState();
|
State<ModifyAvatarView> createState() => _ModifyAvatarViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ModifyAvatarState extends State<ModifyAvatar> {
|
class _ModifyAvatarViewState extends State<ModifyAvatarView> {
|
||||||
final AvatarMakerController _avatarMakerController =
|
final AvatarMakerController _avatarMakerController =
|
||||||
PersistentAvatarMakerController(customizedPropertyCategories: []);
|
PersistentAvatarMakerController(customizedPropertyCategories: []);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@ import 'package:avatar_maker/avatar_maker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
||||||
import 'package:twonly/src/services/twonly_safe/common.twonly_safe.dart';
|
import 'package:twonly/src/services/twonly_safe/common.twonly_safe.dart';
|
||||||
import 'package:twonly/src/services/twonly_safe/create_backup.twonly_safe.dart';
|
import 'package:twonly/src/services/twonly_safe/create_backup.twonly_safe.dart';
|
||||||
|
|
@ -11,7 +13,6 @@ import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:twonly/src/views/components/better_list_title.dart';
|
import 'package:twonly/src/views/components/better_list_title.dart';
|
||||||
import 'package:twonly/src/views/groups/group.view.dart';
|
import 'package:twonly/src/views/groups/group.view.dart';
|
||||||
import 'package:twonly/src/views/settings/profile/modify_avatar.view.dart';
|
|
||||||
|
|
||||||
class ProfileView extends StatefulWidget {
|
class ProfileView extends StatefulWidget {
|
||||||
const ProfileView({super.key});
|
const ProfileView({super.key});
|
||||||
|
|
@ -110,12 +111,7 @@ class _ProfileViewState extends State<ProfileView> {
|
||||||
icon: const Icon(Icons.edit),
|
icon: const Icon(Icons.edit),
|
||||||
label: Text(context.lang.settingsProfileCustomizeAvatar),
|
label: Text(context.lang.settingsProfileCustomizeAvatar),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await Navigator.push(
|
await context.push(Routes.settingsProfileModifyAvatar);
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const ModifyAvatar(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await _avatarMakerController.performRestore();
|
await _avatarMakerController.performRestore();
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,12 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
||||||
import 'package:twonly/src/views/components/better_list_title.dart';
|
import 'package:twonly/src/views/components/better_list_title.dart';
|
||||||
import 'package:twonly/src/views/public_profile.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/account.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/appearance.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/backup/backup.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/chat/chat_settings.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/data_and_storage.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/developer/developer.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/help/help.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/notification.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/privacy.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/profile/profile.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/share_with_friends.view.dart';
|
|
||||||
import 'package:twonly/src/views/settings/subscription/subscription.view.dart';
|
|
||||||
|
|
||||||
class SettingsMainView extends StatefulWidget {
|
class SettingsMainView extends StatefulWidget {
|
||||||
const SettingsMainView({super.key});
|
const SettingsMainView({super.key});
|
||||||
|
|
@ -42,14 +31,7 @@ class _SettingsMainViewState extends State<SettingsMainView> {
|
||||||
Expanded(
|
Expanded(
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await Navigator.push(
|
await context.push(Routes.settingsProfile);
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const ProfileView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
child: ColoredBox(
|
child: ColoredBox(
|
||||||
|
|
@ -86,16 +68,7 @@ class _SettingsMainViewState extends State<SettingsMainView> {
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
onPressed: () {
|
onPressed: () => context.push(Routes.settingsPublicProfile),
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const PublicProfileView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: const FaIcon(FontAwesomeIcons.qrcode),
|
icon: const FaIcon(FontAwesomeIcons.qrcode),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -105,160 +78,61 @@ class _SettingsMainViewState extends State<SettingsMainView> {
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.user,
|
icon: FontAwesomeIcons.user,
|
||||||
text: context.lang.settingsAccount,
|
text: context.lang.settingsAccount,
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsAccount),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const AccountView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.shieldHeart,
|
icon: FontAwesomeIcons.shieldHeart,
|
||||||
text: context.lang.settingsSubscription,
|
text: context.lang.settingsSubscription,
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsSubscription),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const SubscriptionView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: Icons.lock_clock_rounded,
|
icon: Icons.lock_clock_rounded,
|
||||||
text: context.lang.settingsBackup,
|
text: context.lang.settingsBackup,
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsBackup),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const BackupView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.sun,
|
icon: FontAwesomeIcons.sun,
|
||||||
text: context.lang.settingsAppearance,
|
text: context.lang.settingsAppearance,
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsAppearance),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const AppearanceView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.comment,
|
icon: FontAwesomeIcons.comment,
|
||||||
text: context.lang.settingsChats,
|
text: context.lang.settingsChats,
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsChats),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const ChatSettingsView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.lock,
|
icon: FontAwesomeIcons.lock,
|
||||||
text: context.lang.settingsPrivacy,
|
text: context.lang.settingsPrivacy,
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsPrivacy),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const PrivacyView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.bell,
|
icon: FontAwesomeIcons.bell,
|
||||||
text: context.lang.settingsNotification,
|
text: context.lang.settingsNotification,
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsNotification),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const NotificationView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.chartPie,
|
icon: FontAwesomeIcons.chartPie,
|
||||||
iconSize: 15,
|
iconSize: 15,
|
||||||
text: context.lang.settingsStorageData,
|
text: context.lang.settingsStorageData,
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsStorage),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const DataAndStorageView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.circleQuestion,
|
icon: FontAwesomeIcons.circleQuestion,
|
||||||
text: context.lang.settingsHelp,
|
text: context.lang.settingsHelp,
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsHelp),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const HelpView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
if (gUser.isDeveloper)
|
if (gUser.isDeveloper)
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.code,
|
icon: FontAwesomeIcons.code,
|
||||||
text: 'Developer Settings',
|
text: 'Developer Settings',
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsDeveloper),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const DeveloperSettingsView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.shareFromSquare,
|
icon: FontAwesomeIcons.shareFromSquare,
|
||||||
text: context.lang.inviteFriends,
|
text: context.lang.inviteFriends,
|
||||||
onTap: () async {
|
onTap: () => context.push(Routes.settingsInvite),
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const ShareWithFriendsView();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,22 @@
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/src/utils/keyvalue.dart';
|
import 'package:twonly/src/utils/keyvalue.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:twonly/src/views/user_study/user_study_data_collection.dart';
|
import 'package:twonly/src/views/user_study/user_study_data_collection.dart';
|
||||||
|
|
||||||
class UserStudyQuestionnaire extends StatefulWidget {
|
class UserStudyQuestionnaireView extends StatefulWidget {
|
||||||
const UserStudyQuestionnaire({super.key});
|
const UserStudyQuestionnaireView({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<UserStudyQuestionnaire> createState() => _UserStudyQuestionnaireState();
|
State<UserStudyQuestionnaireView> createState() =>
|
||||||
|
_UserStudyQuestionnaireViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _UserStudyQuestionnaireState extends State<UserStudyQuestionnaire> {
|
class _UserStudyQuestionnaireViewState
|
||||||
|
extends State<UserStudyQuestionnaireView> {
|
||||||
final Map<String, dynamic> _responses = {
|
final Map<String, dynamic> _responses = {
|
||||||
'age': null,
|
'age': null,
|
||||||
'education': null,
|
'education': null,
|
||||||
|
|
@ -62,7 +65,7 @@ class _UserStudyQuestionnaireState extends State<UserStudyQuestionnaire> {
|
||||||
const SnackBar(content: Text('Vielen Dank für deine Teilnahme!')),
|
const SnackBar(content: Text('Vielen Dank für deine Teilnahme!')),
|
||||||
);
|
);
|
||||||
|
|
||||||
Navigator.pop(context);
|
context.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:twonly/src/views/user_study/user_study_questionnaire.view.dart';
|
|
||||||
|
|
||||||
class UserStudyWelcomeView extends StatefulWidget {
|
class UserStudyWelcomeView extends StatefulWidget {
|
||||||
const UserStudyWelcomeView({super.key, this.wasOpenedAutomatic = false});
|
const UserStudyWelcomeView({super.key, this.wasOpenedAutomatic = false});
|
||||||
|
|
@ -54,16 +55,8 @@ class _UserStudyWelcomeViewState extends State<UserStudyWelcomeView> {
|
||||||
const SizedBox(height: 40),
|
const SizedBox(height: 40),
|
||||||
Center(
|
Center(
|
||||||
child: FilledButton(
|
child: FilledButton(
|
||||||
onPressed: () {
|
onPressed: () => context
|
||||||
Navigator.pushReplacement(
|
.pushReplacement(Routes.settingsHelpUserStudyQuestionnaire),
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const UserStudyQuestionnaire();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: const Padding(
|
child: const Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 15),
|
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 15),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|
@ -77,9 +70,7 @@ class _UserStudyWelcomeViewState extends State<UserStudyWelcomeView> {
|
||||||
if (widget.wasOpenedAutomatic)
|
if (widget.wasOpenedAutomatic)
|
||||||
Center(
|
Center(
|
||||||
child: OutlinedButton(
|
child: OutlinedButton(
|
||||||
onPressed: () {
|
onPressed: () => context.pop(),
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
child: const Padding(
|
child: const Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|
@ -98,7 +89,7 @@ class _UserStudyWelcomeViewState extends State<UserStudyWelcomeView> {
|
||||||
u.askedForUserStudyPermission = true;
|
u.askedForUserStudyPermission = true;
|
||||||
return u;
|
return u;
|
||||||
});
|
});
|
||||||
if (context.mounted) Navigator.pop(context);
|
if (context.mounted) context.pop();
|
||||||
},
|
},
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Nicht mehr anzeigen',
|
'Nicht mehr anzeigen',
|
||||||
|
|
|
||||||
|
|
@ -852,6 +852,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.3"
|
version: "2.1.3"
|
||||||
|
go_router:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: go_router
|
||||||
|
sha256: "7974313e217a7771557add6ff2238acb63f635317c35fa590d348fb238f00896"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "17.1.0"
|
||||||
google_mlkit_barcode_scanning:
|
google_mlkit_barcode_scanning:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ dependencies:
|
||||||
vector_graphics: ^1.1.19
|
vector_graphics: ^1.1.19
|
||||||
video_player: ^2.10.1
|
video_player: ^2.10.1
|
||||||
in_app_purchase: ^3.2.3
|
in_app_purchase: ^3.2.3
|
||||||
|
go_router: ^17.1.0
|
||||||
|
|
||||||
|
|
||||||
# Trusted publisher fluttercommunity.dev
|
# Trusted publisher fluttercommunity.dev
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue