@ -0,0 +1,17 @@ |
||||
--- |
||||
name: Issue template |
||||
about: Common things to fill |
||||
title: "[Web] or [Mobile] or [Desktop]" |
||||
labels: '' |
||||
assignees: '' |
||||
|
||||
--- |
||||
|
||||
My issue is about [Web] |
||||
My issue is about [Mobile] |
||||
My issue is about [Desktop] |
||||
|
||||
I have tried running `example` directory successfully before creating an issue here. |
||||
|
||||
Please note that we are using <b>latest</b> flutter version in stable channel on branch master. If you are using beta or master channel, or you are not using <b>latest</b> flutter version in stable channel, you may experience error. |
||||
|
@ -1,81 +1,251 @@ |
||||
## [0.0.1] |
||||
## [1.9.1] |
||||
* Cursor jumps to the most appropriate offset to display selection. |
||||
|
||||
* Rich text editor based on Quill Delta. |
||||
## [1.9.0] |
||||
* Support inline image. |
||||
|
||||
## [0.0.2] |
||||
* Support image upload and launch url in read-only mode. |
||||
## [1.8.3] |
||||
* Updated quill_delta. |
||||
|
||||
## [0.0.3] |
||||
* Update home page meta data. |
||||
## [1.8.2] |
||||
* Support mobile image alignment. |
||||
|
||||
## [0.0.4] |
||||
* Update example. |
||||
## [1.8.1] |
||||
* Support mobile custom size image. |
||||
|
||||
## [0.0.5] |
||||
* Update example. |
||||
## [1.8.0] |
||||
* Support entering link for image/video. |
||||
|
||||
## [0.0.6] |
||||
* More toolbar functionality. |
||||
## [1.7.3] |
||||
* Bumps photo_view version. |
||||
|
||||
## [0.0.7] |
||||
* Handle multiple image inserts. |
||||
## [1.7.2] |
||||
* Fix static analysis error. |
||||
|
||||
## [0.0.8] |
||||
* Fix launching url. |
||||
## [1.7.1] |
||||
* Support Youtube video. |
||||
|
||||
## [0.0.9] |
||||
* Handle rgba color. |
||||
## [1.7.0] |
||||
* Support video. |
||||
|
||||
## [0.1.0] |
||||
* Fix insert image. |
||||
## [1.6.4] |
||||
* Bug fix for clear format button. |
||||
|
||||
## [0.1.1] |
||||
* Fix cursor issue when undo. |
||||
## [1.6.3] |
||||
* Fixed dragging right handle scrolling issue. |
||||
|
||||
## [0.1.2] |
||||
* Handle more text colors. |
||||
## [1.6.2] |
||||
* Fixed the position of the selection status drag handle. |
||||
|
||||
## [0.1.3] |
||||
* Handle cursor position change when undo/redo. |
||||
## [1.6.1] |
||||
* Upgrade image_picker and flutter_colorpicker. |
||||
|
||||
## [0.1.4] |
||||
* Handle url with trailing spaces. |
||||
## [1.6.0] |
||||
* Support Multi Row Toolbar. |
||||
|
||||
## [0.1.5] |
||||
* Support text alignment. |
||||
## [1.5.0] |
||||
* Remove file_picker dependency. |
||||
|
||||
## [0.1.6] |
||||
* Fix getExtentEndpointForSelection. |
||||
## [1.4.1] |
||||
* Remove filesystem_picker dependency. |
||||
|
||||
## [0.1.7] |
||||
* Support checked/unchecked list. |
||||
## [1.4.0] |
||||
* Remove path_provider dependency. |
||||
|
||||
## [0.1.8] |
||||
* Support font and size attributes. |
||||
## [1.3.4] |
||||
* Add option to paintCursorAboveText. |
||||
|
||||
## [0.2.0] |
||||
* Add checked/unchecked list button in toolbar. |
||||
## [1.3.3] |
||||
* Upgrade file_picker version. |
||||
|
||||
## [0.2.1] |
||||
## [1.3.2] |
||||
* Fix copy/paste bug. |
||||
|
||||
## [1.3.1] |
||||
* New logo. |
||||
|
||||
## [1.3.0] |
||||
* Support flutter 2.2.0. |
||||
|
||||
## [1.2.2] |
||||
* Checkbox supports tapping. |
||||
|
||||
## [1.2.1] |
||||
* Indented position not holding while editing. |
||||
|
||||
## [1.2.0] |
||||
* Fix image button cancel causes crash. |
||||
|
||||
## [1.1.8] |
||||
* Fix height of empty line bug. |
||||
|
||||
## [1.1.7] |
||||
* Fix text selection in read-only mode. |
||||
|
||||
## [1.1.6] |
||||
* Remove universal_html dependency. |
||||
|
||||
## [1.1.5] |
||||
* Enable "Select", "Select All" and "Copy" in read-only mode. |
||||
|
||||
## [1.1.4] |
||||
* Fix text selection issue. |
||||
|
||||
## [1.1.3] |
||||
* Update example folder. |
||||
|
||||
## [1.1.2] |
||||
* Add pedantic. |
||||
|
||||
## [1.1.1] |
||||
* Base64 image support. |
||||
|
||||
## [1.1.0] |
||||
* Support null safety. |
||||
|
||||
## [1.0.9] |
||||
* Web support for raw editor and keyboard listener. |
||||
|
||||
## [1.0.8] |
||||
* Support token attribute. |
||||
|
||||
## [1.0.7] |
||||
* Fix crash on web (dart:io). |
||||
|
||||
## [1.0.6] |
||||
* Add desktop support - WINDOWS, MACOS and LINUX. |
||||
|
||||
## [1.0.5] |
||||
* Bug fix: Can not insert newline when Bold is toggled ON. |
||||
|
||||
## [1.0.4] |
||||
* Upgrade photo_view to ^0.11.0. |
||||
|
||||
## [1.0.3] |
||||
* Fix issue that text is not displayed while typing [WEB]. |
||||
|
||||
## [1.0.2] |
||||
* Update toolbar in sample home page. |
||||
|
||||
## [1.0.1] |
||||
* Fix static analysis errors. |
||||
|
||||
## [1.0.0] |
||||
* Support flutter 2.0. |
||||
|
||||
## [1.0.0-dev.2] |
||||
* Improve link handling for tel, mailto and etc. |
||||
|
||||
## [1.0.0-dev.1] |
||||
* Upgrade prerelease SDK & Bump for master. |
||||
|
||||
## [0.3.5] |
||||
* Fix for cursor focus issues when keyboard is on. |
||||
|
||||
## [0.3.4] |
||||
* Improve link handling for tel, mailto and etc. |
||||
|
||||
## [0.3.3] |
||||
* More fix on cursor focus issue when keyboard is on. |
||||
|
||||
## [0.3.2] |
||||
* Fix cursor focus issue when keyboard is on. |
||||
|
||||
## [0.3.1] |
||||
* cursor focus when keyboard is on. |
||||
|
||||
## [0.3.0] |
||||
* Line Height calculated based on font size. |
||||
|
||||
## [0.2.12] |
||||
* Support placeholder. |
||||
|
||||
## [0.2.11] |
||||
* Fix static analysis error. |
||||
|
||||
## [0.2.2] |
||||
* Update git repo. |
||||
## [0.2.10] |
||||
* Update TextInputConfiguration autocorrect to true in stable branch. |
||||
|
||||
## [0.2.3] |
||||
* Support custom styles and image on local device storage without uploading. |
||||
## [0.2.9] |
||||
* Update TextInputConfiguration autocorrect to true. |
||||
|
||||
## [0.2.4] |
||||
* Support the use of custom icon size in toolbar. |
||||
## [0.2.8] |
||||
* Support display local image besides network image in stable branch. |
||||
|
||||
## [0.2.5] |
||||
* Toggle text/background color button in toolbar. |
||||
## [0.2.7] |
||||
* Support display local image besides network image. |
||||
|
||||
## [0.2.6] |
||||
* Fix cursor after pasting. |
||||
|
||||
## [0.2.7] |
||||
* Support display local image besides network image. |
||||
## [0.2.5] |
||||
* Toggle text/background color button in toolbar. |
||||
|
||||
## [0.2.8] |
||||
* Support display local image besides network image in stable branch. |
||||
## [0.2.4] |
||||
* Support the use of custom icon size in toolbar. |
||||
|
||||
## [0.2.3] |
||||
* Support custom styles and image on local device storage without uploading. |
||||
|
||||
## [0.2.2] |
||||
* Update git repo. |
||||
|
||||
## [0.2.1] |
||||
* Fix static analysis error. |
||||
|
||||
## [0.2.0] |
||||
* Add checked/unchecked list button in toolbar. |
||||
|
||||
## [0.1.8] |
||||
* Support font and size attributes. |
||||
|
||||
## [0.1.7] |
||||
* Support checked/unchecked list. |
||||
|
||||
## [0.1.6] |
||||
* Fix getExtentEndpointForSelection. |
||||
|
||||
## [0.1.5] |
||||
* Support text alignment. |
||||
|
||||
## [0.1.4] |
||||
* Handle url with trailing spaces. |
||||
|
||||
## [0.1.3] |
||||
* Handle cursor position change when undo/redo. |
||||
|
||||
## [0.1.2] |
||||
* Handle more text colors. |
||||
|
||||
## [0.1.1] |
||||
* Fix cursor issue when undo. |
||||
|
||||
## [0.1.0] |
||||
* Fix insert image. |
||||
|
||||
## [0.0.9] |
||||
* Handle rgba color. |
||||
|
||||
## [0.0.8] |
||||
* Fix launching url. |
||||
|
||||
## [0.0.7] |
||||
* Handle multiple image inserts. |
||||
|
||||
## [0.0.6] |
||||
* More toolbar functionality. |
||||
|
||||
## [0.0.5] |
||||
* Update example. |
||||
|
||||
## [0.0.4] |
||||
* Update example. |
||||
|
||||
## [0.0.3] |
||||
* Update home page meta data. |
||||
|
||||
## [0.0.2] |
||||
* Support image upload and launch url in read-only mode. |
||||
|
||||
## [0.0.1] |
||||
* Rich text editor based on Quill Delta. |
@ -1,40 +1,142 @@ |
||||
<p align="center"> |
||||
<img src="https://user-images.githubusercontent.com/10923085/119221946-2de89000-baf2-11eb-8285-68168a78c658.png" width="600px"> |
||||
</p> |
||||
<h1 align="center">A rich text editor for Flutter</h1> |
||||
|
||||
<a href="https://bulletjournal.us/home/index.html"> |
||||
<img src= |
||||
"https://user-images.githubusercontent.com/122956/72955931-ccc07900-3d52-11ea-89b1-d468a6e2aa2b.png" |
||||
width="150px" height="150px"></a> |
||||
|
||||
# FlutterQuill |
||||
|
||||
Rich text editor and a [Quill] component for [Flutter]. |
||||
|
||||
This library is a WYSIWYG editor built for the modern mobile platform only and web is under development. You can join [Slack Group] for discussion. |
||||
|
||||
https://pub.dev/packages/flutter_quill |
||||
[![MIT License][license-badge]][license-link] |
||||
[![PRs Welcome][prs-badge]][prs-link] |
||||
[![Watch on GitHub][github-watch-badge]][github-watch-link] |
||||
[![Star on GitHub][github-star-badge]][github-star-link] |
||||
[![Watch on GitHub][github-forks-badge]][github-forks-link] |
||||
|
||||
[license-badge]: https://img.shields.io/github/license/singerdmx/flutter-quill.svg?style=for-the-badge |
||||
[license-link]: https://github.com/singerdmx/flutter-quill/blob/master/LICENSE |
||||
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=for-the-badge |
||||
[prs-link]: https://github.com/singerdmx/flutter-quill/issues |
||||
[github-watch-badge]: https://img.shields.io/github/watchers/singerdmx/flutter-quill.svg?style=for-the-badge&logo=github&logoColor=ffffff |
||||
[github-watch-link]: https://github.com/singerdmx/flutter-quill/watchers |
||||
[github-star-badge]: https://img.shields.io/github/stars/singerdmx/flutter-quill.svg?style=for-the-badge&logo=github&logoColor=ffffff |
||||
[github-star-link]: https://github.com/singerdmx/flutter-quill/stargazers |
||||
[github-forks-badge]: https://img.shields.io/github/forks/singerdmx/flutter-quill.svg?style=for-the-badge&logo=github&logoColor=ffffff |
||||
[github-forks-link]: https://github.com/singerdmx/flutter-quill/network/members |
||||
|
||||
|
||||
FlutterQuill is a rich text editor and a [Quill] component for [Flutter]. |
||||
|
||||
This library is a WYSIWYG editor built for the modern mobile platform, with web compatibility under development. You can join our [Slack Group] for discussion. |
||||
|
||||
Demo App: https://bulletjournal.us/home/index.html |
||||
|
||||
Pub: https://pub.dev/packages/flutter_quill |
||||
|
||||
## Usage |
||||
|
||||
See the `example` directory for a minimal example of how to use FlutterQuill. You typically just need to instantiate a controller: |
||||
|
||||
``` |
||||
QuillController _controller = QuillController.basic(); |
||||
``` |
||||
|
||||
and then embed the toolbar and the editor, within your app. For example: |
||||
|
||||
```dart |
||||
Column( |
||||
children: [ |
||||
QuillToolbar.basic(controller: _controller), |
||||
Expanded( |
||||
child: Container( |
||||
child: QuillEditor.basic( |
||||
controller: _controller, |
||||
readOnly: false, // true for view only mode |
||||
), |
||||
), |
||||
) |
||||
], |
||||
) |
||||
``` |
||||
Check out [Sample Page] for advanced usage. |
||||
|
||||
## Input / Output |
||||
|
||||
This library uses [Quill] as an internal data format. |
||||
Use `_controller.document.toDelta()` to extract it or use `_controller.document.toPlainText()` for plain text. |
||||
|
||||
Default branch `master` is on channel `master`. To use channel `stable`, switch to branch `stable`. |
||||
Branch `master` on channel `master` supports web. To run the app on web do the following: |
||||
1) Change flutter channel to master using `flutter channel master`, followed by `flutter upgrade`. |
||||
2) Enable web using `flutter config --enable-web` and restart the IDE. |
||||
3) Upon successful execution of step 1 and 2 you should see `Chrome` as one of the devices which you run `flutter devices`. |
||||
4) Run the app. |
||||
|
||||
For web development, [ReactQuill] is recommended to use for compatibility. |
||||
|
||||
--- |
||||
|
||||
<img width="484" alt="1" src="https://user-images.githubusercontent.com/122956/103142422-9bb19c80-46b7-11eb-83e4-dd0538a9236e.png"> |
||||
<img width="484" alt="1" src="https://user-images.githubusercontent.com/122956/103142455-0531ab00-46b8-11eb-89f8-26a77de9227f.png"> |
||||
<img width="484" alt="1" src="https://user-images.githubusercontent.com/122956/102963021-f28f5a00-449c-11eb-8f5f-6e9dd60844c4.png"> |
||||
<img width="484" alt="1" src="https://user-images.githubusercontent.com/122956/102977404-c9c88e00-44b7-11eb-9423-b68f3b30b0e0.png"> |
||||
|
||||
One client and affiliated collaborator of **[FlutterQuill]** is Bullet Journal App: https://bulletjournal.us/home/index.html |
||||
|
||||
|
||||
* Use `_controller.document.toDelta()` to extract the deltas. |
||||
* Use `_controller.document.toPlainText()` to extract plain text. |
||||
|
||||
FlutterQuill provides some JSON serialisation support, so that you can save and open documents. To save a document as JSON, do something like the following: |
||||
|
||||
``` |
||||
var json = jsonEncode(_controller.document.toDelta().toJson()); |
||||
``` |
||||
|
||||
You can then write this to storage. |
||||
|
||||
To open a FlutterQuill editor with an existing JSON representation that you've previously stored, you can do something like this: |
||||
|
||||
``` |
||||
var myJSON = jsonDecode(incomingJSONText); |
||||
_controller = QuillController( |
||||
document: Document.fromJson(myJSON), |
||||
selection: TextSelection.collapsed(offset: 0)); |
||||
``` |
||||
|
||||
## Configuration |
||||
|
||||
The `QuillToolbar` class lets you customise which formatting options are available. |
||||
[Sample Page] provides sample code for advanced usage and configuration. |
||||
|
||||
## Web |
||||
|
||||
For web development, use `flutter config --enable-web` for flutter and use [ReactQuill] for React. |
||||
|
||||
It is required to provide `EmbedBuilder`, e.g. [defaultEmbedBuilderWeb](https://github.com/singerdmx/flutter-quill/blob/master/example/lib/universal_ui/universal_ui.dart#L28). |
||||
Also it is required to provide `webImagePickImpl`, e.g. [Sample Page](https://github.com/singerdmx/flutter-quill/blob/master/example/lib/pages/home_page.dart#L212). |
||||
|
||||
## Desktop |
||||
|
||||
It is required to provide `filePickImpl` for toolbar image button, e.g. [Sample Page](https://github.com/singerdmx/flutter-quill/blob/master/example/lib/pages/home_page.dart#L192). |
||||
|
||||
## Custom Size Image for Mobile |
||||
|
||||
Define `mobileWidth`, `mobileHeight`, `mobileMargin`, `mobileAlignment` as follows: |
||||
``` |
||||
{ |
||||
"insert": { |
||||
"image": "https://user-images.githubusercontent.com/122956/72955931-ccc07900-3d52-11ea-89b1-d468a6e2aa2b.png" |
||||
}, |
||||
"attributes":{ |
||||
"style":"mobileWidth: 50; mobileHeight: 50; mobileMargin: 10; mobileAlignment: topLeft" |
||||
} |
||||
} |
||||
``` |
||||
|
||||
## Migrate Zefyr Data |
||||
|
||||
Check out [code](https://github.com/jwehrle/zefyr_quill_convert) and [doc](https://docs.google.com/document/d/1FUSrpbarHnilb7uDN5J5DDahaI0v1RMXBjj4fFSpSuY/edit?usp=sharing). |
||||
|
||||
--- |
||||
|
||||
<p float="left"> |
||||
<img width="400" alt="1" src="https://user-images.githubusercontent.com/122956/103142422-9bb19c80-46b7-11eb-83e4-dd0538a9236e.png"> |
||||
<img width="400" alt="1" src="https://user-images.githubusercontent.com/122956/103142455-0531ab00-46b8-11eb-89f8-26a77de9227f.png"> |
||||
</p> |
||||
|
||||
|
||||
<p float="left"> |
||||
<img width="400" alt="1" src="https://user-images.githubusercontent.com/122956/102963021-f28f5a00-449c-11eb-8f5f-6e9dd60844c4.png"> |
||||
<img width="400" alt="1" src="https://user-images.githubusercontent.com/122956/102977404-c9c88e00-44b7-11eb-9423-b68f3b30b0e0.png"> |
||||
</p> |
||||
|
||||
## Sponsors |
||||
|
||||
<a href="https://bulletjournal.us/home/index.html"> |
||||
<img src= |
||||
"https://user-images.githubusercontent.com/122956/72955931-ccc07900-3d52-11ea-89b1-d468a6e2aa2b.png" |
||||
width="150px" height="150px"></a> |
||||
|
||||
[Quill]: https://quilljs.com/docs/formats |
||||
[Flutter]: https://github.com/flutter/flutter |
||||
[FlutterQuill]: https://pub.dev/packages/flutter_quill |
||||
[ReactQuill]: https://github.com/zenoamaro/react-quill |
||||
[Flutter]: https://github.com/flutter/flutter |
||||
[FlutterQuill]: https://pub.dev/packages/flutter_quill |
||||
[ReactQuill]: https://github.com/zenoamaro/react-quill |
||||
[Slack Group]: https://join.slack.com/t/bulletjournal1024/shared_invite/zt-fys7t9hi-ITVU5PGDen1rNRyCjdcQ2g |
||||
[Sample Page]: https://github.com/singerdmx/flutter-quill/blob/master/example/lib/pages/home_page.dart |
||||
|
@ -0,0 +1,37 @@ |
||||
include: package:pedantic/analysis_options.yaml |
||||
|
||||
analyzer: |
||||
errors: |
||||
undefined_prefixed_name: ignore |
||||
unsafe_html: ignore |
||||
linter: |
||||
rules: |
||||
- always_declare_return_types |
||||
- always_put_required_named_parameters_first |
||||
- annotate_overrides |
||||
- avoid_empty_else |
||||
- avoid_escaping_inner_quotes |
||||
- avoid_print |
||||
- avoid_redundant_argument_values |
||||
- avoid_types_on_closure_parameters |
||||
- avoid_void_async |
||||
- cascade_invocations |
||||
- directives_ordering |
||||
- lines_longer_than_80_chars |
||||
- omit_local_variable_types |
||||
- prefer_const_constructors |
||||
- prefer_const_constructors_in_immutables |
||||
- prefer_const_declarations |
||||
- prefer_final_fields |
||||
- prefer_final_in_for_each |
||||
- prefer_final_locals |
||||
- prefer_initializing_formals |
||||
- prefer_int_literals |
||||
- prefer_interpolation_to_compose_strings |
||||
- prefer_relative_imports |
||||
- prefer_single_quotes |
||||
- sort_constructors_first |
||||
- sort_unnamed_constructors_first |
||||
- unnecessary_lambdas |
||||
- unnecessary_parenthesis |
||||
- unnecessary_string_interpolations |
@ -1 +0,0 @@ |
||||
#include "Generated.xcconfig" |
@ -1 +0,0 @@ |
||||
#include "Generated.xcconfig" |
@ -1,173 +0,0 @@ |
||||
import 'dart:async'; |
||||
import 'dart:convert'; |
||||
import 'dart:io'; |
||||
import 'dart:math'; |
||||
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:flutter_quill/models/documents/attribute.dart'; |
||||
import 'package:flutter_quill/models/documents/document.dart'; |
||||
import 'package:flutter_quill/widgets/controller.dart'; |
||||
import 'package:flutter_quill/widgets/default_styles.dart'; |
||||
import 'package:flutter_quill/widgets/editor.dart'; |
||||
import 'package:flutter_quill/widgets/toolbar.dart'; |
||||
import 'package:tuple/tuple.dart'; |
||||
|
||||
import 'read_only_page.dart'; |
||||
|
||||
class HomePage extends StatefulWidget { |
||||
@override |
||||
_HomePageState createState() => _HomePageState(); |
||||
} |
||||
|
||||
class _HomePageState extends State<HomePage> { |
||||
QuillController _controller; |
||||
final FocusNode _focusNode = FocusNode(); |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_loadFromAssets(); |
||||
} |
||||
|
||||
Future<void> _loadFromAssets() async { |
||||
try { |
||||
final result = await rootBundle.loadString('assets/sample_data.json'); |
||||
final doc = Document.fromJson(jsonDecode(result)); |
||||
setState(() { |
||||
_controller = QuillController( |
||||
document: doc, selection: TextSelection.collapsed(offset: 0)); |
||||
}); |
||||
} catch (error) { |
||||
final doc = Document()..insert(0, 'Empty asset'); |
||||
setState(() { |
||||
_controller = QuillController( |
||||
document: doc, selection: TextSelection.collapsed(offset: 0)); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
if (_controller == null) { |
||||
return Scaffold(body: Center(child: Text('Loading...'))); |
||||
} |
||||
|
||||
return Scaffold( |
||||
appBar: AppBar( |
||||
backgroundColor: Colors.grey.shade800, |
||||
elevation: 0, |
||||
centerTitle: false, |
||||
title: Text( |
||||
'Flutter Quill', |
||||
), |
||||
actions: [], |
||||
), |
||||
drawer: Material( |
||||
color: Colors.grey.shade800, |
||||
child: _buildMenuBar(context), |
||||
), |
||||
floatingActionButton: FloatingActionButton( |
||||
onPressed: (){ |
||||
int option = Random().nextInt(30); |
||||
print(option); |
||||
_controller.formatSelection(SizeAttribute("${option.toDouble()}")); |
||||
}, |
||||
), |
||||
body: RawKeyboardListener( |
||||
focusNode: FocusNode(), |
||||
onKey: (RawKeyEvent event) { |
||||
if (event.data.isControlPressed && event.character == 'b') { |
||||
if (_controller |
||||
.getSelectionStyle() |
||||
.attributes |
||||
.keys |
||||
.contains("bold")) { |
||||
_controller |
||||
.formatSelection(Attribute.clone(Attribute.bold, null)); |
||||
} else { |
||||
_controller.formatSelection(Attribute.bold); |
||||
print("not bold"); |
||||
} |
||||
} |
||||
}, |
||||
child: _buildWelcomeEditor(context), |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget _buildWelcomeEditor(BuildContext context) { |
||||
return Column( |
||||
crossAxisAlignment: CrossAxisAlignment.stretch, |
||||
children: <Widget>[ |
||||
Expanded( |
||||
child: Container( |
||||
color: Colors.white, |
||||
padding: const EdgeInsets.only(left: 16.0, right: 16.0), |
||||
child: QuillEditor( |
||||
controller: _controller, |
||||
scrollController: ScrollController(), |
||||
scrollable: true, |
||||
focusNode: _focusNode, |
||||
autoFocus: false, |
||||
readOnly: false, |
||||
enableInteractiveSelection: true, |
||||
expands: false, |
||||
padding: EdgeInsets.zero, |
||||
customStyles: DefaultStyles( |
||||
h1: DefaultTextBlockStyle( |
||||
TextStyle( |
||||
fontSize: 32.0, |
||||
color: Colors.black, |
||||
height:1.15, |
||||
fontWeight: FontWeight.w300, |
||||
), |
||||
Tuple2(16.0, 0.0), |
||||
Tuple2(0.0, 0.0), |
||||
null), |
||||
sizeSmall: TextStyle(fontSize: 9.0), |
||||
sizeHuge: TextStyle(fontSize:64.0) |
||||
), |
||||
), |
||||
), |
||||
), |
||||
Container( |
||||
child: QuillToolbar.basic( |
||||
controller: _controller, |
||||
uploadFileCallback: _fakeUploadImageCallBack), |
||||
) |
||||
], |
||||
); |
||||
} |
||||
|
||||
Future<String> _fakeUploadImageCallBack(File file) async { |
||||
print(file); |
||||
var completer = new Completer<String>(); |
||||
completer.complete( |
||||
'https://user-images.githubusercontent.com/122956/72955931-ccc07900-3d52-11ea-89b1-d468a6e2aa2b.png'); |
||||
return completer.future; |
||||
} |
||||
|
||||
Widget _buildMenuBar(BuildContext context) { |
||||
final itemStyle = TextStyle(color: Colors.white); |
||||
return ListView( |
||||
children: [ |
||||
ListTile( |
||||
title: Text('Read only demo', style: itemStyle), |
||||
dense: true, |
||||
visualDensity: VisualDensity.compact, |
||||
onTap: _readOnly, |
||||
) |
||||
], |
||||
); |
||||
} |
||||
|
||||
void _readOnly() { |
||||
Navigator.push( |
||||
context, |
||||
MaterialPageRoute( |
||||
builder: (BuildContext context) => ReadOnlyPage(), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,143 +0,0 @@ |
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_quill/widgets/controller.dart'; |
||||
import 'package:flutter_quill/widgets/delegate.dart'; |
||||
import 'package:flutter_quill/widgets/editor.dart'; |
||||
|
||||
class QuillField extends StatefulWidget { |
||||
final QuillController controller; |
||||
final FocusNode focusNode; |
||||
final ScrollController scrollController; |
||||
final bool scrollable; |
||||
final EdgeInsetsGeometry padding; |
||||
final bool autofocus; |
||||
final bool showCursor; |
||||
final bool readOnly; |
||||
final bool enableInteractiveSelection; |
||||
final double minHeight; |
||||
final double maxHeight; |
||||
final bool expands; |
||||
final TextCapitalization textCapitalization; |
||||
final Brightness keyboardAppearance; |
||||
final ScrollPhysics scrollPhysics; |
||||
final ValueChanged<String> onLaunchUrl; |
||||
final InputDecoration decoration; |
||||
final Widget toolbar; |
||||
final EmbedBuilder embedBuilder; |
||||
final StyleBuilder styleBuilder; |
||||
QuillField({ |
||||
Key key, |
||||
@required this.controller, |
||||
this.focusNode, |
||||
this.scrollController, |
||||
this.scrollable = true, |
||||
this.padding = EdgeInsets.zero, |
||||
this.autofocus = false, |
||||
this.showCursor = true, |
||||
this.readOnly = false, |
||||
this.enableInteractiveSelection = true, |
||||
this.minHeight, |
||||
this.maxHeight, |
||||
this.expands = false, |
||||
this.textCapitalization = TextCapitalization.sentences, |
||||
this.keyboardAppearance = Brightness.light, |
||||
this.scrollPhysics, |
||||
this.onLaunchUrl, |
||||
this.decoration, |
||||
this.toolbar, |
||||
this.embedBuilder, this.styleBuilder, |
||||
}) : super(key: key); |
||||
|
||||
@override |
||||
_QuillFieldState createState() => _QuillFieldState(); |
||||
} |
||||
|
||||
class _QuillFieldState extends State<QuillField> { |
||||
bool _focused; |
||||
|
||||
void _editorFocusChanged() { |
||||
setState(() { |
||||
_focused = widget.focusNode.hasFocus; |
||||
}); |
||||
} |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_focused = widget.focusNode.hasFocus; |
||||
widget.focusNode.addListener(_editorFocusChanged); |
||||
} |
||||
|
||||
@override |
||||
void didUpdateWidget(covariant QuillField oldWidget) { |
||||
super.didUpdateWidget(oldWidget); |
||||
if (widget.focusNode != oldWidget.focusNode) { |
||||
oldWidget.focusNode.removeListener(_editorFocusChanged); |
||||
widget.focusNode.addListener(_editorFocusChanged); |
||||
_focused = widget.focusNode.hasFocus; |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
Widget child = QuillEditor( |
||||
controller: widget.controller, |
||||
focusNode: widget.focusNode, |
||||
scrollController: widget.scrollController, |
||||
scrollable: widget.scrollable, |
||||
padding: widget.padding, |
||||
autoFocus: widget.autofocus, |
||||
showCursor: widget.showCursor, |
||||
readOnly: widget.readOnly, |
||||
enableInteractiveSelection: widget.enableInteractiveSelection, |
||||
minHeight: widget.minHeight, |
||||
maxHeight: widget.maxHeight, |
||||
expands: widget.expands, |
||||
textCapitalization: widget.textCapitalization, |
||||
keyboardAppearance: widget.keyboardAppearance, |
||||
scrollPhysics: widget.scrollPhysics, |
||||
onLaunchUrl: widget.onLaunchUrl, |
||||
embedBuilder: widget.embedBuilder, |
||||
styleBuilder:widget.styleBuilder, |
||||
); |
||||
|
||||
if (widget.toolbar != null) { |
||||
child = Column( |
||||
children: [ |
||||
child, |
||||
Visibility( |
||||
child: widget.toolbar, |
||||
visible: _focused, |
||||
maintainSize: true, |
||||
maintainAnimation: true, |
||||
maintainState: true, |
||||
), |
||||
], |
||||
); |
||||
} |
||||
|
||||
return AnimatedBuilder( |
||||
animation: |
||||
Listenable.merge(<Listenable>[widget.focusNode, widget.controller]), |
||||
builder: (BuildContext context, Widget child) { |
||||
return InputDecorator( |
||||
decoration: _getEffectiveDecoration(), |
||||
isFocused: widget.focusNode.hasFocus, |
||||
// TODO: Document should be considered empty of it has single empty line with no styles applied |
||||
isEmpty: widget.controller.document.length == 1, |
||||
child: child, |
||||
); |
||||
}, |
||||
child: child, |
||||
); |
||||
} |
||||
|
||||
InputDecoration _getEffectiveDecoration() { |
||||
return (widget.decoration ?? const InputDecoration()) |
||||
.applyDefaults(Theme.of(context).inputDecorationTheme) |
||||
.copyWith( |
||||
enabled: !widget.readOnly, |
||||
hintMaxLines: widget.decoration?.hintMaxLines, |
||||
); |
||||
} |
||||
} |
@ -1,355 +0,0 @@ |
||||
# Generated by pub |
||||
# See https://dart.dev/tools/pub/glossary#lockfile |
||||
packages: |
||||
async: |
||||
dependency: transitive |
||||
description: |
||||
name: async |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.5.0" |
||||
boolean_selector: |
||||
dependency: transitive |
||||
description: |
||||
name: boolean_selector |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.0" |
||||
characters: |
||||
dependency: transitive |
||||
description: |
||||
name: characters |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.1.0" |
||||
charcode: |
||||
dependency: transitive |
||||
description: |
||||
name: charcode |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.2.0" |
||||
clock: |
||||
dependency: transitive |
||||
description: |
||||
name: clock |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.1.0" |
||||
collection: |
||||
dependency: transitive |
||||
description: |
||||
name: collection |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.15.0" |
||||
convert: |
||||
dependency: transitive |
||||
description: |
||||
name: convert |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.1" |
||||
crypto: |
||||
dependency: transitive |
||||
description: |
||||
name: crypto |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.5" |
||||
csslib: |
||||
dependency: transitive |
||||
description: |
||||
name: csslib |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.16.2" |
||||
cupertino_icons: |
||||
dependency: "direct main" |
||||
description: |
||||
name: cupertino_icons |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.0.0" |
||||
fake_async: |
||||
dependency: transitive |
||||
description: |
||||
name: fake_async |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.2.0" |
||||
flutter: |
||||
dependency: "direct main" |
||||
description: flutter |
||||
source: sdk |
||||
version: "0.0.0" |
||||
flutter_colorpicker: |
||||
dependency: transitive |
||||
description: |
||||
name: flutter_colorpicker |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.3.4" |
||||
flutter_plugin_android_lifecycle: |
||||
dependency: transitive |
||||
description: |
||||
name: flutter_plugin_android_lifecycle |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.0.11" |
||||
flutter_quill: |
||||
dependency: "direct main" |
||||
description: |
||||
path: ".." |
||||
relative: true |
||||
source: path |
||||
version: "0.2.8" |
||||
flutter_test: |
||||
dependency: "direct dev" |
||||
description: flutter |
||||
source: sdk |
||||
version: "0.0.0" |
||||
flutter_web_plugins: |
||||
dependency: transitive |
||||
description: flutter |
||||
source: sdk |
||||
version: "0.0.0" |
||||
html: |
||||
dependency: transitive |
||||
description: |
||||
name: html |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.14.0+4" |
||||
http: |
||||
dependency: transitive |
||||
description: |
||||
name: http |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.12.2" |
||||
http_parser: |
||||
dependency: transitive |
||||
description: |
||||
name: http_parser |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "3.1.4" |
||||
image_picker: |
||||
dependency: transitive |
||||
description: |
||||
name: image_picker |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.6.7+17" |
||||
image_picker_platform_interface: |
||||
dependency: transitive |
||||
description: |
||||
name: image_picker_platform_interface |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.1.1" |
||||
js: |
||||
dependency: transitive |
||||
description: |
||||
name: js |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.6.3" |
||||
matcher: |
||||
dependency: transitive |
||||
description: |
||||
name: matcher |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.12.10" |
||||
meta: |
||||
dependency: transitive |
||||
description: |
||||
name: meta |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.3.0" |
||||
path: |
||||
dependency: transitive |
||||
description: |
||||
name: path |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.8.0" |
||||
pedantic: |
||||
dependency: transitive |
||||
description: |
||||
name: pedantic |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.9.2" |
||||
photo_view: |
||||
dependency: transitive |
||||
description: |
||||
name: photo_view |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.10.3" |
||||
plugin_platform_interface: |
||||
dependency: transitive |
||||
description: |
||||
name: plugin_platform_interface |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.0.3" |
||||
quill_delta: |
||||
dependency: transitive |
||||
description: |
||||
name: quill_delta |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.0.0" |
||||
quiver: |
||||
dependency: transitive |
||||
description: |
||||
name: quiver |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.5" |
||||
quiver_hashcode: |
||||
dependency: transitive |
||||
description: |
||||
name: quiver_hashcode |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.0.0" |
||||
sky_engine: |
||||
dependency: transitive |
||||
description: flutter |
||||
source: sdk |
||||
version: "0.0.99" |
||||
source_span: |
||||
dependency: transitive |
||||
description: |
||||
name: source_span |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.8.0" |
||||
stack_trace: |
||||
dependency: transitive |
||||
description: |
||||
name: stack_trace |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.10.0" |
||||
stream_channel: |
||||
dependency: transitive |
||||
description: |
||||
name: stream_channel |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.0" |
||||
string_scanner: |
||||
dependency: transitive |
||||
description: |
||||
name: string_scanner |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.1.0" |
||||
term_glyph: |
||||
dependency: transitive |
||||
description: |
||||
name: term_glyph |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.2.0" |
||||
test_api: |
||||
dependency: transitive |
||||
description: |
||||
name: test_api |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.2.19" |
||||
tuple: |
||||
dependency: transitive |
||||
description: |
||||
name: tuple |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.0.3" |
||||
typed_data: |
||||
dependency: transitive |
||||
description: |
||||
name: typed_data |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.3.0" |
||||
universal_html: |
||||
dependency: transitive |
||||
description: |
||||
name: universal_html |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.2.4" |
||||
universal_io: |
||||
dependency: transitive |
||||
description: |
||||
name: universal_io |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.0.2" |
||||
url_launcher: |
||||
dependency: transitive |
||||
description: |
||||
name: url_launcher |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "5.7.10" |
||||
url_launcher_linux: |
||||
dependency: transitive |
||||
description: |
||||
name: url_launcher_linux |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.0.1+4" |
||||
url_launcher_macos: |
||||
dependency: transitive |
||||
description: |
||||
name: url_launcher_macos |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.0.1+9" |
||||
url_launcher_platform_interface: |
||||
dependency: transitive |
||||
description: |
||||
name: url_launcher_platform_interface |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "1.0.9" |
||||
url_launcher_web: |
||||
dependency: transitive |
||||
description: |
||||
name: url_launcher_web |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.1.5+1" |
||||
url_launcher_windows: |
||||
dependency: transitive |
||||
description: |
||||
name: url_launcher_windows |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.0.1+3" |
||||
vector_math: |
||||
dependency: transitive |
||||
description: |
||||
name: vector_math |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "2.1.0" |
||||
zone_local: |
||||
dependency: transitive |
||||
description: |
||||
name: zone_local |
||||
url: "https://pub.dartlang.org" |
||||
source: hosted |
||||
version: "0.1.2" |
||||
sdks: |
||||
dart: ">=2.12.0-0.0 <3.0.0" |
||||
flutter: ">=1.22.0" |
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 544 B |
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 442 B |
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 721 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1 @@ |
||||
include ':app' |
@ -0,0 +1,2 @@ |
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" |
||||
#include "Generated.xcconfig" |
@ -0,0 +1,2 @@ |
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" |
||||
#include "Generated.xcconfig" |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 564 B After Width: | Height: | Size: 564 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
@ -1,4 +1,3 @@ |
||||
// import 'package:app/pages/home_page.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
|
||||
import 'pages/home_page.dart'; |
@ -0,0 +1,301 @@ |
||||
import 'dart:async'; |
||||
import 'dart:convert'; |
||||
import 'dart:io'; |
||||
|
||||
import 'package:file_picker/file_picker.dart'; |
||||
import 'package:filesystem_picker/filesystem_picker.dart'; |
||||
import 'package:flutter/foundation.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:flutter_quill/flutter_quill.dart' hide Text; |
||||
import 'package:path/path.dart'; |
||||
import 'package:path_provider/path_provider.dart'; |
||||
import 'package:tuple/tuple.dart'; |
||||
|
||||
import '../universal_ui/universal_ui.dart'; |
||||
import 'read_only_page.dart'; |
||||
|
||||
class HomePage extends StatefulWidget { |
||||
@override |
||||
_HomePageState createState() => _HomePageState(); |
||||
} |
||||
|
||||
class _HomePageState extends State<HomePage> { |
||||
QuillController? _controller; |
||||
final FocusNode _focusNode = FocusNode(); |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_loadFromAssets(); |
||||
} |
||||
|
||||
Future<void> _loadFromAssets() async { |
||||
try { |
||||
final result = await rootBundle.loadString('assets/sample_data.json'); |
||||
final doc = Document.fromJson(jsonDecode(result)); |
||||
setState(() { |
||||
_controller = QuillController( |
||||
document: doc, selection: const TextSelection.collapsed(offset: 0)); |
||||
}); |
||||
} catch (error) { |
||||
final doc = Document()..insert(0, 'Empty asset'); |
||||
setState(() { |
||||
_controller = QuillController( |
||||
document: doc, selection: const TextSelection.collapsed(offset: 0)); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
if (_controller == null) { |
||||
return const Scaffold(body: Center(child: Text('Loading...'))); |
||||
} |
||||
|
||||
return Scaffold( |
||||
appBar: AppBar( |
||||
backgroundColor: Colors.grey.shade800, |
||||
elevation: 0, |
||||
centerTitle: false, |
||||
title: const Text( |
||||
'Flutter Quill', |
||||
), |
||||
actions: [], |
||||
), |
||||
drawer: Container( |
||||
constraints: |
||||
BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.7), |
||||
color: Colors.grey.shade800, |
||||
child: _buildMenuBar(context), |
||||
), |
||||
body: RawKeyboardListener( |
||||
focusNode: FocusNode(), |
||||
onKey: (event) { |
||||
if (event.data.isControlPressed && event.character == 'b') { |
||||
if (_controller! |
||||
.getSelectionStyle() |
||||
.attributes |
||||
.keys |
||||
.contains('bold')) { |
||||
_controller! |
||||
.formatSelection(Attribute.clone(Attribute.bold, null)); |
||||
} else { |
||||
_controller!.formatSelection(Attribute.bold); |
||||
} |
||||
} |
||||
}, |
||||
child: _buildWelcomeEditor(context), |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget _buildWelcomeEditor(BuildContext context) { |
||||
var quillEditor = QuillEditor( |
||||
controller: _controller!, |
||||
scrollController: ScrollController(), |
||||
scrollable: true, |
||||
focusNode: _focusNode, |
||||
autoFocus: false, |
||||
readOnly: false, |
||||
placeholder: 'Add content', |
||||
expands: false, |
||||
padding: EdgeInsets.zero, |
||||
customStyles: DefaultStyles( |
||||
h1: DefaultTextBlockStyle( |
||||
const TextStyle( |
||||
fontSize: 32, |
||||
color: Colors.black, |
||||
height: 1.15, |
||||
fontWeight: FontWeight.w300, |
||||
), |
||||
const Tuple2(16, 0), |
||||
const Tuple2(0, 0), |
||||
null), |
||||
sizeSmall: const TextStyle(fontSize: 9), |
||||
)); |
||||
if (kIsWeb) { |
||||
quillEditor = QuillEditor( |
||||
controller: _controller!, |
||||
scrollController: ScrollController(), |
||||
scrollable: true, |
||||
focusNode: _focusNode, |
||||
autoFocus: false, |
||||
readOnly: false, |
||||
placeholder: 'Add content', |
||||
expands: false, |
||||
padding: EdgeInsets.zero, |
||||
customStyles: DefaultStyles( |
||||
h1: DefaultTextBlockStyle( |
||||
const TextStyle( |
||||
fontSize: 32, |
||||
color: Colors.black, |
||||
height: 1.15, |
||||
fontWeight: FontWeight.w300, |
||||
), |
||||
const Tuple2(16, 0), |
||||
const Tuple2(0, 0), |
||||
null), |
||||
sizeSmall: const TextStyle(fontSize: 9), |
||||
), |
||||
embedBuilder: defaultEmbedBuilderWeb); |
||||
} |
||||
var toolbar = QuillToolbar.basic( |
||||
controller: _controller!, |
||||
// provide a callback to enable picking images from device. |
||||
// if omit, "image" button only allows adding images from url. |
||||
// same goes for videos. |
||||
onImagePickCallback: _onImagePickCallback, |
||||
onVideoPickCallback: _onVideoPickCallback, |
||||
// uncomment to provide a custom "pick from" dialog. |
||||
// mediaPickSettingSelector: _selectMediaPickSetting, |
||||
); |
||||
if (kIsWeb) { |
||||
toolbar = QuillToolbar.basic( |
||||
controller: _controller!, |
||||
onImagePickCallback: _onImagePickCallback, |
||||
webImagePickImpl: _webImagePickImpl); |
||||
} |
||||
if (_isDesktop()) { |
||||
toolbar = QuillToolbar.basic( |
||||
controller: _controller!, |
||||
onImagePickCallback: _onImagePickCallback, |
||||
filePickImpl: openFileSystemPickerForDesktop); |
||||
} |
||||
|
||||
return SafeArea( |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||
children: <Widget>[ |
||||
Expanded( |
||||
flex: 15, |
||||
child: Container( |
||||
color: Colors.white, |
||||
padding: const EdgeInsets.only(left: 16, right: 16), |
||||
child: quillEditor, |
||||
), |
||||
), |
||||
kIsWeb |
||||
? Expanded( |
||||
child: Container( |
||||
padding: |
||||
const EdgeInsets.symmetric(vertical: 16, horizontal: 8), |
||||
child: toolbar, |
||||
)) |
||||
: Container(child: toolbar) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
bool _isDesktop() => !kIsWeb && !Platform.isAndroid && !Platform.isIOS; |
||||
|
||||
Future<String?> openFileSystemPickerForDesktop(BuildContext context) async { |
||||
return await FilesystemPicker.open( |
||||
context: context, |
||||
rootDirectory: await getApplicationDocumentsDirectory(), |
||||
fsType: FilesystemType.file, |
||||
fileTileSelectMode: FileTileSelectMode.wholeTile, |
||||
); |
||||
} |
||||
|
||||
// Renders the image picked by imagePicker from local file storage |
||||
// You can also upload the picked image to any server (eg : AWS s3 |
||||
// or Firebase) and then return the uploaded image URL. |
||||
Future<String> _onImagePickCallback(File file) async { |
||||
// Copies the picked file from temporary cache to applications directory |
||||
final appDocDir = await getApplicationDocumentsDirectory(); |
||||
final copiedFile = |
||||
await file.copy('${appDocDir.path}/${basename(file.path)}'); |
||||
return copiedFile.path.toString(); |
||||
} |
||||
|
||||
Future<String?> _webImagePickImpl( |
||||
OnImagePickCallback onImagePickCallback) async { |
||||
final result = await FilePicker.platform.pickFiles(); |
||||
if (result == null) { |
||||
return null; |
||||
} |
||||
|
||||
// Take first, because we don't allow picking multiple files. |
||||
final fileName = result.files.first.name; |
||||
final file = File(fileName); |
||||
|
||||
return onImagePickCallback(file); |
||||
} |
||||
|
||||
// Renders the video picked by imagePicker from local file storage |
||||
// You can also upload the picked video to any server (eg : AWS s3 |
||||
// or Firebase) and then return the uploaded video URL. |
||||
Future<String> _onVideoPickCallback(File file) async { |
||||
// Copies the picked file from temporary cache to applications directory |
||||
final appDocDir = await getApplicationDocumentsDirectory(); |
||||
final copiedFile = |
||||
await file.copy('${appDocDir.path}/${basename(file.path)}'); |
||||
return copiedFile.path.toString(); |
||||
} |
||||
|
||||
Future<MediaPickSetting?> _selectMediaPickSetting(BuildContext context) => |
||||
showDialog<MediaPickSetting>( |
||||
context: context, |
||||
builder: (ctx) => AlertDialog( |
||||
contentPadding: EdgeInsets.zero, |
||||
content: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: [ |
||||
TextButton.icon( |
||||
icon: const Icon(Icons.collections), |
||||
label: const Text('Gallery'), |
||||
onPressed: () => Navigator.pop(ctx, MediaPickSetting.Gallery), |
||||
), |
||||
TextButton.icon( |
||||
icon: const Icon(Icons.link), |
||||
label: const Text('Link'), |
||||
onPressed: () => Navigator.pop(ctx, MediaPickSetting.Link), |
||||
) |
||||
], |
||||
), |
||||
), |
||||
); |
||||
|
||||
Widget _buildMenuBar(BuildContext context) { |
||||
final size = MediaQuery.of(context).size; |
||||
const itemStyle = TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 18, |
||||
fontWeight: FontWeight.bold, |
||||
); |
||||
return Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Divider( |
||||
thickness: 2, |
||||
color: Colors.white, |
||||
indent: size.width * 0.1, |
||||
endIndent: size.width * 0.1, |
||||
), |
||||
ListTile( |
||||
title: const Center(child: Text('Read only demo', style: itemStyle)), |
||||
dense: true, |
||||
visualDensity: VisualDensity.compact, |
||||
onTap: _readOnly, |
||||
), |
||||
Divider( |
||||
thickness: 2, |
||||
color: Colors.white, |
||||
indent: size.width * 0.1, |
||||
endIndent: size.width * 0.1, |
||||
), |
||||
], |
||||
); |
||||
} |
||||
|
||||
void _readOnly() { |
||||
Navigator.push( |
||||
super.context, |
||||
MaterialPageRoute( |
||||
builder: (context) => ReadOnlyPage(), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,3 @@ |
||||
class PlatformViewRegistry { |
||||
static void registerViewFactory(String viewId, dynamic cb) {} |
||||
} |
@ -0,0 +1,7 @@ |
||||
import 'dart:ui' as ui; |
||||
|
||||
class PlatformViewRegistry { |
||||
static void registerViewFactory(String viewId, dynamic cb) { |
||||
ui.platformViewRegistry.registerViewFactory(viewId, cb); |
||||
} |
||||
} |
@ -0,0 +1,58 @@ |
||||
library universal_ui; |
||||
|
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/foundation.dart'; |
||||
import 'package:flutter_quill/flutter_quill.dart'; |
||||
import 'package:universal_html/html.dart' as html; |
||||
|
||||
import '../widgets/responsive_widget.dart'; |
||||
import 'fake_ui.dart' if (dart.library.html) 'real_ui.dart' as ui_instance; |
||||
|
||||
class PlatformViewRegistryFix { |
||||
void registerViewFactory(dynamic x, dynamic y) { |
||||
if (kIsWeb) { |
||||
ui_instance.PlatformViewRegistry.registerViewFactory( |
||||
x, |
||||
y, |
||||
); |
||||
} |
||||
} |
||||
} |
||||
|
||||
class UniversalUI { |
||||
PlatformViewRegistryFix platformViewRegistry = PlatformViewRegistryFix(); |
||||
} |
||||
|
||||
var ui = UniversalUI(); |
||||
|
||||
Widget defaultEmbedBuilderWeb(BuildContext context, Embed node, bool readOnly) { |
||||
switch (node.value.type) { |
||||
case 'image': |
||||
final String imageUrl = node.value.data; |
||||
final size = MediaQuery.of(context).size; |
||||
UniversalUI().platformViewRegistry.registerViewFactory( |
||||
imageUrl, (viewId) => html.ImageElement()..src = imageUrl); |
||||
return Padding( |
||||
padding: EdgeInsets.only( |
||||
right: ResponsiveWidget.isMediumScreen(context) |
||||
? size.width * 0.5 |
||||
: (ResponsiveWidget.isLargeScreen(context)) |
||||
? size.width * 0.75 |
||||
: size.width * 0.2, |
||||
), |
||||
child: SizedBox( |
||||
height: MediaQuery.of(context).size.height * 0.45, |
||||
child: HtmlElementView( |
||||
viewType: imageUrl, |
||||
), |
||||
), |
||||
); |
||||
|
||||
default: |
||||
throw UnimplementedError( |
||||
'Embeddable type "${node.value.type}" is not supported by default ' |
||||
'embed builder of QuillEditor. You must pass your own builder function ' |
||||
'to embedBuilder property of QuillEditor or QuillField widgets.', |
||||
); |
||||
} |
||||
} |
@ -1,16 +1,16 @@ |
||||
import 'package:flutter/material.dart'; |
||||
|
||||
class ResponsiveWidget extends StatelessWidget { |
||||
final Widget largeScreen; |
||||
final Widget mediumScreen; |
||||
final Widget smallScreen; |
||||
const ResponsiveWidget({ |
||||
required this.largeScreen, |
||||
this.mediumScreen, |
||||
this.smallScreen, |
||||
Key? key, |
||||
}) : super(key: key); |
||||
|
||||
const ResponsiveWidget( |
||||
{Key key, |
||||
@required this.largeScreen, |
||||
this.mediumScreen, |
||||
this.smallScreen}) |
||||
: super(key: key); |
||||
final Widget largeScreen; |
||||
final Widget? mediumScreen; |
||||
final Widget? smallScreen; |
||||
|
||||
static bool isSmallScreen(BuildContext context) { |
||||
return MediaQuery.of(context).size.width < 800; |
@ -0,0 +1 @@ |
||||
flutter/ephemeral |
@ -0,0 +1,106 @@ |
||||
cmake_minimum_required(VERSION 3.10) |
||||
project(runner LANGUAGES CXX) |
||||
|
||||
set(BINARY_NAME "app") |
||||
set(APPLICATION_ID "com.example.app") |
||||
|
||||
cmake_policy(SET CMP0063 NEW) |
||||
|
||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") |
||||
|
||||
# Configure build options. |
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) |
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE |
||||
STRING "Flutter build mode" FORCE) |
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS |
||||
"Debug" "Profile" "Release") |
||||
endif() |
||||
|
||||
# Compilation settings that should be applied to most targets. |
||||
function(APPLY_STANDARD_SETTINGS TARGET) |
||||
target_compile_features(${TARGET} PUBLIC cxx_std_14) |
||||
target_compile_options(${TARGET} PRIVATE -Wall -Werror) |
||||
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>") |
||||
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>") |
||||
endfunction() |
||||
|
||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") |
||||
|
||||
# Flutter library and tool build rules. |
||||
add_subdirectory(${FLUTTER_MANAGED_DIR}) |
||||
|
||||
# System-level dependencies. |
||||
find_package(PkgConfig REQUIRED) |
||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) |
||||
|
||||
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") |
||||
|
||||
# Application build |
||||
add_executable(${BINARY_NAME} |
||||
"main.cc" |
||||
"my_application.cc" |
||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" |
||||
) |
||||
apply_standard_settings(${BINARY_NAME}) |
||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter) |
||||
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) |
||||
add_dependencies(${BINARY_NAME} flutter_assemble) |
||||
# Only the install-generated bundle's copy of the executable will launch |
||||
# correctly, since the resources must in the right relative locations. To avoid |
||||
# people trying to run the unbundled copy, put it in a subdirectory instead of |
||||
# the default top-level location. |
||||
set_target_properties(${BINARY_NAME} |
||||
PROPERTIES |
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" |
||||
) |
||||
|
||||
# Generated plugin build rules, which manage building the plugins and adding |
||||
# them to the application. |
||||
include(flutter/generated_plugins.cmake) |
||||
|
||||
|
||||
# === Installation === |
||||
# By default, "installing" just makes a relocatable bundle in the build |
||||
# directory. |
||||
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") |
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) |
||||
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) |
||||
endif() |
||||
|
||||
# Start with a clean build bundle directory every time. |
||||
install(CODE " |
||||
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") |
||||
" COMPONENT Runtime) |
||||
|
||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") |
||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") |
||||
|
||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" |
||||
COMPONENT Runtime) |
||||
|
||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" |
||||
COMPONENT Runtime) |
||||
|
||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" |
||||
COMPONENT Runtime) |
||||
|
||||
if(PLUGIN_BUNDLED_LIBRARIES) |
||||
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" |
||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" |
||||
COMPONENT Runtime) |
||||
endif() |
||||
|
||||
# Fully re-copy the assets directory on each build to avoid having stale files |
||||
# from a previous install. |
||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets") |
||||
install(CODE " |
||||
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") |
||||
" COMPONENT Runtime) |
||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" |
||||
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) |
||||
|
||||
# Install the AOT library on non-Debug builds only. |
||||
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") |
||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" |
||||
COMPONENT Runtime) |
||||
endif() |
@ -0,0 +1,91 @@ |
||||
cmake_minimum_required(VERSION 3.10) |
||||
|
||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") |
||||
|
||||
# Configuration provided via flutter tool. |
||||
include(${EPHEMERAL_DIR}/generated_config.cmake) |
||||
|
||||
# TODO: Move the rest of this into files in ephemeral. See |
||||
# https://github.com/flutter/flutter/issues/57146. |
||||
|
||||
# Serves the same purpose as list(TRANSFORM ... PREPEND ...), |
||||
# which isn't available in 3.10. |
||||
function(list_prepend LIST_NAME PREFIX) |
||||
set(NEW_LIST "") |
||||
foreach(element ${${LIST_NAME}}) |
||||
list(APPEND NEW_LIST "${PREFIX}${element}") |
||||
endforeach(element) |
||||
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) |
||||
endfunction() |
||||
|
||||
# === Flutter Library === |
||||
# System-level dependencies. |
||||
find_package(PkgConfig REQUIRED) |
||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) |
||||
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) |
||||
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) |
||||
pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid) |
||||
pkg_check_modules(LZMA REQUIRED IMPORTED_TARGET liblzma) |
||||
|
||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") |
||||
|
||||
# Published to parent scope for install step. |
||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) |
||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) |
||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) |
||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) |
||||
|
||||
list(APPEND FLUTTER_LIBRARY_HEADERS |
||||
"fl_basic_message_channel.h" |
||||
"fl_binary_codec.h" |
||||
"fl_binary_messenger.h" |
||||
"fl_dart_project.h" |
||||
"fl_engine.h" |
||||
"fl_json_message_codec.h" |
||||
"fl_json_method_codec.h" |
||||
"fl_message_codec.h" |
||||
"fl_method_call.h" |
||||
"fl_method_channel.h" |
||||
"fl_method_codec.h" |
||||
"fl_method_response.h" |
||||
"fl_plugin_registrar.h" |
||||
"fl_plugin_registry.h" |
||||
"fl_standard_message_codec.h" |
||||
"fl_standard_method_codec.h" |
||||
"fl_string_codec.h" |
||||
"fl_value.h" |
||||
"fl_view.h" |
||||
"flutter_linux.h" |
||||
) |
||||
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") |
||||
add_library(flutter INTERFACE) |
||||
target_include_directories(flutter INTERFACE |
||||
"${EPHEMERAL_DIR}" |
||||
) |
||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") |
||||
target_link_libraries(flutter INTERFACE |
||||
PkgConfig::GTK |
||||
PkgConfig::GLIB |
||||
PkgConfig::GIO |
||||
PkgConfig::BLKID |
||||
PkgConfig::LZMA |
||||
) |
||||
add_dependencies(flutter flutter_assemble) |
||||
|
||||
# === Flutter tool backend === |
||||
# _phony_ is a non-existent file to force this command to run every time, |
||||
# since currently there's no way to get a full input/output list from the |
||||
# flutter tool. |
||||
add_custom_command( |
||||
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} |
||||
${CMAKE_CURRENT_BINARY_DIR}/_phony_ |
||||
COMMAND ${CMAKE_COMMAND} -E env |
||||
${FLUTTER_TOOL_ENVIRONMENT} |
||||
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" |
||||
linux-x64 ${CMAKE_BUILD_TYPE} |
||||
VERBATIM |
||||
) |
||||
add_custom_target(flutter_assemble DEPENDS |
||||
"${FLUTTER_LIBRARY}" |
||||
${FLUTTER_LIBRARY_HEADERS} |
||||
) |
@ -0,0 +1,13 @@ |
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
#include "generated_plugin_registrant.h" |
||||
|
||||
#include <url_launcher_linux/url_launcher_plugin.h> |
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) { |
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = |
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); |
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); |
||||
} |
@ -0,0 +1,13 @@ |
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT_ |
||||
#define GENERATED_PLUGIN_REGISTRANT_ |
||||
|
||||
#include <flutter_linux/flutter_linux.h> |
||||
|
||||
// Registers Flutter plugins.
|
||||
void fl_register_plugins(FlPluginRegistry* registry); |
||||
|
||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
@ -0,0 +1,16 @@ |
||||
# |
||||
# Generated file, do not edit. |
||||
# |
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST |
||||
url_launcher_linux |
||||
) |
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES) |
||||
|
||||
foreach(plugin ${FLUTTER_PLUGIN_LIST}) |
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) |
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) |
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>) |
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) |
||||
endforeach(plugin) |
@ -0,0 +1,6 @@ |
||||
#include "my_application.h" |
||||
|
||||
int main(int argc, char** argv) { |
||||
g_autoptr(MyApplication) app = my_application_new(); |
||||
return g_application_run(G_APPLICATION(app), argc, argv); |
||||
} |
@ -0,0 +1,104 @@ |
||||
#include "my_application.h" |
||||
|
||||
#include <flutter_linux/flutter_linux.h> |
||||
#ifdef GDK_WINDOWING_X11 |
||||
#include <gdk/gdkx.h> |
||||
#endif |
||||
|
||||
#include "flutter/generated_plugin_registrant.h" |
||||
|
||||
struct _MyApplication { |
||||
GtkApplication parent_instance; |
||||
char** dart_entrypoint_arguments; |
||||
}; |
||||
|
||||
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) |
||||
|
||||
// Implements GApplication::activate.
|
||||
static void my_application_activate(GApplication* application) { |
||||
MyApplication* self = MY_APPLICATION(application); |
||||
GtkWindow* window = |
||||
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); |
||||
|
||||
// Use a header bar when running in GNOME as this is the common style used
|
||||
// by applications and is the setup most users will be using (e.g. Ubuntu
|
||||
// desktop).
|
||||
// If running on X and not using GNOME then just use a traditional title bar
|
||||
// in case the window manager does more exotic layout, e.g. tiling.
|
||||
// If running on Wayland assume the header bar will work (may need changing
|
||||
// if future cases occur).
|
||||
gboolean use_header_bar = TRUE; |
||||
#ifdef GDK_WINDOWING_X11 |
||||
GdkScreen *screen = gtk_window_get_screen(window); |
||||
if (GDK_IS_X11_SCREEN(screen)) { |
||||
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); |
||||
if (g_strcmp0(wm_name, "GNOME Shell") != 0) { |
||||
use_header_bar = FALSE; |
||||
} |
||||
} |
||||
#endif |
||||
if (use_header_bar) { |
||||
GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); |
||||
gtk_widget_show(GTK_WIDGET(header_bar)); |
||||
gtk_header_bar_set_title(header_bar, "app"); |
||||
gtk_header_bar_set_show_close_button(header_bar, TRUE); |
||||
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); |
||||
} |
||||
else { |
||||
gtk_window_set_title(window, "app"); |
||||
} |
||||
|
||||
gtk_window_set_default_size(window, 1280, 720); |
||||
gtk_widget_show(GTK_WIDGET(window)); |
||||
|
||||
g_autoptr(FlDartProject) project = fl_dart_project_new(); |
||||
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); |
||||
|
||||
FlView* view = fl_view_new(project); |
||||
gtk_widget_show(GTK_WIDGET(view)); |
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); |
||||
|
||||
fl_register_plugins(FL_PLUGIN_REGISTRY(view)); |
||||
|
||||
gtk_widget_grab_focus(GTK_WIDGET(view)); |
||||
} |
||||
|
||||
// Implements GApplication::local_command_line.
|
||||
static gboolean my_application_local_command_line(GApplication* application, gchar ***arguments, int *exit_status) { |
||||
MyApplication* self = MY_APPLICATION(application); |
||||
// Strip out the first argument as it is the binary name.
|
||||
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); |
||||
|
||||
g_autoptr(GError) error = nullptr; |
||||
if (!g_application_register(application, nullptr, &error)) { |
||||
g_warning("Failed to register: %s", error->message); |
||||
*exit_status = 1; |
||||
return TRUE; |
||||
} |
||||
|
||||
g_application_activate(application); |
||||
*exit_status = 0; |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
// Implements GObject::dispose.
|
||||
static void my_application_dispose(GObject *object) { |
||||
MyApplication* self = MY_APPLICATION(object); |
||||
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); |
||||
G_OBJECT_CLASS(my_application_parent_class)->dispose(object); |
||||
} |
||||
|
||||
static void my_application_class_init(MyApplicationClass* klass) { |
||||
G_APPLICATION_CLASS(klass)->activate = my_application_activate; |
||||
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; |
||||
G_OBJECT_CLASS(klass)->dispose = my_application_dispose; |
||||
} |
||||
|
||||
static void my_application_init(MyApplication* self) {} |
||||
|
||||
MyApplication* my_application_new() { |
||||
return MY_APPLICATION(g_object_new(my_application_get_type(), |
||||
"application-id", APPLICATION_ID, |
||||
nullptr)); |
||||
} |
@ -0,0 +1,18 @@ |
||||
#ifndef FLUTTER_MY_APPLICATION_H_ |
||||
#define FLUTTER_MY_APPLICATION_H_ |
||||
|
||||
#include <gtk/gtk.h> |
||||
|
||||
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, |
||||
GtkApplication) |
||||
|
||||
/**
|
||||
* my_application_new: |
||||
* |
||||
* Creates a new Flutter-based application. |
||||
* |
||||
* Returns: a new #MyApplication. |
||||
*/ |
||||
MyApplication* my_application_new(); |
||||
|
||||
#endif // FLUTTER_MY_APPLICATION_H_
|
@ -0,0 +1,7 @@ |
||||
# Flutter-related |
||||
**/Flutter/ephemeral/ |
||||
**/Pods/ |
||||
|
||||
# Xcode-related |
||||
**/xcuserdata/ |
||||
Podfile.lock |
@ -0,0 +1,2 @@ |
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" |
||||
#include "ephemeral/Flutter-Generated.xcconfig" |
@ -0,0 +1,2 @@ |
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" |
||||
#include "ephemeral/Flutter-Generated.xcconfig" |
@ -0,0 +1,14 @@ |
||||
// |
||||
// Generated file. Do not edit. |
||||
// |
||||
|
||||
import FlutterMacOS |
||||
import Foundation |
||||
|
||||
import path_provider_macos |
||||
import url_launcher_macos |
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { |
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) |
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) |
||||
} |
@ -0,0 +1,40 @@ |
||||
platform :osx, '10.11' |
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency. |
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true' |
||||
|
||||
project 'Runner', { |
||||
'Debug' => :debug, |
||||
'Profile' => :release, |
||||
'Release' => :release, |
||||
} |
||||
|
||||
def flutter_root |
||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) |
||||
unless File.exist?(generated_xcode_build_settings_path) |
||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" |
||||
end |
||||
|
||||
File.foreach(generated_xcode_build_settings_path) do |line| |
||||
matches = line.match(/FLUTTER_ROOT\=(.*)/) |
||||
return matches[1].strip if matches |
||||
end |
||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" |
||||
end |
||||
|
||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) |
||||
|
||||
flutter_macos_podfile_setup |
||||
|
||||
target 'Runner' do |
||||
use_frameworks! |
||||
use_modular_headers! |
||||
|
||||
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) |
||||
end |
||||
|
||||
post_install do |installer| |
||||
installer.pods_project.targets.each do |target| |
||||
flutter_additional_macos_build_settings(target) |
||||
end |
||||
end |
@ -0,0 +1,632 @@ |
||||
// !$*UTF8*$! |
||||
{ |
||||
archiveVersion = 1; |
||||
classes = { |
||||
}; |
||||
objectVersion = 51; |
||||
objects = { |
||||
|
||||
/* Begin PBXAggregateTarget section */ |
||||
33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { |
||||
isa = PBXAggregateTarget; |
||||
buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; |
||||
buildPhases = ( |
||||
33CC111E2044C6BF0003C045 /* ShellScript */, |
||||
); |
||||
dependencies = ( |
||||
); |
||||
name = "Flutter Assemble"; |
||||
productName = FLX; |
||||
}; |
||||
/* End PBXAggregateTarget section */ |
||||
|
||||
/* Begin PBXBuildFile section */ |
||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; |
||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; |
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; |
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; |
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; |
||||
7C7D9700842BA0E01048B7B5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93FCB7C0C7A612A19EB2D2C2 /* Pods_Runner.framework */; }; |
||||
/* End PBXBuildFile section */ |
||||
|
||||
/* Begin PBXContainerItemProxy section */ |
||||
33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { |
||||
isa = PBXContainerItemProxy; |
||||
containerPortal = 33CC10E52044A3C60003C045 /* Project object */; |
||||
proxyType = 1; |
||||
remoteGlobalIDString = 33CC111A2044C6BA0003C045; |
||||
remoteInfo = FLX; |
||||
}; |
||||
/* End PBXContainerItemProxy section */ |
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */ |
||||
33CC110E2044A8840003C045 /* Bundle Framework */ = { |
||||
isa = PBXCopyFilesBuildPhase; |
||||
buildActionMask = 2147483647; |
||||
dstPath = ""; |
||||
dstSubfolderSpec = 10; |
||||
files = ( |
||||
); |
||||
name = "Bundle Framework"; |
||||
runOnlyForDeploymentPostprocessing = 0; |
||||
}; |
||||
/* End PBXCopyFilesBuildPhase section */ |
||||
|
||||
/* Begin PBXFileReference section */ |
||||
0C1FD22CA47E09B485C5D2F0 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; }; |
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; }; |
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; }; |
||||
33CC10ED2044A3C60003C045 /* app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = app.app; sourceTree = BUILT_PRODUCTS_DIR; }; |
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; |
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; }; |
||||
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; }; |
||||
33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; }; |
||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; }; |
||||
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; }; |
||||
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; }; |
||||
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; }; |
||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; }; |
||||
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; }; |
||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; }; |
||||
4B8510D07EAD5FFD466A09A7 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; }; |
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; }; |
||||
93FCB7C0C7A612A19EB2D2C2 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; |
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; }; |
||||
F44289D50723316BB0B4ADA1 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; }; |
||||
/* End PBXFileReference section */ |
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */ |
||||
33CC10EA2044A3C60003C045 /* Frameworks */ = { |
||||
isa = PBXFrameworksBuildPhase; |
||||
buildActionMask = 2147483647; |
||||
files = ( |
||||
7C7D9700842BA0E01048B7B5 /* Pods_Runner.framework in Frameworks */, |
||||
); |
||||
runOnlyForDeploymentPostprocessing = 0; |
||||
}; |
||||
/* End PBXFrameworksBuildPhase section */ |
||||
|
||||
/* Begin PBXGroup section */ |
||||
33BA886A226E78AF003329D5 /* Configs */ = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */, |
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */, |
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */, |
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */, |
||||
); |
||||
path = Configs; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
33CC10E42044A3C60003C045 = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
33FAB671232836740065AC1E /* Runner */, |
||||
33CEB47122A05771004F2AC0 /* Flutter */, |
||||
33CC10EE2044A3C60003C045 /* Products */, |
||||
D73912EC22F37F3D000D13A0 /* Frameworks */, |
||||
D4C5240DF6823DEC9AB0AD3D /* Pods */, |
||||
); |
||||
sourceTree = "<group>"; |
||||
}; |
||||
33CC10EE2044A3C60003C045 /* Products */ = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
33CC10ED2044A3C60003C045 /* app.app */, |
||||
); |
||||
name = Products; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
33CC11242044D66E0003C045 /* Resources */ = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */, |
||||
33CC10F42044A3C60003C045 /* MainMenu.xib */, |
||||
33CC10F72044A3C60003C045 /* Info.plist */, |
||||
); |
||||
name = Resources; |
||||
path = ..; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
33CEB47122A05771004F2AC0 /* Flutter */ = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, |
||||
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, |
||||
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, |
||||
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, |
||||
); |
||||
path = Flutter; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
33FAB671232836740065AC1E /* Runner */ = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */, |
||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, |
||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */, |
||||
33E51914231749380026EE4D /* Release.entitlements */, |
||||
33CC11242044D66E0003C045 /* Resources */, |
||||
33BA886A226E78AF003329D5 /* Configs */, |
||||
); |
||||
path = Runner; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
D4C5240DF6823DEC9AB0AD3D /* Pods */ = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
0C1FD22CA47E09B485C5D2F0 /* Pods-Runner.debug.xcconfig */, |
||||
4B8510D07EAD5FFD466A09A7 /* Pods-Runner.release.xcconfig */, |
||||
F44289D50723316BB0B4ADA1 /* Pods-Runner.profile.xcconfig */, |
||||
); |
||||
name = Pods; |
||||
path = Pods; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
D73912EC22F37F3D000D13A0 /* Frameworks */ = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
93FCB7C0C7A612A19EB2D2C2 /* Pods_Runner.framework */, |
||||
); |
||||
name = Frameworks; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
/* End PBXGroup section */ |
||||
|
||||
/* Begin PBXNativeTarget section */ |
||||
33CC10EC2044A3C60003C045 /* Runner */ = { |
||||
isa = PBXNativeTarget; |
||||
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; |
||||
buildPhases = ( |
||||
ECE07D1381B49CCA8A8E0C5F /* [CP] Check Pods Manifest.lock */, |
||||
33CC10E92044A3C60003C045 /* Sources */, |
||||
33CC10EA2044A3C60003C045 /* Frameworks */, |
||||
33CC10EB2044A3C60003C045 /* Resources */, |
||||
33CC110E2044A8840003C045 /* Bundle Framework */, |
||||
3399D490228B24CF009A79C7 /* ShellScript */, |
||||
678C02007C3A278E6325D529 /* [CP] Embed Pods Frameworks */, |
||||
); |
||||
buildRules = ( |
||||
); |
||||
dependencies = ( |
||||
33CC11202044C79F0003C045 /* PBXTargetDependency */, |
||||
); |
||||
name = Runner; |
||||
productName = Runner; |
||||
productReference = 33CC10ED2044A3C60003C045 /* app.app */; |
||||
productType = "com.apple.product-type.application"; |
||||
}; |
||||
/* End PBXNativeTarget section */ |
||||
|
||||
/* Begin PBXProject section */ |
||||
33CC10E52044A3C60003C045 /* Project object */ = { |
||||
isa = PBXProject; |
||||
attributes = { |
||||
LastSwiftUpdateCheck = 0920; |
||||
LastUpgradeCheck = 0930; |
||||
ORGANIZATIONNAME = ""; |
||||
TargetAttributes = { |
||||
33CC10EC2044A3C60003C045 = { |
||||
CreatedOnToolsVersion = 9.2; |
||||
LastSwiftMigration = 1100; |
||||
ProvisioningStyle = Automatic; |
||||
SystemCapabilities = { |
||||
com.apple.Sandbox = { |
||||
enabled = 1; |
||||
}; |
||||
}; |
||||
}; |
||||
33CC111A2044C6BA0003C045 = { |
||||
CreatedOnToolsVersion = 9.2; |
||||
ProvisioningStyle = Manual; |
||||
}; |
||||
}; |
||||
}; |
||||
buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; |
||||
compatibilityVersion = "Xcode 9.3"; |
||||
developmentRegion = en; |
||||
hasScannedForEncodings = 0; |
||||
knownRegions = ( |
||||
en, |
||||
Base, |
||||
); |
||||
mainGroup = 33CC10E42044A3C60003C045; |
||||
productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; |
||||
projectDirPath = ""; |
||||
projectRoot = ""; |
||||
targets = ( |
||||
33CC10EC2044A3C60003C045 /* Runner */, |
||||
33CC111A2044C6BA0003C045 /* Flutter Assemble */, |
||||
); |
||||
}; |
||||
/* End PBXProject section */ |
||||
|
||||
/* Begin PBXResourcesBuildPhase section */ |
||||
33CC10EB2044A3C60003C045 /* Resources */ = { |
||||
isa = PBXResourcesBuildPhase; |
||||
buildActionMask = 2147483647; |
||||
files = ( |
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, |
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, |
||||
); |
||||
runOnlyForDeploymentPostprocessing = 0; |
||||
}; |
||||
/* End PBXResourcesBuildPhase section */ |
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */ |
||||
3399D490228B24CF009A79C7 /* ShellScript */ = { |
||||
isa = PBXShellScriptBuildPhase; |
||||
buildActionMask = 2147483647; |
||||
files = ( |
||||
); |
||||
inputFileListPaths = ( |
||||
); |
||||
inputPaths = ( |
||||
); |
||||
outputFileListPaths = ( |
||||
); |
||||
outputPaths = ( |
||||
); |
||||
runOnlyForDeploymentPostprocessing = 0; |
||||
shellPath = /bin/sh; |
||||
shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; |
||||
}; |
||||
33CC111E2044C6BF0003C045 /* ShellScript */ = { |
||||
isa = PBXShellScriptBuildPhase; |
||||
buildActionMask = 2147483647; |
||||
files = ( |
||||
); |
||||
inputFileListPaths = ( |
||||
Flutter/ephemeral/FlutterInputs.xcfilelist, |
||||
); |
||||
inputPaths = ( |
||||
Flutter/ephemeral/tripwire, |
||||
); |
||||
outputFileListPaths = ( |
||||
Flutter/ephemeral/FlutterOutputs.xcfilelist, |
||||
); |
||||
outputPaths = ( |
||||
); |
||||
runOnlyForDeploymentPostprocessing = 0; |
||||
shellPath = /bin/sh; |
||||
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; |
||||
}; |
||||
678C02007C3A278E6325D529 /* [CP] Embed Pods Frameworks */ = { |
||||
isa = PBXShellScriptBuildPhase; |
||||
buildActionMask = 2147483647; |
||||
files = ( |
||||
); |
||||
inputFileListPaths = ( |
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", |
||||
); |
||||
name = "[CP] Embed Pods Frameworks"; |
||||
outputFileListPaths = ( |
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", |
||||
); |
||||
runOnlyForDeploymentPostprocessing = 0; |
||||
shellPath = /bin/sh; |
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; |
||||
showEnvVarsInLog = 0; |
||||
}; |
||||
ECE07D1381B49CCA8A8E0C5F /* [CP] Check Pods Manifest.lock */ = { |
||||
isa = PBXShellScriptBuildPhase; |
||||
buildActionMask = 2147483647; |
||||
files = ( |
||||
); |
||||
inputFileListPaths = ( |
||||
); |
||||
inputPaths = ( |
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock", |
||||
"${PODS_ROOT}/Manifest.lock", |
||||
); |
||||
name = "[CP] Check Pods Manifest.lock"; |
||||
outputFileListPaths = ( |
||||
); |
||||
outputPaths = ( |
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", |
||||
); |
||||
runOnlyForDeploymentPostprocessing = 0; |
||||
shellPath = /bin/sh; |
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; |
||||
showEnvVarsInLog = 0; |
||||
}; |
||||
/* End PBXShellScriptBuildPhase section */ |
||||
|
||||
/* Begin PBXSourcesBuildPhase section */ |
||||
33CC10E92044A3C60003C045 /* Sources */ = { |
||||
isa = PBXSourcesBuildPhase; |
||||
buildActionMask = 2147483647; |
||||
files = ( |
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, |
||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, |
||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, |
||||
); |
||||
runOnlyForDeploymentPostprocessing = 0; |
||||
}; |
||||
/* End PBXSourcesBuildPhase section */ |
||||
|
||||
/* Begin PBXTargetDependency section */ |
||||
33CC11202044C79F0003C045 /* PBXTargetDependency */ = { |
||||
isa = PBXTargetDependency; |
||||
target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; |
||||
targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; |
||||
}; |
||||
/* End PBXTargetDependency section */ |
||||
|
||||
/* Begin PBXVariantGroup section */ |
||||
33CC10F42044A3C60003C045 /* MainMenu.xib */ = { |
||||
isa = PBXVariantGroup; |
||||
children = ( |
||||
33CC10F52044A3C60003C045 /* Base */, |
||||
); |
||||
name = MainMenu.xib; |
||||
path = Runner; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
/* End PBXVariantGroup section */ |
||||
|
||||
/* Begin XCBuildConfiguration section */ |
||||
338D0CE9231458BD00FA5F75 /* Profile */ = { |
||||
isa = XCBuildConfiguration; |
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; |
||||
buildSettings = { |
||||
ALWAYS_SEARCH_USER_PATHS = NO; |
||||
CLANG_ANALYZER_NONNULL = YES; |
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; |
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; |
||||
CLANG_CXX_LIBRARY = "libc++"; |
||||
CLANG_ENABLE_MODULES = YES; |
||||
CLANG_ENABLE_OBJC_ARC = YES; |
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; |
||||
CLANG_WARN_BOOL_CONVERSION = YES; |
||||
CLANG_WARN_CONSTANT_CONVERSION = YES; |
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; |
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; |
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES; |
||||
CLANG_WARN_EMPTY_BODY = YES; |
||||
CLANG_WARN_ENUM_CONVERSION = YES; |
||||
CLANG_WARN_INFINITE_RECURSION = YES; |
||||
CLANG_WARN_INT_CONVERSION = YES; |
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; |
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; |
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; |
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; |
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES; |
||||
CODE_SIGN_IDENTITY = "-"; |
||||
COPY_PHASE_STRIP = NO; |
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; |
||||
ENABLE_NS_ASSERTIONS = NO; |
||||
ENABLE_STRICT_OBJC_MSGSEND = YES; |
||||
GCC_C_LANGUAGE_STANDARD = gnu11; |
||||
GCC_NO_COMMON_BLOCKS = YES; |
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; |
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; |
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
||||
GCC_WARN_UNUSED_FUNCTION = YES; |
||||
GCC_WARN_UNUSED_VARIABLE = YES; |
||||
MACOSX_DEPLOYMENT_TARGET = 10.11; |
||||
MTL_ENABLE_DEBUG_INFO = NO; |
||||
SDKROOT = macosx; |
||||
SWIFT_COMPILATION_MODE = wholemodule; |
||||
SWIFT_OPTIMIZATION_LEVEL = "-O"; |
||||
}; |
||||
name = Profile; |
||||
}; |
||||
338D0CEA231458BD00FA5F75 /* Profile */ = { |
||||
isa = XCBuildConfiguration; |
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; |
||||
buildSettings = { |
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
||||
CLANG_ENABLE_MODULES = YES; |
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; |
||||
CODE_SIGN_STYLE = Automatic; |
||||
COMBINE_HIDPI_IMAGES = YES; |
||||
INFOPLIST_FILE = Runner/Info.plist; |
||||
LD_RUNPATH_SEARCH_PATHS = ( |
||||
"$(inherited)", |
||||
"@executable_path/../Frameworks", |
||||
); |
||||
PROVISIONING_PROFILE_SPECIFIER = ""; |
||||
SWIFT_VERSION = 5.0; |
||||
}; |
||||
name = Profile; |
||||
}; |
||||
338D0CEB231458BD00FA5F75 /* Profile */ = { |
||||
isa = XCBuildConfiguration; |
||||
buildSettings = { |
||||
CODE_SIGN_STYLE = Manual; |
||||
PRODUCT_NAME = "$(TARGET_NAME)"; |
||||
}; |
||||
name = Profile; |
||||
}; |
||||
33CC10F92044A3C60003C045 /* Debug */ = { |
||||
isa = XCBuildConfiguration; |
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; |
||||
buildSettings = { |
||||
ALWAYS_SEARCH_USER_PATHS = NO; |
||||
CLANG_ANALYZER_NONNULL = YES; |
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; |
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; |
||||
CLANG_CXX_LIBRARY = "libc++"; |
||||
CLANG_ENABLE_MODULES = YES; |
||||
CLANG_ENABLE_OBJC_ARC = YES; |
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; |
||||
CLANG_WARN_BOOL_CONVERSION = YES; |
||||
CLANG_WARN_CONSTANT_CONVERSION = YES; |
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; |
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; |
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES; |
||||
CLANG_WARN_EMPTY_BODY = YES; |
||||
CLANG_WARN_ENUM_CONVERSION = YES; |
||||
CLANG_WARN_INFINITE_RECURSION = YES; |
||||
CLANG_WARN_INT_CONVERSION = YES; |
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; |
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; |
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; |
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; |
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES; |
||||
CODE_SIGN_IDENTITY = "-"; |
||||
COPY_PHASE_STRIP = NO; |
||||
DEBUG_INFORMATION_FORMAT = dwarf; |
||||
ENABLE_STRICT_OBJC_MSGSEND = YES; |
||||
ENABLE_TESTABILITY = YES; |
||||
GCC_C_LANGUAGE_STANDARD = gnu11; |
||||
GCC_DYNAMIC_NO_PIC = NO; |
||||
GCC_NO_COMMON_BLOCKS = YES; |
||||
GCC_OPTIMIZATION_LEVEL = 0; |
||||
GCC_PREPROCESSOR_DEFINITIONS = ( |
||||
"DEBUG=1", |
||||
"$(inherited)", |
||||
); |
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; |
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; |
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
||||
GCC_WARN_UNUSED_FUNCTION = YES; |
||||
GCC_WARN_UNUSED_VARIABLE = YES; |
||||
MACOSX_DEPLOYMENT_TARGET = 10.11; |
||||
MTL_ENABLE_DEBUG_INFO = YES; |
||||
ONLY_ACTIVE_ARCH = YES; |
||||
SDKROOT = macosx; |
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; |
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; |
||||
}; |
||||
name = Debug; |
||||
}; |
||||
33CC10FA2044A3C60003C045 /* Release */ = { |
||||
isa = XCBuildConfiguration; |
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; |
||||
buildSettings = { |
||||
ALWAYS_SEARCH_USER_PATHS = NO; |
||||
CLANG_ANALYZER_NONNULL = YES; |
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; |
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; |
||||
CLANG_CXX_LIBRARY = "libc++"; |
||||
CLANG_ENABLE_MODULES = YES; |
||||
CLANG_ENABLE_OBJC_ARC = YES; |
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; |
||||
CLANG_WARN_BOOL_CONVERSION = YES; |
||||
CLANG_WARN_CONSTANT_CONVERSION = YES; |
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; |
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; |
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES; |
||||
CLANG_WARN_EMPTY_BODY = YES; |
||||
CLANG_WARN_ENUM_CONVERSION = YES; |
||||
CLANG_WARN_INFINITE_RECURSION = YES; |
||||
CLANG_WARN_INT_CONVERSION = YES; |
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; |
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; |
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; |
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; |
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES; |
||||
CODE_SIGN_IDENTITY = "-"; |
||||
COPY_PHASE_STRIP = NO; |
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; |
||||
ENABLE_NS_ASSERTIONS = NO; |
||||
ENABLE_STRICT_OBJC_MSGSEND = YES; |
||||
GCC_C_LANGUAGE_STANDARD = gnu11; |
||||
GCC_NO_COMMON_BLOCKS = YES; |
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; |
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; |
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
||||
GCC_WARN_UNUSED_FUNCTION = YES; |
||||
GCC_WARN_UNUSED_VARIABLE = YES; |
||||
MACOSX_DEPLOYMENT_TARGET = 10.11; |
||||
MTL_ENABLE_DEBUG_INFO = NO; |
||||
SDKROOT = macosx; |
||||
SWIFT_COMPILATION_MODE = wholemodule; |
||||
SWIFT_OPTIMIZATION_LEVEL = "-O"; |
||||
}; |
||||
name = Release; |
||||
}; |
||||
33CC10FC2044A3C60003C045 /* Debug */ = { |
||||
isa = XCBuildConfiguration; |
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; |
||||
buildSettings = { |
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
||||
CLANG_ENABLE_MODULES = YES; |
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; |
||||
CODE_SIGN_STYLE = Automatic; |
||||
COMBINE_HIDPI_IMAGES = YES; |
||||
INFOPLIST_FILE = Runner/Info.plist; |
||||
LD_RUNPATH_SEARCH_PATHS = ( |
||||
"$(inherited)", |
||||
"@executable_path/../Frameworks", |
||||
); |
||||
PROVISIONING_PROFILE_SPECIFIER = ""; |
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; |
||||
SWIFT_VERSION = 5.0; |
||||
}; |
||||
name = Debug; |
||||
}; |
||||
33CC10FD2044A3C60003C045 /* Release */ = { |
||||
isa = XCBuildConfiguration; |
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; |
||||
buildSettings = { |
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
||||
CLANG_ENABLE_MODULES = YES; |
||||
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; |
||||
CODE_SIGN_STYLE = Automatic; |
||||
COMBINE_HIDPI_IMAGES = YES; |
||||
INFOPLIST_FILE = Runner/Info.plist; |
||||
LD_RUNPATH_SEARCH_PATHS = ( |
||||
"$(inherited)", |
||||
"@executable_path/../Frameworks", |
||||
); |
||||
PROVISIONING_PROFILE_SPECIFIER = ""; |
||||
SWIFT_VERSION = 5.0; |
||||
}; |
||||
name = Release; |
||||
}; |
||||
33CC111C2044C6BA0003C045 /* Debug */ = { |
||||
isa = XCBuildConfiguration; |
||||
buildSettings = { |
||||
CODE_SIGN_STYLE = Manual; |
||||
PRODUCT_NAME = "$(TARGET_NAME)"; |
||||
}; |
||||
name = Debug; |
||||
}; |
||||
33CC111D2044C6BA0003C045 /* Release */ = { |
||||
isa = XCBuildConfiguration; |
||||
buildSettings = { |
||||
CODE_SIGN_STYLE = Automatic; |
||||
PRODUCT_NAME = "$(TARGET_NAME)"; |
||||
}; |
||||
name = Release; |
||||
}; |
||||
/* End XCBuildConfiguration section */ |
||||
|
||||
/* Begin XCConfigurationList section */ |
||||
33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { |
||||
isa = XCConfigurationList; |
||||
buildConfigurations = ( |
||||
33CC10F92044A3C60003C045 /* Debug */, |
||||
33CC10FA2044A3C60003C045 /* Release */, |
||||
338D0CE9231458BD00FA5F75 /* Profile */, |
||||
); |
||||
defaultConfigurationIsVisible = 0; |
||||
defaultConfigurationName = Release; |
||||
}; |
||||
33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { |
||||
isa = XCConfigurationList; |
||||
buildConfigurations = ( |
||||
33CC10FC2044A3C60003C045 /* Debug */, |
||||
33CC10FD2044A3C60003C045 /* Release */, |
||||
338D0CEA231458BD00FA5F75 /* Profile */, |
||||
); |
||||
defaultConfigurationIsVisible = 0; |
||||
defaultConfigurationName = Release; |
||||
}; |
||||
33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { |
||||
isa = XCConfigurationList; |
||||
buildConfigurations = ( |
||||
33CC111C2044C6BA0003C045 /* Debug */, |
||||
33CC111D2044C6BA0003C045 /* Release */, |
||||
338D0CEB231458BD00FA5F75 /* Profile */, |
||||
); |
||||
defaultConfigurationIsVisible = 0; |
||||
defaultConfigurationName = Release; |
||||
}; |
||||
/* End XCConfigurationList section */ |
||||
}; |
||||
rootObject = 33CC10E52044A3C60003C045 /* Project object */; |
||||
} |