mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 09:28:41 +00:00
start with settings view
This commit is contained in:
parent
d5bfd5944a
commit
86b6177d42
8 changed files with 394 additions and 102 deletions
|
|
@ -7,22 +7,25 @@ plugins {
|
|||
|
||||
android {
|
||||
namespace = "com.example.connect"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
// compileSdk = flutter.compileSdkVersion
|
||||
compileSdk 34
|
||||
//ndkVersion = flutter.ndkVersion
|
||||
ndkVersion = "25.1.8937393"
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
coreLibraryDesugaringEnabled true
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = 17
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "eu.twonly"
|
||||
multiDexEnabled true
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = flutter.minSdkVersion
|
||||
|
|
@ -43,3 +46,7 @@ android {
|
|||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
||||
dependencies {
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2'
|
||||
}
|
||||
BIN
android/app/src/main/res/drawable/logo.png
Normal file
BIN
android/app/src/main/res/drawable/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
135
lib/main.dart
135
lib/main.dart
|
|
@ -1,4 +1,8 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:twonly/src/providers/api/api.dart';
|
||||
import 'package:twonly/src/providers/api_provider.dart';
|
||||
|
|
@ -15,6 +19,135 @@ import 'src/app.dart';
|
|||
late DbProvider dbProvider;
|
||||
late ApiProvider apiProvider;
|
||||
|
||||
/// Streams are created so that app can respond to notification-related events
|
||||
/// since the plugin is initialized in the `main` function
|
||||
final StreamController<NotificationResponse> selectNotificationStream =
|
||||
StreamController<NotificationResponse>.broadcast();
|
||||
|
||||
const MethodChannel platform =
|
||||
MethodChannel('dexterx.dev/flutter_local_notifications_example');
|
||||
|
||||
const String portName = 'notification_send_port';
|
||||
|
||||
class ReceivedNotification {
|
||||
ReceivedNotification({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.body,
|
||||
required this.payload,
|
||||
this.data,
|
||||
});
|
||||
|
||||
final int id;
|
||||
final String? title;
|
||||
final String? body;
|
||||
final String? payload;
|
||||
final Map<String, dynamic>? data;
|
||||
}
|
||||
|
||||
String? selectedNotificationPayload;
|
||||
|
||||
/// A notification action which triggers a url launch event
|
||||
const String urlLaunchActionId = 'id_1';
|
||||
|
||||
/// A notification action which triggers a App navigation event
|
||||
const String navigationActionId = 'id_3';
|
||||
|
||||
/// Defines a iOS/MacOS notification category for text input actions.
|
||||
const String darwinNotificationCategoryText = 'textCategory';
|
||||
|
||||
/// Defines a iOS/MacOS notification category for plain actions.
|
||||
const String darwinNotificationCategoryPlain = 'plainCategory';
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void notificationTapBackground(NotificationResponse notificationResponse) {
|
||||
// ignore: avoid_print
|
||||
print('notification(${notificationResponse.id}) action tapped: '
|
||||
'${notificationResponse.actionId} with'
|
||||
' payload: ${notificationResponse.payload}');
|
||||
if (notificationResponse.input?.isNotEmpty ?? false) {
|
||||
// ignore: avoid_print
|
||||
print(
|
||||
'notification action tapped with input: ${notificationResponse.input}');
|
||||
}
|
||||
}
|
||||
|
||||
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
|
||||
FlutterLocalNotificationsPlugin();
|
||||
|
||||
int id = 0;
|
||||
|
||||
Future<void> setupPushNotification() async {
|
||||
const AndroidInitializationSettings initializationSettingsAndroid =
|
||||
AndroidInitializationSettings("logo");
|
||||
|
||||
final List<DarwinNotificationCategory> darwinNotificationCategories =
|
||||
<DarwinNotificationCategory>[
|
||||
DarwinNotificationCategory(
|
||||
darwinNotificationCategoryText,
|
||||
actions: <DarwinNotificationAction>[
|
||||
DarwinNotificationAction.text(
|
||||
'text_1',
|
||||
'Action 1',
|
||||
buttonTitle: 'Send',
|
||||
placeholder: 'Placeholder',
|
||||
),
|
||||
],
|
||||
),
|
||||
DarwinNotificationCategory(
|
||||
darwinNotificationCategoryPlain,
|
||||
actions: <DarwinNotificationAction>[
|
||||
DarwinNotificationAction.plain('id_1', 'Action 1'),
|
||||
DarwinNotificationAction.plain(
|
||||
'id_2',
|
||||
'Action 2 (destructive)',
|
||||
options: <DarwinNotificationActionOption>{
|
||||
DarwinNotificationActionOption.destructive,
|
||||
},
|
||||
),
|
||||
DarwinNotificationAction.plain(
|
||||
navigationActionId,
|
||||
'Action 3 (foreground)',
|
||||
options: <DarwinNotificationActionOption>{
|
||||
DarwinNotificationActionOption.foreground,
|
||||
},
|
||||
),
|
||||
DarwinNotificationAction.plain(
|
||||
'id_4',
|
||||
'Action 4 (auth required)',
|
||||
options: <DarwinNotificationActionOption>{
|
||||
DarwinNotificationActionOption.authenticationRequired,
|
||||
},
|
||||
),
|
||||
],
|
||||
options: <DarwinNotificationCategoryOption>{
|
||||
DarwinNotificationCategoryOption.hiddenPreviewShowTitle,
|
||||
},
|
||||
)
|
||||
];
|
||||
|
||||
/// Note: permissions aren't requested here just to demonstrate that can be
|
||||
/// done later
|
||||
final DarwinInitializationSettings initializationSettingsDarwin =
|
||||
DarwinInitializationSettings(
|
||||
requestAlertPermission: false,
|
||||
requestBadgePermission: false,
|
||||
requestSoundPermission: false,
|
||||
notificationCategories: darwinNotificationCategories,
|
||||
);
|
||||
|
||||
final InitializationSettings initializationSettings = InitializationSettings(
|
||||
android: initializationSettingsAndroid,
|
||||
iOS: initializationSettingsDarwin,
|
||||
);
|
||||
|
||||
await flutterLocalNotificationsPlugin.initialize(
|
||||
initializationSettings,
|
||||
onDidReceiveNotificationResponse: selectNotificationStream.add,
|
||||
onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
|
||||
);
|
||||
}
|
||||
|
||||
void main() async {
|
||||
final settingsController = SettingsChangeProvider();
|
||||
|
||||
|
|
@ -34,6 +167,8 @@ void main() async {
|
|||
}
|
||||
});
|
||||
|
||||
setupPushNotification();
|
||||
|
||||
await initMediaStorage();
|
||||
|
||||
dbProvider = DbProvider();
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import 'package:twonly/src/utils/misc.dart';
|
|||
import 'package:twonly/src/views/chats/chat_item_details_view.dart';
|
||||
import 'package:twonly/src/views/home_view.dart';
|
||||
import 'package:twonly/src/views/chats/media_viewer_view.dart';
|
||||
import 'package:twonly/src/views/profile_view.dart';
|
||||
import 'package:twonly/src/views/settings/settings_main_view.dart';
|
||||
import 'package:twonly/src/views/chats/search_username_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,87 +0,0 @@
|
|||
import 'package:provider/provider.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/storage.dart';
|
||||
|
||||
class ProfileView extends StatefulWidget {
|
||||
const ProfileView({super.key});
|
||||
|
||||
// final SettingsController settingsController;
|
||||
|
||||
@override
|
||||
State<ProfileView> createState() => _ProfileViewState();
|
||||
}
|
||||
|
||||
class _ProfileViewState extends State<ProfileView> {
|
||||
final Future<UserData?> _userData = getUser();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: FutureBuilder(
|
||||
future: _userData,
|
||||
builder: (context, snap) {
|
||||
if (snap.hasData) {
|
||||
return Text("Settings");
|
||||
// return Text("Hello ${snap.data!.username}!");
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
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<ThemeMode>(
|
||||
// Read the selected themeMode from the controller
|
||||
value: context.watch<SettingsChangeProvider>().themeMode,
|
||||
// Call the updateThemeMode method any time the user selects a theme.
|
||||
onChanged: (theme) {
|
||||
context.read<SettingsChangeProvider>().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),
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
211
lib/src/views/settings/settings_main_view.dart
Normal file
211
lib/src/views/settings/settings_main_view.dart
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
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/storage.dart';
|
||||
|
||||
class ProfileView extends StatefulWidget {
|
||||
const ProfileView({super.key});
|
||||
|
||||
@override
|
||||
State<ProfileView> createState() => _ProfileViewState();
|
||||
}
|
||||
|
||||
class _ProfileViewState extends State<ProfileView> {
|
||||
UserData? userData;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
initAsync();
|
||||
}
|
||||
|
||||
Future initAsync() async {
|
||||
userData = await getUser();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text("Settings"),
|
||||
),
|
||||
body: (userData == null)
|
||||
? null
|
||||
: ListView(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(30),
|
||||
child: Row(
|
||||
children: [
|
||||
InitialsAvatar(
|
||||
displayName: userData!.username,
|
||||
fontSize: 30,
|
||||
),
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
userData!.displayName,
|
||||
style: TextStyle(fontSize: 20),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
Text(
|
||||
userData!.username,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: IconButton(
|
||||
onPressed: () {},
|
||||
icon: FaIcon(FontAwesomeIcons.qrcode),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
icon: FontAwesomeIcons.user,
|
||||
text: "Konto",
|
||||
onTap: () {},
|
||||
),
|
||||
SettingsListTile(
|
||||
icon: FontAwesomeIcons.shieldHeart,
|
||||
text: "Subscription",
|
||||
onTap: () {},
|
||||
),
|
||||
const Divider(),
|
||||
SettingsListTile(
|
||||
icon: FontAwesomeIcons.sun,
|
||||
text: "Darstellung",
|
||||
onTap: () {},
|
||||
),
|
||||
SettingsListTile(
|
||||
icon: FontAwesomeIcons.lock,
|
||||
text: "Datenschutz",
|
||||
onTap: () {},
|
||||
),
|
||||
SettingsListTile(
|
||||
icon: FontAwesomeIcons.bell,
|
||||
text: "Benachrichtigungen",
|
||||
onTap: () async {
|
||||
const AndroidNotificationDetails
|
||||
androidNotificationDetails = AndroidNotificationDetails(
|
||||
'0',
|
||||
'Messages',
|
||||
channelDescription: 'Messages from other users.',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
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');
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
SettingsListTile(
|
||||
icon: FontAwesomeIcons.circleQuestion,
|
||||
text: "Help",
|
||||
onTap: () {},
|
||||
),
|
||||
// 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<ThemeMode>(
|
||||
// // Read the selected themeMode from the controller
|
||||
// value: context.watch<SettingsChangeProvider>().themeMode,
|
||||
// // Call the updateThemeMode method any time the user selects a theme.
|
||||
// onChanged: (theme) {
|
||||
// context
|
||||
// .read<SettingsChangeProvider>()
|
||||
// .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),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SettingsListTile extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String text;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const SettingsListTile({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.text,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
right: 10,
|
||||
left: 19,
|
||||
),
|
||||
child: FaIcon(
|
||||
icon,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
title: Text(text),
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
}
|
||||
32
pubspec.lock
32
pubspec.lock
|
|
@ -427,6 +427,30 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
flutter_local_notifications:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_local_notifications
|
||||
sha256: ef41ae901e7529e52934feba19ed82827b11baa67336829564aeab3129460610
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "18.0.1"
|
||||
flutter_local_notifications_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_linux
|
||||
sha256: "8f685642876742c941b29c32030f6f4f6dacd0e4eaecb3efbb187d6a3812ca01"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
flutter_local_notifications_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_platform_interface
|
||||
sha256: "6c5b83c86bf819cdb177a9247a3722067dd8cc6313827ce7c77a4b238a26fd52"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.0"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
|
@ -1167,6 +1191,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.3"
|
||||
timezone:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timezone
|
||||
sha256: ffc9d5f4d1193534ef051f9254063fa53d588609418c84299956c3db9383587d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.0"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
14
pubspec.yaml
14
pubspec.yaml
|
|
@ -20,6 +20,7 @@ dependencies:
|
|||
flutter:
|
||||
sdk: flutter
|
||||
flutter_image_compress: ^2.4.0
|
||||
flutter_local_notifications: ^18.0.1
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
flutter_secure_storage: ^9.2.2
|
||||
|
|
@ -74,13 +75,6 @@ flutter:
|
|||
|
||||
assets:
|
||||
# Add assets from the images directory to the application.
|
||||
- assets/images/
|
||||
- assets/animations/present.lottie.json
|
||||
- assets/animations/selfie2.json
|
||||
- assets/animations/messages.json
|
||||
- assets/animations/local.json
|
||||
- assets/animations/test.json
|
||||
- assets/animations/product.json
|
||||
- assets/animations/twonlies.json
|
||||
- assets/animations/rocket.json
|
||||
- assets/animations/e2e.json
|
||||
# - assets/images/
|
||||
# - assets/images/logo.jpg
|
||||
- assets/
|
||||
|
|
|
|||
Loading…
Reference in a new issue