diff --git a/settings_screen.dart b/settings_screen.dart new file mode 100644 index 00000000..61177f50 --- /dev/null +++ b/settings_screen.dart @@ -0,0 +1,470 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_settings_screens/flutter_settings_screens.dart'; +import 'package:file_picker/file_picker.dart'; +import 'dart:io'; +import 'package:otzaria/models/app_model.dart'; +import 'package:provider/provider.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +class SettingsScreen extends StatefulWidget { + @override + _SettingsScreenState createState() => _SettingsScreenState(); +} + +class _SettingsScreenState extends State { + final storage = const FlutterSecureStorage(); + String? lockCode; + bool isLocked = false; + + @override + void initState() { + super.initState(); + loadLockCode(); + } + + Future loadLockCode() async { + lockCode = await storage.read(key: 'settings_lock_code'); + if (lockCode != null) { + setState(() { + isLocked = true; + }); + } + } + + Future saveLockCode(String code) async { + await storage.write(key: 'settings_lock_code', value: code); + setState(() { + lockCode = code; + isLocked = true; + }); + } + + Future _showUnlockDialog() async { + String inputCode = ''; + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text('הזן קוד נעילה'), + content: TextField( + onChanged: (value) { + inputCode = value; + }, + decoration: InputDecoration(hintText: "הכנס קוד"), + obscureText: true, + ), + actions: [ + TextButton( + child: Text('ביטול'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: Text('אישור'), + onPressed: () { + if (inputCode == lockCode) { + setState(() { + isLocked = false; + }); + Navigator.of(context).pop(); + } else { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('קוד לא נכון')), + ); + } + }, + ), + ], + ); + }, + ); + } + + Future _showSetLockDialog() async { + String newCode = ''; + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text('הגדר קוד נעילה'), + content: TextField( + onChanged: (value) { + newCode = value; + }, + decoration: InputDecoration(hintText: "הכנס קוד חדש"), + obscureText: true, + ), + actions: [ + TextButton( + child: Text('ביטול'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: Text('שמור'), + onPressed: () { + if (newCode.isNotEmpty) { + saveLockCode(newCode); + Navigator.of(context).pop(); + } + }, + ), + ], + ); + }, + ); + } + + Future _clearLockCode() async { + await storage.delete(key: 'settings_lock_code'); + setState(() { + lockCode = null; + isLocked = false; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('הגדרות'), + ), + body: isLocked + ? Center( + child: ElevatedButton( + onPressed: _showUnlockDialog, + child: Text('הזן קוד נעילה כדי לפתוח'), + ), + ) + : ListView( + padding: EdgeInsets.all(16), + children: [ + ListTile( + title: Text('אפשרות א'), + subtitle: Text('הגדרה ראשונה'), + trailing: Switch( + value: true, + onChanged: (bool value) { + // שינוי ההגדרות + }, + ), + ), + ListTile( + title: Text('אפשרות ב'), + subtitle: Text('הגדרה שנייה'), + trailing: Switch( + value: false, + onChanged: (bool value) { + // שינוי ההגדרות + }, + ), + ), + Divider(), + ListTile( + title: Text('הגדר קוד נעילה'), + onTap: _showSetLockDialog, + ), + ListTile( + title: Text('מחק קוד נעילה'), + onTap: _clearLockCode, + ), + ], + ), + ); + } +} + +class MySettingsScreen extends StatefulWidget { + const MySettingsScreen({ + Key? key, + }) : super(key: key); + + @override + State createState() => _MySettingsScreenState(); +} + +class _MySettingsScreenState extends State { + @override + Widget build(BuildContext context) { + const Map shortcuctsList = { + 'ctrl+a': 'CTRL + A', + 'ctrl+b': "CTRL + B", + 'ctrl+c': "CTRL + C", + 'ctrl+d': "CTRL + D", + 'ctrl+e': "CTRL + E", + 'ctrl+f': "CTRL + F", + 'ctrl+g': "CTRL + G", + 'ctrl+h': "CTRL + H", + 'ctrl+i': "CTRL + I", + 'ctrl+j': "CTRL + J", + 'ctrl+k': "CTRL + K", + 'ctrl+l': "CTRL + L", + 'ctrl+m': "CTRL + M", + 'ctrl+n': "CTRL + N", + 'ctrl+o': "CTRL + O", + 'ctrl+p': "CTRL + P", + 'ctrl+q': "CTRL + Q", + 'ctrl+r': "CTRL + R", + 'ctrl+s': "CTRL + S", + 'ctrl+t': "CTRL + T", + 'ctrl+u': "CTRL + U", + 'ctrl+v': "CTRL + V", + 'ctrl+w': "CTRL + W", + 'ctrl+x': "CTRL + X", + 'ctrl+y': "CTRL + Y", + 'ctrl+z': "CTRL + Z", + 'ctrl+0': "CTRL + 0", + 'ctrl+1': "CTRL + 1", + 'ctrl+2': "CTRL + 2", + 'ctrl+3': "CTRL + 3", + 'ctrl+4': "CTRL + 4", + 'ctrl+5': "CTRL + 5", + 'ctrl+6': "CTRL + 6", + 'ctrl+7': "CTRL + 7", + 'ctrl+8': "CTRL + 8", + 'ctrl+9': "CTRL + 9", + }; + + return Scaffold( + body: Consumer(builder: (context, appModel, child) { + return Center( + child: SettingsScreen( + title: 'הגדרות', + children: [ + SettingsGroup( + titleAlignment: Alignment.centerRight, + title: 'הגדרות עיצוב', + titleTextStyle: const TextStyle(fontSize: 25), + children: [ + SwitchSettingsTile( + settingKey: 'key-dark-mode', + title: 'מצב כהה', + enabledLabel: 'מופעל', + disabledLabel: 'לא מופעל', + leading: const Icon(Icons.nightlight_round_outlined), + onChange: (value) { + appModel.isDarkMode.value = value; + }, + ), + ColorPickerSettingsTile( + title: 'צבע בסיס', + leading: const Icon(Icons.color_lens), + settingKey: 'key-swatch-color', + onChange: (p0) { + appModel.seedColor.value = p0; + }, + ), + const SliderSettingsTile( + title: 'גודל גופן התחלתי בספרים', + settingKey: 'key-font-size', + defaultValue: 30, + min: 15, + max: 60, + step: 1, + leading: Icon(Icons.format_size), + decimalPrecision: 0, + ), + DropDownSettingsTile( + title: 'גופן', + settingKey: 'key-font-family', + values: const { + 'TaameyDavidCLM': 'דוד', + 'FrankRuhlCLM': 'פרנק-רוהל', + 'TaameyAshkenaz': 'טעמי אשכנז', + 'KeterYG': 'כתר', + 'Shofar': 'שופר', + 'NotoSerifHebrew': 'נוטו', + 'Tinos': 'טינוס', + 'NotoRashiHebrew': 'רש"י', + 'Candara': 'קנדרה', + 'roboto': 'רובוטו', + 'Calibri': 'קליברי', + 'Arial': 'אריאל', + }, + selected: 'FrankRuhlCLM', + leading: const Icon(Icons.font_download_outlined), + onChange: (value) {}, + ), + SliderSettingsTile( + title: 'רוחב השוליים בצידי הטקסט', + settingKey: 'key-padding-size', + defaultValue: 10, + min: 0, + max: 500, + step: 2, + leading: const Icon(Icons.horizontal_distribute), + decimalPrecision: 0, + onChange: (p0) => appModel.paddingSize.value = p0, + ), + ], + ), + Platform.isAndroid + ? const SizedBox.shrink() + : const SettingsGroup( + titleAlignment: Alignment.centerRight, + title: "קיצורי מקשים", + titleTextStyle: const TextStyle(fontSize: 25), + children: [ + DropDownSettingsTile( + selected: 'ctrl+l', + settingKey: 'key-shortcut-open-library-browser', + title: 'ספרייה', + values: shortcuctsList, + leading: Icon(Icons.library_books), + ), + DropDownSettingsTile( + selected: 'ctrl+o', + settingKey: 'key-shortcut-open-find-ref', + title: 'איתור', + values: shortcuctsList, + leading: Icon(Icons.auto_stories_rounded), + ), + DropDownSettingsTile( + selected: 'ctrl+r', + settingKey: 'key-shortcut-open-reading-screen', + title: 'עיון', + leading: Icon(Icons.menu_book_rounded), + values: shortcuctsList, + ), + DropDownSettingsTile( + selected: 'ctrl+q', + settingKey: 'key-shortcut-open-new-search', + title: 'חלון חיפוש חדש', + leading: Icon(Icons.search), + values: shortcuctsList, + ), + DropDownSettingsTile( + selected: 'ctrl+w', + settingKey: 'key-shortcut-close-tab', + title: 'סגור ספר נוכחי', + leading: Icon(Icons.cancel), + values: shortcuctsList, + ), + DropDownSettingsTile( + selected: 'ctrl+x', + settingKey: 'key-shortcut-close-all-tabs', + title: 'סגור כל הספרים', + leading: Icon(Icons.close), + values: shortcuctsList, + ), + ]), + SettingsGroup( + title: 'הגדרות ממשק', + titleAlignment: Alignment.centerRight, + titleTextStyle: const TextStyle(fontSize: 25), + children: [ + // Platform.isAndroid + // ? const SizedBox.shrink() + // : const SwitchSettingsTile( + // settingKey: 'key-close-left-pane-on-scroll', + // title: 'סגירת תפריט הצד בעת גלילה', + // enabledLabel: + // 'עם תחילת הגלילה, ייסגר תפריט הצד אוטומטית', + // disabledLabel: 'תפריט הצד לא ייסגר אוטומטית', + // leading: Icon(Icons.arrow_back), + // ), + const SwitchSettingsTile( + settingKey: 'key-splited-view', + title: 'ברירת המחדל להצגת המפרשים', + enabledLabel: 'המפרשים יוצגו לצד הטקסט', + disabledLabel: 'המפרשים יוצגו מתחת הטקסט', + leading: Icon(Icons.vertical_split), + defaultValue: false, + ), + SwitchSettingsTile( + settingKey: 'key-use-fast-search', + title: 'חיפוש מהיר באמצעות אינדקס', + enabledLabel: + 'החיפוש יהיה מהיר יותר, נדרש ליצור אינדקס', + disabledLabel: 'החיפוש יהיה איטי יותר, לא נדרש אינדקס', + leading: Icon(Icons.search), + defaultValue: true, + onChange: (value) => context + .read() + .useFastSearch + .value = value, + ), + SwitchSettingsTile( + settingKey: 'key-show-external-books', + title: 'איתור ספרים באתרים חיצוניים', + enabledLabel: 'יוצגו גם ספרים מאתרים חיצוניים', + disabledLabel: 'יוצגו רק ספרים מספריית אוצריא', + leading: const Icon(Icons.open_in_new), + defaultValue: false, + onChange: (value) { + Provider.of(context, listen: false) + .showExternalBooks + .value = value; + Provider.of(context, listen: false) + .showHebrewBooks + .value = value; + Provider.of(context, listen: false) + .showOtzarHachochma + .value = value; + Settings.setValue('key-show-hebrew-books', value); + Settings.setValue('key-show-otzar-hachochma', value); + }, + ), + ]), + SettingsGroup( + title: 'כללי', + titleAlignment: Alignment.centerRight, + titleTextStyle: const TextStyle(fontSize: 25), + children: [ + SimpleSettingsTile( + title: 'מיקום הספרייה', + subtitle: Settings.getValue('key-library-path') ?? + 'לא קיים', + leading: const Icon(Icons.folder), + onTap: () async { + String? path = + await FilePicker.platform.getDirectoryPath(); + if (path != null) { + Settings.setValue('key-library-path', path); + setState( + () {}, + ); + } + }, + ), + const SwitchSettingsTile( + settingKey: 'key-dev-channel', + title: 'עדכון לגרסאות מפתחים', + enabledLabel: + 'קבלת עדכונים על גרסאות בדיקה, ייתכנו באגים וחוסר יציבות', + disabledLabel: 'קבלת עדכונים על גרסאות יציבות בלבד', + leading: Icon(Icons.bug_report), + ), + FutureBuilder( + future: PackageInfo.fromPlatform(), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return SimpleSettingsTile( + title: 'גרסה נוכחית', + subtitle: 'המתן..', + leading: Icon(Icons.info_rounded), + ); + } + return Align( + alignment: Alignment.centerRight, + child: SimpleSettingsTile( + title: 'גרסה נוכחית', + subtitle: snapshot.data!.version, + leading: Icon(Icons.info_rounded), + ), + ); + }) + ], + ) + ], + ), + ); + }, + ), + ); + } +}