From e7f0488a100ae9a99a4c1d22e97c0463457df0eb Mon Sep 17 00:00:00 2001 From: otsmr Date: Sat, 8 Feb 2025 00:03:59 +0100 Subject: [PATCH] start with settings --- lib/src/components/radio_button.dart | 37 +++++++ lib/src/localization/app_en.arb | 12 +++ .../camera_to_share/camera_preview_view.dart | 2 +- lib/src/views/home_view.dart | 6 +- lib/src/views/settings/account_view.dart | 14 +++ lib/src/views/settings/appearance_view.dart | 80 ++++++++++++++++ lib/src/views/settings/help_view.dart | 69 +++++++++++++ .../views/settings/settings_main_view.dart | 96 ++++++------------- pubspec.lock | 80 ++++++++++++++++ pubspec.yaml | 4 +- 10 files changed, 329 insertions(+), 71 deletions(-) create mode 100644 lib/src/components/radio_button.dart create mode 100644 lib/src/views/settings/account_view.dart create mode 100644 lib/src/views/settings/appearance_view.dart create mode 100644 lib/src/views/settings/help_view.dart diff --git a/lib/src/components/radio_button.dart b/lib/src/components/radio_button.dart new file mode 100644 index 0000000..d93c4b0 --- /dev/null +++ b/lib/src/components/radio_button.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; + +class RadioButton extends StatelessWidget { + final T value; + final T? groupValue; + final String label; + final ValueChanged onChanged; + + const RadioButton({ + super.key, + required this.value, + required this.groupValue, + required this.label, + required this.onChanged, + }); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Radio( + value: value, + groupValue: groupValue, + onChanged: onChanged, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + Expanded( + child: GestureDetector( + onTap: () => + onChanged(value), // Call onChanged when the text is tapped + child: Text(label), + ), + ), + ], + ); + } +} diff --git a/lib/src/localization/app_en.arb b/lib/src/localization/app_en.arb index 99424cc..c7da365 100644 --- a/lib/src/localization/app_en.arb +++ b/lib/src/localization/app_en.arb @@ -30,6 +30,18 @@ "messageSendState_TapToLoad": "Tap to load", "messageSendState_Loading": "Downloading", "imageEditorDrawOk": "Take drawing", + "settingsTitle": "Settings", + "settingsAccount": "Konto", + "settingsSubscription": "Subscription", + "settingsAppearance": "Appearance", + "settingsPrivacy": "Privacy", + "settingsNotification": "Notification", + "settingsHelp": "Help", + "settingsHelpSupport": "Support Center", + "settingsHelpVersion": "Version", + "settingsHelpLicenses": "Licenses", + "settingsHelpLegal": "Terms & Privacy Policy", + "settingsAppearanceTheme": "Theme", "undo": "Undo", "redo": "Redo", "close": "Close", diff --git a/lib/src/views/camera_to_share/camera_preview_view.dart b/lib/src/views/camera_to_share/camera_preview_view.dart index 3386c9c..9450431 100644 --- a/lib/src/views/camera_to_share/camera_preview_view.dart +++ b/lib/src/views/camera_to_share/camera_preview_view.dart @@ -33,7 +33,7 @@ class _CameraPreviewViewPermission extends State { }); } } else { - return const CircularProgressIndicator(); + return Container(); } }); } diff --git a/lib/src/views/home_view.dart b/lib/src/views/home_view.dart index 9ef6963..c7f4222 100644 --- a/lib/src/views/home_view.dart +++ b/lib/src/views/home_view.dart @@ -73,8 +73,8 @@ class HomeViewState extends State { bottomNavigationBar: BottomNavigationBar( showSelectedLabels: false, showUnselectedLabels: false, - selectedIconTheme: - IconThemeData(color: const Color.fromARGB(255, 255, 255, 255)), + selectedIconTheme: IconThemeData( + color: Theme.of(context).colorScheme.inverseSurface), items: [ BottomNavigationBarItem( icon: FaIcon(FontAwesomeIcons.camera), @@ -82,8 +82,6 @@ class HomeViewState extends State { ), BottomNavigationBarItem( icon: FaIcon(FontAwesomeIcons.solidComments), label: ""), - // BottomNavigationBarItem( - // icon: FaIcon(FontAwesomeIcons.userShield), label: ""), ], onTap: (int index) { activePageIdx = index; diff --git a/lib/src/views/settings/account_view.dart b/lib/src/views/settings/account_view.dart new file mode 100644 index 0000000..3c48348 --- /dev/null +++ b/lib/src/views/settings/account_view.dart @@ -0,0 +1,14 @@ +import 'package:restart_app/restart_app.dart'; + + + // FilledButton.icon( + // onPressed: () async { + // await deleteLocalUserData(); + // Restart.restartApp( + // notificationTitle: 'Successfully logged out', + // notificationBody: 'Click here to open the app again', + // ); + // }, + // label: Text("Logout"), + // icon: Icon(Icons.no_accounts), + // ), \ No newline at end of file diff --git a/lib/src/views/settings/appearance_view.dart b/lib/src/views/settings/appearance_view.dart new file mode 100644 index 0000000..48b0657 --- /dev/null +++ b/lib/src/views/settings/appearance_view.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:twonly/src/components/radio_button.dart'; +import 'package:twonly/src/providers/settings_change_provider.dart'; +import 'package:twonly/src/utils/misc.dart'; + +class AppearanceView extends StatelessWidget { + const AppearanceView({super.key}); + + void _showSelectThemeMode(BuildContext context) async { + ThemeMode? selectedValue = context.read().themeMode; + + await showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text(context.lang.settingsAppearanceTheme), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + RadioButton( + value: ThemeMode.system, + groupValue: selectedValue, + label: 'System default', + onChanged: (ThemeMode? value) { + selectedValue = value; + Navigator.of(context).pop(); + }, + ), + RadioButton( + value: ThemeMode.light, + groupValue: selectedValue, + label: 'Light', + onChanged: (ThemeMode? value) { + selectedValue = value; + Navigator.of(context).pop(); + }, + ), + RadioButton( + value: ThemeMode.dark, + groupValue: selectedValue, + label: 'Dark', + onChanged: (ThemeMode? value) { + selectedValue = value; + Navigator.of(context).pop(); + }, + ), + ], + ), + ); + }, + ); + if (selectedValue != null && context.mounted) { + context.read().updateThemeMode(selectedValue); + } + } + + @override + Widget build(BuildContext context) { + ThemeMode? selectedTheme = + context.watch().themeMode; + return Scaffold( + appBar: AppBar( + title: Text(context.lang.settingsAppearance), + ), + body: ListView( + children: [ + ListTile( + title: Text(context.lang.settingsAppearanceTheme), + subtitle: + Text(selectedTheme.name, style: TextStyle(color: Colors.grey)), + onTap: () { + _showSelectThemeMode(context); + }, + ), + ], + ), + ); + } +} diff --git a/lib/src/views/settings/help_view.dart b/lib/src/views/settings/help_view.dart new file mode 100644 index 0000000..c131fa3 --- /dev/null +++ b/lib/src/views/settings/help_view.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import 'package:twonly/src/utils/misc.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class HelpView extends StatelessWidget { + const HelpView({super.key}); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(context.lang.settingsHelp), + ), + body: ListView( + children: [ + ListTile( + title: Text(context.lang.settingsHelpSupport), + onTap: () { + launchUrl(Uri.parse("https://twonly.eu/support")); + }, + trailing: + FaIcon(FontAwesomeIcons.arrowUpRightFromSquare, size: 15), + ), + Divider(), + + FutureBuilder( + future: PackageInfo.fromPlatform(), + builder: (context, snap) { + if (snap.hasData) { + return ListTile( + title: Text(context.lang.settingsHelpVersion), + subtitle: Text(snap.data!.version), + ); + } else { + return Container(); + } + }, + ), + ListTile( + title: Text(context.lang.settingsHelpLicenses), + onTap: () { + showLicensePage(context: context); + }, + ), + + // Diagnoseprotokoll + + ListTile( + title: Text(context.lang.settingsHelpLegal), + onTap: () { + launchUrl(Uri.parse("https://twonly.eu/legal")); + // showLicensePage(context: context); + }, + trailing: + FaIcon(FontAwesomeIcons.arrowUpRightFromSquare, size: 15), + ), + ListTile( + title: Text( + "Copyright twonly", + style: TextStyle(color: Colors.grey, fontSize: 13), + ), + ), + + // + ], + )); + } +} diff --git a/lib/src/views/settings/settings_main_view.dart b/lib/src/views/settings/settings_main_view.dart index 9577004..6c96655 100644 --- a/lib/src/views/settings/settings_main_view.dart +++ b/lib/src/views/settings/settings_main_view.dart @@ -1,13 +1,13 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; import 'package:twonly/main.dart'; import 'package:twonly/src/components/initialsavatar.dart'; import 'package:twonly/src/model/json/user_data.dart'; -import 'package:restart_app/restart_app.dart'; import 'package:flutter/material.dart'; -import 'package:twonly/src/providers/settings_change_provider.dart'; +import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/storage.dart'; +import 'package:twonly/src/views/settings/appearance_view.dart'; +import 'package:twonly/src/views/settings/help_view.dart'; class ProfileView extends StatefulWidget { const ProfileView({super.key}); @@ -33,7 +33,7 @@ class _ProfileViewState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text("Settings"), + title: Text(context.lang.settingsTitle), ), body: (userData == null) ? null @@ -79,100 +79,66 @@ class _ProfileViewState extends State { ), SettingsListTile( icon: FontAwesomeIcons.user, - text: "Konto", + text: context.lang.settingsAccount, onTap: () {}, ), SettingsListTile( icon: FontAwesomeIcons.shieldHeart, - text: "Subscription", + text: context.lang.settingsSubscription, onTap: () {}, ), const Divider(), SettingsListTile( icon: FontAwesomeIcons.sun, - text: "Darstellung", - onTap: () {}, + text: context.lang.settingsAppearance, + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (context) { + return AppearanceView(); + })); + }, ), SettingsListTile( icon: FontAwesomeIcons.lock, - text: "Datenschutz", + text: context.lang.settingsPrivacy, onTap: () {}, ), SettingsListTile( icon: FontAwesomeIcons.bell, - text: "Benachrichtigungen", + text: context.lang.settingsNotification, onTap: () async { const AndroidNotificationDetails androidNotificationDetails = AndroidNotificationDetails( '0', - 'Messages', + 'Messages2', channelDescription: 'Messages from other users.', importance: Importance.max, - priority: Priority.high, + priority: Priority.max, ticker: 'ticker', ); const NotificationDetails notificationDetails = NotificationDetails( android: androidNotificationDetails); - await flutterLocalNotificationsPlugin.show(0, 'New message', - 'You got a new message from XX', notificationDetails, - payload: 'item x'); + await flutterLocalNotificationsPlugin.show( + 1, + 'New message from x', + 'You got a new message from XX', + notificationDetails, + payload: 'test'); }, ), const Divider(), SettingsListTile( icon: FontAwesomeIcons.circleQuestion, - text: "Help", - onTap: () {}, + text: context.lang.settingsHelp, + onTap: () { + Navigator.push(context, MaterialPageRoute( + builder: (context) { + return HelpView(); + }, + )); + }, ), - // Padding( - // padding: const EdgeInsets.all(16), - // // Glue the SettingsController to the theme selection DropdownButton. - // // - // // When a user selects a theme from the dropdown list, the - // // SettingsController is updated, which rebuilds the MaterialApp. - // child: DropdownButton( - // // Read the selected themeMode from the controller - // value: context.watch().themeMode, - // // Call the updateThemeMode method any time the user selects a theme. - // onChanged: (theme) { - // context - // .read() - // .updateThemeMode(theme); - // }, - // items: const [ - // DropdownMenuItem( - // value: ThemeMode.system, - // child: Text('System Theme'), - // ), - // DropdownMenuItem( - // value: ThemeMode.light, - // child: Text('Light Theme'), - // ), - // DropdownMenuItem( - // value: ThemeMode.dark, - // child: Text('Dark Theme'), - // ) - // ], - // ), - // ), - // ElevatedButton( - // onPressed: () { - // showLicensePage(context: context); - // }, - // child: Text('Show Licenses'), - // ), - // FilledButton.icon( - // onPressed: () async { - // await deleteLocalUserData(); - // Restart.restartApp( - // notificationTitle: 'Successfully logged out', - // notificationBody: 'Click here to open the app again', - // ); - // }, - // label: Text("Logout"), - // icon: Icon(Icons.no_accounts), - // ), ], ), ); diff --git a/pubspec.lock b/pubspec.lock index cd125d8..a1c1f24 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -850,6 +850,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + package_info_plus: + dependency: "direct main" + description: + name: package_info_plus + sha256: "67eae327b1b0faf761964a1d2e5d323c797f3799db0e85aa232db8d9e922bc35" + url: "https://pub.dev" + source: hosted + version: "8.2.1" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: "205ec83335c2ab9107bbba3f8997f9356d72ca3c715d2f038fc773d0366b4c76" + url: "https://pub.dev" + source: hosted + version: "3.1.0" path: dependency: "direct main" description: @@ -1215,6 +1231,70 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" + url: "https://pub.dev" + source: hosted + version: "6.3.1" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" + url: "https://pub.dev" + source: hosted + version: "6.3.14" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" + url: "https://pub.dev" + source: hosted + version: "6.3.2" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" + url: "https://pub.dev" + source: hosted + version: "3.2.2" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + url: "https://pub.dev" + source: hosted + version: "3.1.4" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 10b32d7..e98113b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: "Send pictures to friends in real time and be sure you are the only # Prevent accidental publishing to pub.dev. publish_to: 'none' -version: 1.0.0+1 +version: 0.0.1+1 environment: sdk: ^3.5.4 @@ -38,6 +38,7 @@ dependencies: logging: ^1.3.0 lottie: ^3.3.1 no_screenshot: ^0.3.1 + package_info_plus: ^8.2.1 path: ^1.9.0 path_provider: ^2.1.5 permission_handler: ^11.3.1 @@ -48,6 +49,7 @@ dependencies: restart_app: ^1.3.2 screenshot: ^3.0.0 sqflite_sqlcipher: ^3.1.0+1 + url_launcher: ^6.3.1 web_socket_channel: ^3.0.1 dev_dependencies: