import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; import 'package:settings_ui/settings_ui.dart'; import 'package:simplecloudnotifier/git_stamp/git_stamp.dart'; import 'package:simplecloudnotifier/pages/settings/settings_number_modal.dart'; import 'package:simplecloudnotifier/pages/settings/settings_picker_screen.dart'; import 'package:simplecloudnotifier/state/app_settings.dart'; import 'package:simplecloudnotifier/state/app_auth.dart'; import 'package:simplecloudnotifier/state/app_theme.dart'; import 'package:simplecloudnotifier/state/globals.dart'; import 'package:simplecloudnotifier/utils/navi.dart'; import 'package:simplecloudnotifier/utils/toaster.dart'; class SettingsRootPage extends StatefulWidget { const SettingsRootPage({super.key, required bool isVisiblePage}); @override State createState() => _SettingsRootPageState(); } class _SettingsRootPageState extends State { int _multiClickCounter = 0; DateTime? _lastClickTime = null; @override Widget build(BuildContext context) { final cfg = Provider.of(context); final thm = Provider.of(context); return SettingsList( platform: PlatformUtils.detectPlatform(context), contentPadding: EdgeInsets.fromLTRB(0, 0, 0, 24), sections: [ SettingsSection( title: Text('General'), tiles: [ SettingsTile.navigation( leading: Icon(thm.darkMode ? FontAwesomeIcons.solidMoon : FontAwesomeIcons.solidSun), title: Text('Theme'), value: Text(thm.darkMode ? 'Dark' : 'Light'), onPressed: (_) => thm.switchDarkMode(), ), SettingsTile.navigation( leading: Icon(FontAwesomeIcons.solidSquare, color: thm.color.value), title: Text('Color'), value: Text(thm.color.displayStr), onPressed: (_) => Navi.push( context, () => SettingsPickerScreen( title: 'Color', initialValue: thm.color, values: ThemeColor.values, icons: (v) => Icon(FontAwesomeIcons.solidSquare, color: v.value), onValueChanged: (value) => AppTheme().setColor(value), ), ), ), SettingsTile.navigation( leading: Icon(FontAwesomeIcons.solidLineColumns), title: Text('Message Preview Lines'), value: Text("${cfg.messagePreviewLength}"), onPressed: (_) { SettingsNumberModal.show( context, title: 'Message Preview Lines', currentValue: cfg.messagePreviewLength, minValue: 1, maxValue: 32, onValueChanged: (value) => AppSettings().update((p) => p.messagePreviewLength = value), ); }, ), if (Platform.isAndroid) SettingsTile.switchTile( initialValue: cfg.groupNotifications, leading: Icon(FontAwesomeIcons.solidLayerGroup), title: Text('Group notifications together'), onToggle: (value) => AppSettings().update((p) => p.groupNotifications = !p.groupNotifications), ), SettingsTile.navigation( leading: Icon(FontAwesomeIcons.solidCalendarDays), title: Text('Date Format'), value: Text(cfg.dateFormat.displayStr), onPressed: (_) => Navi.push( context, () => SettingsPickerScreen( title: 'Date Format', initialValue: cfg.dateFormat, values: AppSettingsDateFormat.values, onValueChanged: (value) => AppSettings().update((p) => p.dateFormat = value), ), ), ), ], ), SettingsSection( title: Text('Priority 0 (Low)'), tiles: _buildNotificationTiles(context, cfg, 0), ), SettingsSection( title: Text('Priority 1 (Normal)'), tiles: _buildNotificationTiles(context, cfg, 1), ), SettingsSection( title: Text('Priority 2 (High)'), tiles: _buildNotificationTiles(context, cfg, 2), ), SettingsSection( title: Text('Advanced Settings'), tiles: [ if (cfg.devMode) SettingsTile.switchTile( initialValue: cfg.showDebugButton, leading: Icon(FontAwesomeIcons.solidSpiderBlackWidow), title: Text('Debug Button anzeigen'), onToggle: (value) => AppSettings().update((p) => p.showDebugButton = !p.showDebugButton), ), SettingsTile.navigation( leading: Icon(FontAwesomeIcons.solidList), title: Text('Page Size (Messages)'), value: Text("${cfg.messagePageSize}"), onPressed: (_) { SettingsNumberModal.show( context, title: 'Page Size (Messages)', currentValue: cfg.messagePageSize, minValue: 1, maxValue: 2048, onValueChanged: (value) => AppSettings().update((p) => p.messagePageSize = value), ); }, ), SettingsTile.switchTile( initialValue: cfg.backgroundRefreshMessageListOnPop, leading: Icon(FontAwesomeIcons.solidPageCaretDown), title: Text('Refresh messages on page navigation'), onToggle: (value) => AppSettings().update((p) => p.backgroundRefreshMessageListOnPop = !p.backgroundRefreshMessageListOnPop), ), SettingsTile.switchTile( initialValue: cfg.alwaysBackgroundRefreshMessageListOnLifecycleResume, leading: Icon(FontAwesomeIcons.solidRecycle), title: Text('Refresh messages on app resume'), onToggle: (value) => AppSettings().update((p) => p.alwaysBackgroundRefreshMessageListOnLifecycleResume = !p.alwaysBackgroundRefreshMessageListOnLifecycleResume), ), ], ), SettingsSection( title: Text('About'), tiles: [ SettingsTile.navigation( leading: Icon(FontAwesomeIcons.solidCodeCommit), title: Text('Version'), value: Text(Globals().version), onPressed: (cfg.devMode) ? null : (context) { if (_lastClickTime == null || DateTime.now().difference(_lastClickTime!).inSeconds > 1) _multiClickCounter = 0; _multiClickCounter++; _lastClickTime = DateTime.now(); if (_multiClickCounter >= 12) { Toaster.info("Debug", "Developer mode enabled"); AppSettings().update((p) { p.devMode = true; p.showDebugButton = true; }); } }, ), SettingsTile.navigation( leading: Icon(FontAwesomeIcons.solidCodeBranch), title: Text('Build'), value: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(GitStamp.sha.substring(0, 7) + ' +' + Globals().buildNumber), Text("( " + cfg.dateFormat.dateFormat().format(DateTime.parse(GitStamp.buildDateTime).toLocal()) + " )", style: TextStyle(fontStyle: FontStyle.italic)), ], ), onPressed: (context) => _clipboardCopy(GitStamp.sha), ), SettingsTile.navigation( leading: Icon(FontAwesomeIcons.solidBell), title: Text('FCM Token'), value: Text(AppAuth().getToken()), onPressed: (context) => _clipboardCopy(AppAuth().getToken()), ), ], ), ], ); } void _clipboardCopy(String v) { Clipboard.setData(new ClipboardData(text: v)); Toaster.info("Clipboard", 'Copied to Clipboard'); print('================= [CLIPBOARD] =================\n${v}\n================= [/CLIPBOARD] ================='); } List _buildNotificationTiles(BuildContext context, AppSettings cfg, int prio) { final ncf = AppSettings().getNotificationSettings(prio); return [ SettingsTile.switchTile( initialValue: ncf.enableLights, leading: Icon(FontAwesomeIcons.solidLightbulb), title: Text('Enable Lights'), onToggle: (value) => AppSettings().updateNotification(prio, (p) => p.withEnableLights(!p.enableLights)), ), SettingsTile.switchTile( initialValue: ncf.enableVibration, leading: Icon(FontAwesomeIcons.solidShutters), title: Text('Enable Vibration'), onToggle: (value) => AppSettings().updateNotification(prio, (p) => p.withEnableVibration(!p.enableVibration)), ), SettingsTile.navigation( leading: Icon(FontAwesomeIcons.solidWaveform), title: Text('Notification Sound'), value: Text(ncf.sound ?? '(Default)'), onPressed: (context) => {/*TODO*/}, ), SettingsTile.switchTile( initialValue: ncf.playSound, leading: Icon(FontAwesomeIcons.solidVolume), title: Text('Play Sound'), onToggle: (value) => AppSettings().updateNotification(prio, (p) => p.withPlaySound(!p.playSound)), ), SettingsTile.switchTile( initialValue: ncf.silent, leading: Icon(FontAwesomeIcons.solidVolumeSlash), title: Text('Silent'), onToggle: (value) => AppSettings().updateNotification(prio, (p) => p.withSilent(!p.silent)), ), SettingsTile.navigation( leading: Icon(FontAwesomeIcons.solidStopwatch20), title: Text('Auto Timeout'), value: Text((ncf.timeoutAfter != null) ? "${ncf.timeoutAfter} sec" : "(None)"), onPressed: (context) => {/*TODO*/}, ), ]; } }