-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix tab view and browser, add settings support
- Loading branch information
Showing
10 changed files
with
592 additions
and
228 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,10 @@ | ||
V add multi tabs support | ||
V save tab state | ||
close the current tab | ||
V change markdown loading to async | ||
V add book title search | ||
move tabView to be home page | ||
add setting screen | ||
add option for styling the markdown | ||
up folder in brwser | ||
use html2markdown | ||
add option for themes for the markdown | ||
add search in markdown content | ||
add PDF support | ||
add search for reference | ||
deploy with msix for sharing | ||
להוסיף את הרמה האחרונה של כותרת לכל הרמות מעל 4 | ||
להחזיר ספרים שנמחקו | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
extensions: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
import 'package:flutter_settings_screen_ex/flutter_settings_screen_ex.dart'; | ||
import 'package:universal_io/io.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:markdown_widget/markdown_widget.dart'; | ||
import 'custom_node.dart'; | ||
import 'main.dart'; | ||
import 'dart:math'; | ||
|
||
class MarkdownTabView extends StatefulWidget { | ||
|
||
|
||
const MarkdownTabView({Key? key,}) | ||
: super(key: key); | ||
|
||
@override | ||
MarkdownTabViewState createState() => MarkdownTabViewState(); | ||
} | ||
|
||
class MarkdownTabViewState extends State<MarkdownTabView> with TickerProviderStateMixin{ | ||
int selectedIndex = 0; | ||
List<File> openedFiles = []; | ||
late TabController tabController; | ||
|
||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
tabController = TabController(length: openedFiles.length, vsync:this); | ||
|
||
} | ||
|
||
|
||
void enlargeText() { | ||
setState(() { | ||
Settings.setValue<double>( 'key-font-size',min(Settings.getValue<double>('key-font-size')!+5,50.0)); | ||
|
||
}); | ||
|
||
} | ||
|
||
void enSmallText() { | ||
setState(() { | ||
Settings.setValue<double>( 'key-font-size',max(Settings.getValue<double>('key-font-size')!-5,15.0)); | ||
|
||
}); | ||
|
||
} | ||
|
||
void closelastTab() { | ||
setState(() { | ||
if (openedFiles.isNotEmpty) { | ||
openedFiles.removeAt(tabController.index); | ||
|
||
tabController = TabController(length: openedFiles.length, vsync:this,initialIndex: max(0,tabController.index-1)); | ||
} | ||
}); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar( | ||
title: const Center(child: Text('אוצריא')), | ||
actions: [ | ||
|
||
IconButton( | ||
icon: const Icon( | ||
Icons.font_download_outlined, | ||
|
||
), | ||
tooltip: 'הגדל טקסט', | ||
onPressed: enlargeText, | ||
), | ||
IconButton( | ||
icon: const Icon( | ||
Icons.font_download_off_outlined, | ||
|
||
), | ||
tooltip: 'הקטן טקסט', | ||
onPressed: enSmallText, | ||
), | ||
IconButton( | ||
icon: const Icon(Icons.close), | ||
tooltip: 'סגור ספר פתוח', | ||
onPressed: closelastTab, | ||
), | ||
], | ||
bottom: TabBar( | ||
controller: tabController, | ||
tabs: openedFiles | ||
.map((file) => Tab(text: file.path.split('/').last)) | ||
.toList(), | ||
), | ||
), | ||
body: Row(children: [ | ||
NavigationRail( | ||
labelType: NavigationRailLabelType.all, | ||
destinations: const [ | ||
NavigationRailDestination( | ||
icon: Icon(Icons.library_books), | ||
label: Text('ספריה'), | ||
), | ||
NavigationRailDestination( | ||
icon: Icon(Icons.search), | ||
label: Text('חיפוש'), | ||
), | ||
NavigationRailDestination( | ||
icon: Icon(Icons.settings), | ||
label: Text('הגדרות'), | ||
), | ||
], | ||
selectedIndex: selectedIndex, | ||
onDestinationSelected: (int index) { | ||
setState(() { | ||
selectedIndex = index; | ||
switch (index) { | ||
case 0: | ||
_openSelectedFile('browser'); | ||
case 1: | ||
_openSelectedFile('search'); | ||
case 2: | ||
Navigator.pushNamed(context, '/settings'); | ||
} | ||
}); | ||
}), | ||
Expanded( | ||
child: TabBarView( | ||
controller: tabController, | ||
children: openedFiles.map((file) { | ||
return BookViewer( | ||
file: file, | ||
); | ||
}).toList()), | ||
), | ||
]), | ||
); | ||
} | ||
|
||
void _openSelectedFile(String how) async { | ||
File? selectedFile; | ||
|
||
if (how == 'browser') { | ||
selectedFile = await Navigator.push( | ||
context, | ||
MaterialPageRoute( | ||
builder: (context) => DirectoryBrowser( | ||
directory: Directory('./אוצריא'), | ||
)), | ||
); | ||
} else if (how == 'search') { | ||
selectedFile = await Navigator.push( | ||
context, | ||
MaterialPageRoute(builder: (context) => BookSearchScreen()), | ||
); | ||
} | ||
if (selectedFile != null) { | ||
setState(() { | ||
openedFiles.add(selectedFile!); | ||
tabController = TabController(length: openedFiles.length, vsync:this,initialIndex: openedFiles.length-1); | ||
}); | ||
} | ||
} | ||
} | ||
|
||
|
||
class BookViewer extends StatefulWidget { | ||
final File file; | ||
late Future<String> data; | ||
|
||
BookViewer({Key? key, required this.file}) : super(key: key) { | ||
data = file.readAsString(); | ||
} | ||
|
||
@override | ||
State<BookViewer> createState() => _BookViewerState(); | ||
} | ||
|
||
class _BookViewerState extends State<BookViewer> with AutomaticKeepAliveClientMixin<BookViewer> { | ||
//use value notifier | ||
|
||
ValueNotifier textFontSize = ValueNotifier(Settings.getValue('key-font-size')); | ||
|
||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
} | ||
final tocController = TocController(); | ||
|
||
Widget buildTocWidget() => TocWidget(controller: tocController); | ||
|
||
Widget buildMarkdown() => FutureBuilder( | ||
future: widget.data.then((value) => value), | ||
builder: (context, snapshot) { | ||
if (snapshot.connectionState == ConnectionState.done) { | ||
if (snapshot.hasError) { | ||
return Center(child: Text('Error: ${snapshot.error}')); | ||
} | ||
|
||
if (snapshot.hasData) { | ||
return ValueListenableBuilder( | ||
key: PageStorageKey<String>(widget.key.toString()), | ||
valueListenable: textFontSize, | ||
builder: (context, value, child) => | ||
MarkdownWidget( | ||
padding: const EdgeInsets.all(50), | ||
data: snapshot.data!, | ||
tocController: tocController, | ||
config: MarkdownConfig(configs: [ | ||
PConfig( | ||
textStyle: TextStyle( | ||
fontSize: Settings.getValue('key-font-size'), | ||
fontFamily: Settings.getValue('key-font-family'), | ||
|
||
)), | ||
]), | ||
markdownGenerator: MarkdownGenerator( | ||
textGenerator: (node, config, visitor) => | ||
CustomTextNode(node.textContent, config, visitor)))); | ||
} | ||
} | ||
return const Center(child: CircularProgressIndicator( | ||
)); | ||
}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
drawer: Drawer(child: buildTocWidget()), | ||
appBar: AppBar( | ||
actions: [], | ||
title: Text('${widget.file.path.split('/').last}'), | ||
), | ||
body: buildMarkdown(), | ||
); | ||
} | ||
@override | ||
bool get wantKeepAlive => true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import 'package:flutter/foundation.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:hive/hive.dart'; | ||
import 'package:path_provider/path_provider.dart'; | ||
import 'package:flutter_settings_screen_ex/flutter_settings_screen_ex.dart'; | ||
|
||
|
||
/// A cache access provider class for shared preferences using Hive library | ||
class HiveCache extends CacheProvider { | ||
Box? _preferences; | ||
final String keyName = 'app_preferences'; | ||
|
||
@override | ||
Future<void> init() async { | ||
WidgetsFlutterBinding.ensureInitialized(); | ||
if (!kIsWeb) { | ||
final defaultDirectory = await getApplicationDocumentsDirectory(); | ||
Hive.init(defaultDirectory.path); | ||
} | ||
if (Hive.isBoxOpen(keyName)) { | ||
_preferences = Hive.box(keyName); | ||
} else { | ||
_preferences = await Hive.openBox(keyName); | ||
} | ||
} | ||
|
||
Set get keys => getKeys(); | ||
|
||
@override | ||
bool? getBool(String key, {bool? defaultValue}) { | ||
return _preferences?.get(key); | ||
} | ||
|
||
@override | ||
double? getDouble(String key, {double? defaultValue}) { | ||
return _preferences?.get(key); | ||
} | ||
|
||
@override | ||
int? getInt(String key, {int? defaultValue}) { | ||
return _preferences?.get(key); | ||
} | ||
|
||
@override | ||
String? getString(String key, {String? defaultValue}) { | ||
return _preferences?.get(key); | ||
} | ||
|
||
@override | ||
Future<void> setBool(String key, bool? value) async { | ||
await _preferences?.put(key, value); | ||
} | ||
|
||
@override | ||
Future<void> setDouble(String key, double? value) async { | ||
await _preferences?.put(key, value); | ||
} | ||
|
||
@override | ||
Future<void> setInt(String key, int? value) async { | ||
await _preferences?.put(key, value); | ||
} | ||
|
||
@override | ||
Future<void> setString(String key, String? value) async { | ||
await _preferences?.put(key, value); | ||
} | ||
|
||
@override | ||
Future<void> setObject<T>(String key, T? value) async { | ||
await _preferences?.put(key, value); | ||
} | ||
|
||
@override | ||
bool containsKey(String key) { | ||
return _preferences?.containsKey(key) ?? false; | ||
} | ||
|
||
@override | ||
Set getKeys() { | ||
return _preferences?.keys.toSet() ?? {}; | ||
} | ||
|
||
@override | ||
Future<void> remove(String key) async { | ||
if (containsKey(key)) { | ||
await _preferences?.delete(key); | ||
} | ||
} | ||
|
||
@override | ||
Future<void> removeAll() async { | ||
final keys = getKeys(); | ||
await _preferences?.deleteAll(keys); | ||
} | ||
|
||
@override | ||
T? getValue<T>(String key, {T? defaultValue}) { | ||
var value = _preferences?.get(key); | ||
if (value is T) { | ||
return value; | ||
} | ||
return defaultValue; | ||
} | ||
} |
Oops, something went wrong.