Can I run a CLI command inside a flutter project - flutter

When I click the Boilerplate button I want to run the CLI command "flutter create projectName" (inside a flutter project/dart file)
I have already heard about
process.run
import 'dart:io';
main() async {
// List all files in the current directory in UNIX-like systems.
var result = await Process.run('ls', ['-l']);
print(result.stdout);
}
&
shell
var shell = Shell();
await shell.run('''
echo "hello world"
''');
But I don't know how to use in this situation

Related

How to launch another app from the flutter desktop application?

I have a flutter application that communicates to a server in the same machine. So now I need to start the server with the flutter app automatically. So is there any way to start the server when I start the flutter app and kill the server when I close the flutter app?
If is in windows you can use the package Win32 :
https://pub.dev/packages/win32
try {
final verb = 'open'.toNativeUtf16();
final process = 'app.exe'.toNativeUtf16();
final params = 'p1'.toNativeUtf16();
final nullParams = ''.toNativeUtf16();
ShellExecute(0, verb, process, params, nullParams, SW_SHOW);
return true;
}catch(_){
return false;
}
For Linux u can use process run:
https://pub.dev/packages/process_run
var shell = Shell();
await shell.run('''
app.sh
''');

Flutter Web - Save ui.Image to png File

I need some help with my code, I use the
"FilePicker.platform.saveFile()"
function to get the path on Windows Version (but not works on Web) and then
"final imageFuture = await controller
.renderImage(backgroundImageSize)
.then<Uint8List?>((ui.Image image) => image.pngBytes);
final imgFile = File(path);
imgFile.writeAsBytesSync(imageFuture!);
"
to save my image to disk, this works perfectly on Windows, but not on the web version.I need an alternative to save ui.Image (web Version) to PNG File on disk. 🙏🙏
I was able to solve my problem only, however the solution works only in release mode (after the build process).
import 'dart:html' as html;
import 'dart:js' as js;
final backgroundImageSize = Size(backgroundImage!.width.toDouble(),
backgroundImage!.height.toDouble());
final imageFuture = await controller
.renderImage(backgroundImageSize)
.then<Uint8List?>((ui.Image image) => image.pngBytes);
(imageFuture != null)
? js.context.callMethod(
"saveAs",
[
html.Blob([imageFuture]),
'output-image.png',
],
)
: print('Image is null');
It is necessary to add inside your web/index.html file:
<script src="https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.21.15/plugins/export/libs/FileSaver.js/FileSaver.min.js"></script>

Flutter proper way to test dart:ui on Android device

I faced following problem:
My Android Flutter app has a serie of dart:ui calls, basically to do an application files backup. Lets just check how to test that it find the correct path of the app files. The function to test:
static Future<String> getUserPath() async {
final appDocDir = await getApplicationDocumentsDirectory();
final pathComponents = path.split(appDocDir.path);
pathComponents.removeLast();
final filepaths = path.join(path.joinAll(pathComponents), 'files', '.user');
if (!await Directory(filepaths).exists()) throw FileSystemException('User directory not found');
return filepaths;
}
Easy, it call different dart:ui functions to check where the user files are. It works now, but I want to write the test for this funcion. Basically I found two ways to test this is: using Flutter Drive tests to write integration tests, i followed this tutorial: https://flutter-website-staging.firebaseapp.com/testing/ . And using Flutter integration tests, using this guide: https://docs.flutter.dev/testing/integration-tests.
The test I wrote is next:
testWidgets('test_correct_path', (WidgetTester tester) async {
print('user folder: ' + await getUserPath());
assert('.user' == basename(await getUserPath()));
});
Using driver tests
I created the following folder on my project:
test_driver
├── backup.dart
└── backup_test.dart
On backup.dart
// This line imports the extension
import 'package:flutter_driver/driver_extension.dart';
import 'package:elRepoIo/main.dart' as app;
void main() {
// This line enables the extension
enableFlutterDriverExtension();
}
And on backup_test.dart I just added the needed functions after test main declaration:
void main() {
FlutterDriver driver;
// connect flutter driver to the app before executing the runs
setUpAll(() async {
driver = await FlutterDriver.connect();
});
// disconnect flutter driver from the app after executing the runs
tearDownAll(() async {
if (driver != null) {
driver.close();
}
});
// Tests down here
Then when I execute the tests using flutter drive --target=test_driver/backup.dart I receive a bunch of errors such flutter/packages/flutter_test/lib/src/frame_timing_summarizer.dart:5:8: Error: Not found: 'dart:ui' import 'dart:ui';
Using integration tests
Under
integration_test
├── backup_test.dart
I wrote the tests adding the following line:
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized(); // NEW
Then I run the test using flutter test integration_test/backup_test.dart -d $device_id where I get device_id using flutter devices.
If I debug this I found that the path is correct, but await Directory(filepaths).exists() is false.
It seem that if I run the app to create the folder and inmetially I run the tests the directory exist. Are integration tests deleting all file data? And how can I keep it?

Separate development from deployment assets in Flutter

I am using some assets during my development (fake API responses and random images), and for that, I am loading some assets.
Obviously I do not want those assets to be bundled with the release APK, how do you come around doing so?
For now, I have all assets in one pubspec.yaml.
The end goal is to be able to run the app flutter run and have fake backend. I know of mocking HTTP calls, but it is very difficult to wrap a full app, so now I have two different data source (one from assets and another http-based), and I call the one depending on kReleaseMode value.
Thanks!
I had the same problem (which also seems to be an orphaned flutter issue), but solved it using a Builder running in the dart build_runner - not to be confused with the flutter Builder pattern for widgets (which spoils the search results). This works as sketched here:
collect dev-resources in a separate directory out of assets (in my case lib/devdata/)
create a Builder implementation and a build.yaml file
in build.yaml create separate dev_properties that allow the builder to behave according to the build mode, i.e. either copy the files to assets/devdata/ or delete them in assets/devdata/ and this directory to .gitignore
add assets/devdata/ to assets in pubspec.yaml
run build_runner either in dev or in prod mode to copy or delete the files
consume the files in the app using rootBundle if they are present / catch the resulting exception if they are absent
this command invokes the build_runner in dev / release mode respectively:
$ flutter pub run build_runner build
$ flutter pub run build_runner build --release
the builder looks roughly as follows (saved in lib/devdata/devdata.dart):
import 'dart:async';
import 'dart:io';
import 'package:build/build.dart';
Builder devData(BuilderOptions options) => DevDataBuilder(options);
class DevDataBuilder implements Builder {
final BuilderOptions options;
DevDataBuilder(this.options);
#override
FutureOr<void> build(BuildStep buildStep) async {
var mode = options.config['mode'];
var inputId = buildStep.inputId;
var sourcePath = inputId.path;
var targetPath = sourcePath.replaceFirst('lib/devdata/', 'assets/devdata/');
final outputId = AssetId(
inputId.package,
targetPath,
);
if (mode == 'dev') {
log.info('copying $sourcePath to $targetPath');
var contents = await buildStep.readAsString(inputId);
await buildStep.writeAsString(outputId, contents);
} else {
var file = File(targetPath);
if (await file.exists()) {
log.info('deleting $targetPath');
file.delete();
}
}
}
#override
Map<String, List<String>> get buildExtensions {
return {
'lib/devdata/{{file}}.json': const ['assets/devdata/{{file}}.json'],
};
}
}
the corresponding build.yaml is here:
builders:
test_data:
import: 'package:my_app_package/builder/devdata.dart'
builder_factories: ['devData']
build_extensions: {"lib/devdata/{{file}}.json": ["assets/testdata/{{file}}.json"]}
build_to: source
auto_apply: root_package
defaults:
generate_for:
include:
- lib/devdata/**
global_options:
my_app_package:test_data:
options:
mode: prod
dev_options:
mode: dev
here are some additional resources that led to this approach:
https://pub.dev/packages/build
https://pub.dev/packages/build_config
https://pub.dev/packages/build_runner
https://github.com/dart-lang/build/tree/master/example
https://github.com/dart-lang/build/blob/master/docs/build_yaml_format.md
https://pedromarquez.dev/blog/2022/8/flutter-code-gen-1
https://pedromarquez.dev/blog/2022/9/flutter-code-gen-2
https://github.com/flutter/flutter/issues/5813
https://github.com/flutter/flutter/pull/25487
an alternative approach without a builder can be found here (using the pr #25487 mentioned above):
https://github.com/sestegra/flutter_assets_flavors

Replacing InteractiveShellEmbed with Qt console

I am running embedded ipython console via (simplified):
# the code uses PyQt4, this makes sure it is initialized properly
import IPython.lib.inputhook
qapp=IPython.lib.inputhook.enable_gui(gui='qt4')
# create the embedded terminal
from IPython.frontend.terminal.embed import InteractiveShellEmbed
ipshell=InteractiveShellEmbed()
ipshell()
What would this code look like if I would like to run ipython's Qt console instead of the embedded terminal shell? There are examples of using ipython qtconsole all around, but not how to integrate it into my own code.
There is an example script that works in this question: Embedding IPython Qt console in a PyQt application
Here you can find it for reference:
from IPython.zmq.ipkernel import IPKernelApp
from IPython.lib.kernel import find_connection_file
from IPython.frontend.qt.kernelmanager import QtKernelManager
from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
from IPython.utils.traitlets import TraitError
from PySide import QtGui, QtCore
import atexit
def event_loop(kernel):
kernel.timer = QtCore.QTimer()
kernel.timer.timeout.connect(kernel.do_one_iteration)
kernel.timer.start(1000*kernel._poll_interval)
def default_kernel_app():
app = IPKernelApp.instance()
app.initialize(['python', '--pylab=qt', '--profile=plask'])
app.kernel.eventloop = event_loop
return app
def default_manager(kernel):
connection_file = find_connection_file(kernel.connection_file)
manager = QtKernelManager(connection_file=connection_file)
manager.load_connection_file()
manager.start_channels()
atexit.register(manager.cleanup_connection_file)
return manager
def console_widget(manager):
try: # Ipython v0.13
widget = RichIPythonWidget(gui_completion='droplist')
except TraitError: # IPython v0.12
widget = RichIPythonWidget(gui_completion=True)
widget.kernel_manager = manager
return widget
def terminal_widget(**kwargs):
kernel_app = default_kernel_app()
manager = default_manager(kernel_app)
widget = console_widget(manager)
# Update namespace
kernel_app.shell.user_ns.update(kwargs)
kernel_app.start()
return widget
# This simply opens qtconsole widged in a new window. But you can find embed it wherever you want
app = QtGui.QApplication([''])
widget = terminal_widget(testing=123)
widget.setWindowTitle("Your console")
widget.show()
app.exec_()