saminsohag

improved gpt_markdown example app

import 'dart:io';
import 'package:desktop_drop/desktop_drop.dart';
import 'package:flutter/material.dart';
import 'package:gpt_markdown/gpt_markdown.dart';
import 'package:flutter_math_fork/flutter_math.dart';
import 'package:watcher/watcher.dart';
//
void main() {
... ... @@ -113,6 +117,35 @@ You can also use LaTeX for mathematical expressions. Here's an example:
Markdown and LaTeX can be powerful tools for formatting text and mathematical expressions in your Flutter app. If you have any questions or need further assistance, feel free to ask!
''',
);
File? file;
loadContent() async {
File? file = this.file;
if (file == null) {
return;
}
String content = await file.readAsString();
_controller.text = content;
}
updateContent(String contents) async {
//
await file?.writeAsString(contents);
}
load() async {
await loadContent();
String? path = file?.path;
if (path == null) {
return;
}
FileWatcher(path).events.listen((details) {
loadContent();
});
}
bool writingMod = true;
@override
Widget build(BuildContext context) {
return Scaffold(
... ... @@ -131,173 +164,196 @@ Markdown and LaTeX can be powerful tools for formatting text and mathematical ex
onPressed: widget.onPressed,
icon: const Icon(Icons.sunny),
),
IconButton(
onPressed: () => setState(() {
writingMod = !writingMod;
}),
icon: const Icon(Icons.arrow_drop_down),
),
],
),
body: Stack(
children: [
Column(
children: [
Expanded(
child: ListView(
children: [
AnimatedBuilder(
animation: _controller,
builder: (context, _) {
return Material(
// color: Theme.of(context).colorScheme.surfaceVariant,
shape: RoundedRectangleBorder(
side: BorderSide(
width: 1,
color: Theme.of(context).colorScheme.outline),
),
child: LayoutBuilder(builder: (context, constraints) {
return Theme(
data: Theme.of(context),
// .copyWith(
// textTheme: const TextTheme(
// // For H1.
// headlineLarge: TextStyle(fontSize: 55),
// // For H2.
// headlineMedium: TextStyle(fontSize: 45),
// // For H3.
// headlineSmall: TextStyle(fontSize: 35),
// // For H4.
// titleLarge: TextStyle(fontSize: 25),
// // For H5.
// titleMedium: TextStyle(fontSize: 15),
// // For H6.
// titleSmall: TextStyle(fontSize: 10),
// ),
// ),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TexMarkdown(
_controller.text,
textDirection: _direction,
onLinkTab: (url, title) {
debugPrint(url);
debugPrint(title);
},
// maxLines: 7,
// overflow: TextOverflow.ellipsis,
textAlign: TextAlign.justify,
// textScaler: const TextScaler.linear(1.3),
textScaler: const TextScaler.linear(1),
style: const TextStyle(
// Regular text font size here.
fontSize: 15,
),
latexWorkaround: (tex) {
List<String> stack = [];
tex = tex.splitMapJoin(
RegExp(r"\\text\{|\{|\}|\_"),
onMatch: (p) {
String input = p[0] ?? "";
if (input == r"\text{") {
stack.add(input);
}
if (stack.isNotEmpty) {
if (input == r"{") {
body: DropTarget(
onDragDone: (details) {
var files = details.files;
if (files.length != 1) {
return;
}
var file = files[0];
String path = file.path;
this.file = File(path);
load();
},
child: Stack(
children: [
Column(
children: [
Expanded(
child: ListView(
children: [
AnimatedBuilder(
animation: _controller,
builder: (context, _) {
return Material(
// color: Theme.of(context).colorScheme.surfaceVariant,
shape: RoundedRectangleBorder(
side: BorderSide(
width: 1,
color: Theme.of(context).colorScheme.outline),
),
child:
LayoutBuilder(builder: (context, constraints) {
return Theme(
data: Theme.of(context),
// .copyWith(
// textTheme: const TextTheme(
// // For H1.
// headlineLarge: TextStyle(fontSize: 55),
// // For H2.
// headlineMedium: TextStyle(fontSize: 45),
// // For H3.
// headlineSmall: TextStyle(fontSize: 35),
// // For H4.
// titleLarge: TextStyle(fontSize: 25),
// // For H5.
// titleMedium: TextStyle(fontSize: 15),
// // For H6.
// titleSmall: TextStyle(fontSize: 10),
// ),
// ),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TexMarkdown(
_controller.text,
textDirection: _direction,
onLinkTab: (url, title) {
debugPrint(url);
debugPrint(title);
},
// maxLines: 7,
// overflow: TextOverflow.ellipsis,
textAlign: TextAlign.justify,
// textScaler: const TextScaler.linear(1.3),
textScaler: const TextScaler.linear(1),
style: const TextStyle(
// Regular text font size here.
fontSize: 15,
),
latexWorkaround: (tex) {
List<String> stack = [];
tex = tex.splitMapJoin(
RegExp(r"\\text\{|\{|\}|\_"),
onMatch: (p) {
String input = p[0] ?? "";
if (input == r"\text{") {
stack.add(input);
}
if (input == r"}") {
stack.removeLast();
}
if (input == r"_") {
return r"\_";
if (stack.isNotEmpty) {
if (input == r"{") {
stack.add(input);
}
if (input == r"}") {
stack.removeLast();
}
if (input == r"_") {
return r"\_";
}
}
}
return input;
},
);
return tex.replaceAllMapped(
RegExp(r"align\*"),
(match) => "aligned");
},
latexBuilder:
(contex, tex, textStyle, inline) {
if (tex.contains(r"\begin{tabular}")) {
// return table.
String tableString = "|${(RegExp(
r"^\\begin\{tabular\}\{.*?\}(.*?)\\end\{tabular\}$",
multiLine: true,
dotAll: true,
).firstMatch(tex)?[1] ?? "").trim()}|";
tableString = tableString
.replaceAll(r"\\", "|\n|")
.replaceAll(r"\hline", "")
.replaceAll(RegExp(r"(?<!\\)&"), "|");
var tableStringList = tableString
.split("\n")
..insert(1, "|---|");
tableString = tableStringList.join("\n");
return TexMarkdown(tableString);
}
var controller = ScrollController();
Widget child = Math.tex(
tex,
textStyle: textStyle,
);
if (!inline) {
child = Padding(
padding: const EdgeInsets.all(0.0),
child: Material(
color: Theme.of(context)
.colorScheme
.onInverseSurface,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Scrollbar(
controller: controller,
child: SingleChildScrollView(
return input;
},
);
return tex.replaceAllMapped(
RegExp(r"align\*"),
(match) => "aligned");
},
latexBuilder:
(contex, tex, textStyle, inline) {
if (tex.contains(r"\begin{tabular}")) {
// return table.
String tableString = "|${(RegExp(
r"^\\begin\{tabular\}\{.*?\}(.*?)\\end\{tabular\}$",
multiLine: true,
dotAll: true,
).firstMatch(tex)?[1] ?? "").trim()}|";
tableString = tableString
.replaceAll(r"\\", "|\n|")
.replaceAll(r"\hline", "")
.replaceAll(
RegExp(r"(?<!\\)&"), "|");
var tableStringList = tableString
.split("\n")
..insert(1, "|---|");
tableString =
tableStringList.join("\n");
return TexMarkdown(tableString);
}
var controller = ScrollController();
Widget child = Math.tex(
tex,
textStyle: textStyle,
);
if (!inline) {
child = Padding(
padding: const EdgeInsets.all(0.0),
child: Material(
color: Theme.of(context)
.colorScheme
.onInverseSurface,
child: Padding(
padding:
const EdgeInsets.all(8.0),
child: Scrollbar(
controller: controller,
scrollDirection:
Axis.horizontal,
child: Math.tex(
tex,
textStyle: textStyle,
child: SingleChildScrollView(
controller: controller,
scrollDirection:
Axis.horizontal,
child: Math.tex(
tex,
textStyle: textStyle,
),
),
),
),
),
),
);
}
child = InkWell(
onTap: () {
debugPrint("Hello world");
},
child: child,
);
}
child = InkWell(
onTap: () {
debugPrint("Hello world");
},
child: child,
);
return child;
},
return child;
},
),
),
),
// child: const Text("Hello"),
);
}),
);
},
),
],
),
),
ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 200),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
label: Text("Type here:")),
maxLines: null,
controller: _controller,
// child: const Text("Hello"),
);
}),
);
},
),
],
),
),
),
],
),
],
if (writingMod)
ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 200),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
label: Text("Type here:")),
maxLines: null,
controller: _controller,
),
),
),
],
),
],
),
),
);
}
... ...
... ... @@ -6,10 +6,14 @@
#include "generated_plugin_registrant.h"
#include <desktop_drop/desktop_drop_plugin.h>
#include <printing/printing_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) desktop_drop_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin");
desktop_drop_plugin_register_with_registrar(desktop_drop_registrar);
g_autoptr(FlPluginRegistrar) printing_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "PrintingPlugin");
printing_plugin_register_with_registrar(printing_registrar);
... ...
... ... @@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
desktop_drop
printing
url_launcher_linux
)
... ...
... ... @@ -5,11 +5,13 @@
import FlutterMacOS
import Foundation
import desktop_drop
import path_provider_foundation
import printing
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
PrintingPlugin.register(with: registry.registrar(forPlugin: "PrintingPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
... ...
PODS:
- desktop_drop (0.0.1):
- FlutterMacOS
- FlutterMacOS (1.0.0)
- path_provider_foundation (0.0.1):
- Flutter
... ... @@ -9,12 +11,15 @@ PODS:
- FlutterMacOS
DEPENDENCIES:
- desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- printing (from `Flutter/ephemeral/.symlinks/plugins/printing/macos`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
EXTERNAL SOURCES:
desktop_drop:
:path: Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos
FlutterMacOS:
:path: Flutter/ephemeral
path_provider_foundation:
... ... @@ -25,6 +30,7 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
SPEC CHECKSUMS:
desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
printing: 1dd6a1fce2209ec240698e2439a4adbb9b427637
... ...
import Cocoa
import FlutterMacOS
@NSApplicationMain
@main
class AppDelegate: FlutterAppDelegate {
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
... ...
... ... @@ -8,5 +8,7 @@
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>
... ...
... ... @@ -4,5 +4,7 @@
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>
... ...
... ... @@ -97,6 +97,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.8"
desktop_drop:
dependency: "direct main"
description:
name: desktop_drop
sha256: d55a010fe46c8e8fcff4ea4b451a9ff84a162217bdb3b2a0aa1479776205e15d
url: "https://pub.dev"
source: hosted
version: "0.4.4"
fake_async:
dependency: transitive
description:
... ... @@ -117,10 +125,10 @@ packages:
dependency: "direct main"
description:
name: file_picker
sha256: "824f5b9f389bfc4dddac3dea76cd70c51092d9dff0b2ece7ef4f53db8547d258"
sha256: "825aec673606875c33cd8d3c4083f1a3c3999015a84178b317b7ef396b7384f3"
url: "https://pub.dev"
source: hosted
version: "8.0.6"
version: "8.0.7"
flutter:
dependency: "direct main"
description: flutter
... ... @@ -211,18 +219,18 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev"
source: hosted
version: "10.0.4"
version: "10.0.5"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev"
source: hosted
version: "3.0.3"
version: "3.0.5"
leak_tracker_testing:
dependency: transitive
description:
... ... @@ -251,18 +259,18 @@ packages:
dependency: transitive
description:
name: material_color_utilities
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
version: "0.8.0"
version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev"
source: hosted
version: "1.12.0"
version: "1.15.0"
nested:
dependency: transitive
description:
... ... @@ -363,10 +371,10 @@ packages:
dependency: transitive
description:
name: permission_handler_android
sha256: b29a799ca03be9f999aa6c39f7de5209482d638e6f857f6b93b0875c618b7e54
sha256: eaf2a1ec4472775451e88ca6a7b86559ef2f1d1ed903942ed135e38ea0097dca
url: "https://pub.dev"
source: hosted
version: "12.0.7"
version: "12.0.8"
permission_handler_apple:
dependency: transitive
description:
... ... @@ -387,10 +395,10 @@ packages:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20"
sha256: fe0ffe274d665be8e34f9c59705441a7d248edebbe5d9e3ec2665f88b79358ea
url: "https://pub.dev"
source: hosted
version: "4.2.1"
version: "4.2.2"
permission_handler_windows:
dependency: transitive
description:
... ... @@ -496,10 +504,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev"
source: hosted
version: "0.7.0"
version: "0.7.2"
tuple:
dependency: transitive
description:
... ... @@ -568,10 +576,10 @@ packages:
dependency: transitive
description:
name: url_launcher_web
sha256: a36e2d7981122fa185006b216eb6b5b97ede3f9a54b7a511bc966971ab98d049
sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
version: "2.3.3"
url_launcher_windows:
dependency: transitive
description:
... ... @@ -616,10 +624,18 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
url: "https://pub.dev"
source: hosted
version: "14.2.4"
watcher:
dependency: "direct main"
description:
name: watcher
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
url: "https://pub.dev"
source: hosted
version: "14.2.1"
version: "1.1.0"
web:
dependency: transitive
description:
... ...
... ... @@ -21,6 +21,8 @@ dependencies:
permission_handler: ^11.3.1
file_picker: ^8.0.6
flutter_math_fork: ^0.7.2
watcher: ^1.1.0
desktop_drop: ^0.4.4
dev_dependencies:
flutter_test:
... ...
... ... @@ -6,11 +6,14 @@
#include "generated_plugin_registrant.h"
#include <desktop_drop/desktop_drop_plugin.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
#include <printing/printing_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
DesktopDropPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("DesktopDropPlugin"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
PrintingPluginRegisterWithRegistrar(
... ...
... ... @@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
desktop_drop
permission_handler_windows
printing
url_launcher_windows
... ...