Flutter web paste image from clipboard to <List>Uint8List - flutter

My flutter web feature right now can be able to select files from disk to Uint8List. With Uint8List I can display selected images by widget.
Now I am adding more feature to the web. My motivation is Twitter copy/paste image and post.
The following is my attempt to read image from memory, but it return null to me.
import 'dart:convert';
import 'dart:typed_data';
import 'package:pasteboard/pasteboard.dart';
import 'package:flutter/material.dart';
class Experiment extends StatefulWidget {
static const String routeName = '/experiment';
const Experiment({Key? key}) : super(key: key);
#override
State<Experiment> createState() => _ExperimentState();
}
class _ExperimentState extends State<Experiment> {
List<Uint8List>? _pickedBytes = <Uint8List>[];
void clickPaste() async {
var bytes = await Pasteboard.image;
print("xx");
print(bytes);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Row(
children: [
Text("Experiment"),
ElevatedButton(
onPressed: clickPaste,
child: Text("BTN"),
)
],
),
)
);
}
}
Question:
How to let flutter web read the image from clipboard to <List>Uint8List?

The working example is here. But it support only Text.
/// Data stored on the system clipboard.
///
/// The system clipboard can contain data of various media types. This data
/// structure currently supports only plain text data, in the [text] property.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class Experiment extends StatefulWidget {
static const String routeName = '/experiment';
const Experiment({Key? key}) : super(key: key);
#override
State<Experiment> createState() => _ExperimentState();
}
class _ExperimentState extends State<Experiment> {
Future<void> _clipboardToWidget() async {
var data = await Clipboard.getData('text/plain');
print(data?.text);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Row(
children: [
Text("Experiment"),
ElevatedButton(
onPressed: _clipboardToWidget,
child: Text("BBTN"),
)
],
),
)
);
}
}

Related

CheckBox ui is not updated though the item value of checkbox is updated, Getx flutter

Get the working code sample here
I have an RxList of addOnProducts which contains product and selected attributes.
I am trying to implement the simple multiSelectable grid View, but on clicking the checkBox the selected attribute changes but it is not reflected back to the ui,
If i refresh it will be updated.
I tried Obx()=> (); widget , It is still not updating
My ProductController
class ProductsController extends GetxController {
late Worker worker;
static ProductsController instance = Get.find();
RxList<ProductModel> products = RxList<ProductModel>([]);
RxList<CheckProduct> addOnProducts = <CheckProduct>[].obs;
String collection = "products";
#override
void onReady() {
super.onReady();
products.bindStream(getAllProducts());
worker = once(products, (List<ProductModel> value) {
fillAddOnProducts(value);
}, condition: () => products.isNotEmpty);
}
Stream<List<ProductModel>> getAllProducts() => FirebaseFirestore.instance
.collection(collection)
.snapshots()
.map((query) => query.docs
.map((item) => ProductModel.fromMap(item.data(), item.id))
.toList());
void fillAddOnProducts(List<ProductModel> products) => {
products.forEach((element) {
addOnProducts.add(CheckProduct(product: element, selected: false));
})
};
}
class CheckProduct {
ProductModel product;
bool selected;
CheckProduct(
{required ProductModel this.product, required bool this.selected});
}
My Grid View
class AddOns extends StatelessWidget {
const AddOns({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [],
title: Text("Select Addons"),
),
body: Obx(() => GridView.count(
crossAxisCount: 2,
children: productsController.addOnProducts
.map((element) => ProductWidget(product: element))
.toList(),
)));
}
}
class ProductWidget extends StatelessWidget {
final CheckProduct product;
const ProductWidget({Key? key, required this.product}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow,
margin: EdgeInsets.all(10),
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
top: 4,
left: 4,
child: Checkbox(
value: product.selected,
onChanged: (value) {
print("value of the value is : $value");
print("value of product selected before is: " +
product.selected.toString());
product.selected = value!;
print("value of product selected after is: " +
product.selected.toString());
},
),
),
],
));
}
}
Therefore in the console it is :
I/flutter (20067): value of the value is : true
I/flutter (20067): value of product selected before is: false
I/flutter (20067): value of product selected after is: true
But the checkBox is not updating, it updates only when i refresh, How to overCome this? Adding Obx() to the parent isn't helping..
Find the github link to code below here which has just the question and and the problem faced..
After going through your code. I've implemented the following that will change state without hot reload:
In your main dart you do not need to put your product controller here as you are not using it
main.dart
import 'package:flutter/material.dart';
import 'grid.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: GridSelect(),
);
}
}
Next, I have changed your grid class to generate a list of product widget as the size of the addProduct list length. In my opinion this is a better way to write GridView counts children. Remove obx from your gridview and change your stateful widget to stateless as you are using Getx. It will manage your state even in a stateless widget. Add your product controller here as you will access addProduct list from the controller class.
grid.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:test_project/controllers/productController.dart';
import 'package:test_project/productWidget.dart';
class GridSelect extends StatelessWidget {
final _controller = Get.put(ProductController());
GridSelect({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: GridView.count(
crossAxisCount: 2,
children: List.generate(_controller.addOnProducts.length, (index) => ProductWidget(index: index))
),
);
}
}
In your product controller class, remove the instance as it is not important. That is the only change here:
ProductController.dart
import 'package:get/get.dart';
import 'package:test_project/models/productModel.dart';
class ProductController extends GetxController {
RxList<CheckProduct> addOnProducts = <CheckProduct>[].obs;
#override
void onReady() {
super.onReady();
addOnProducts.add(CheckProduct(product: ProductModel('productOne', 20)));
addOnProducts.add(CheckProduct(product: ProductModel('productTwo', 25)));
addOnProducts.add(CheckProduct(product: ProductModel('productThree', 30)));
addOnProducts.add(CheckProduct(product: ProductModel('productFour', 40)));
}
}
class CheckProduct {
ProductModel product;
RxBool selected = false.obs;
CheckProduct({
required this.product,
});
}
Lastly, your productWidget class needs a required value index. So, the widget knows which index in gridview the user is clicking and use Obx() here in checkbox as you have an observable value selected here. Remember to always use Obx() when you have an obs value. This will update the widget whenever an obs value changes. Here, if you notice we are using Get.find() instead of Put as Get.put is already inside the scope so all you need to do is find the controller that you will use. You can find or put multiple controllers and update values as much as you want.
productWidget.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:test_project/controllers/productController.dart';
class ProductWidget extends StatelessWidget {
final ProductController _controller = Get.find();
final int index;
ProductWidget({Key? key, required this.index}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow,
margin: EdgeInsets.all(20),
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
top: 4,
left: 4,
child: Obx(()=>Checkbox(
value: _controller.addOnProducts[index].selected.value,
onChanged: (value) {
print("value of the value is : $value");
print("value of product selected before is: " +
_controller.addOnProducts[index].selected.toString());
_controller.addOnProducts[index].selected.value = value!;
print("value of product selected after is: " +
_controller.addOnProducts[index].selected.toString());
},
)),
)
],
),
);
}
}
Go through GetX documentation for proper use of GetX. Even though I have 2 apps in Playstore with GetX, I still go through documentation from time to time. They have a clear documentation on how to manage state.
In ProductWidget adding an additional Obx() solved my problem
class ProductWidget extends StatelessWidget {
final CheckProduct product;
const ProductWidget({Key? key, required this.product}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow,
margin: EdgeInsets.all(10),
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
top: 4,
left: 4,
// Even the child needs Obx() ; The parent's Obx() is not reflected here
child: Obx(()=>(Checkbox(
value: product.selected,
onChanged: (value) {
print("value of the value is : $value");
print("value of product selected before is: " +
product.selected.toString());
product.selected = value!;
print("value of product selected after is: " +
product.selected.toString());
},
),))
),
],
));
}

How to create a custom class for list in flutter? I am getting this error screen

There is an error when I run my app it doesn't show my text and author from the list.
But I am following a course recorded 3 years ago he doesn't use
required or late but I need to use it because it throws errors of null safety. Here is the image of the app.
[1]: https://i.stack.imgur.com/VgNXu.png
// ignore_for_file: prefer_const_constructors
import 'package:flutter/material.dart';
import 'quote.dart';
void main() {
runApp(MaterialApp(
home: Quotelist(),
),);
}
class Quotelist extends StatefulWidget {
const Quotelist({Key? key}) : super(key: key);
#override
State<Quotelist> createState() => _QuotelistState();
}
class _QuotelistState extends State<Quotelist> {
List<HQuote> listQuotes = [
HQuote(text: "hello",author: "Nagu"),
HQuote(text: "hello1",author: "Nagu1"),
HQuote(text: "hello2",author: "Nagu2"),
HQuote(text: "hello3",author: "Nagu3"),
];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey\[200\],
appBar: AppBar(
title: Text("Quotes"),
centerTitle: true,
backgroundColor: Colors.red\[400\],
),
body: Column(
children: listQuotes.map((e) => Text('$e.text')).toList(),
),
);
}
}
//quote.dart file
class HQuote{
late String text;
late String author;
HQuote({required this.text,required this.author});
}
When adding "." on a variable, you have add the curly braces like: ${x.randomThing}
So, change
children: listQuotes.map((e) => Text('$e.text')).toList(),
To:
children: listQuotes.map((e) => Text('${e.text}')).toList(),

A flutter package for showing a country code selector (default value)

How to set country code selector (default value) based on selected country on the phone
Widget build(BuildContext context) => new Scaffold(
body: Center(
child: CountryCodePicker(
onChanged: print,
// Initial selection and favorite can be one of code ('IT') OR dial_code('+39')
initialSelection: 'IT',
favorite: ['+39','FR'],
// optional. Shows only country name and flag
showCountryOnly: false,
// optional. Shows only country name and flag when popup is closed.
showOnlyCountryWhenClosed: false,
// optional. aligns the flag and the Text left
alignLeft: false,
),
),
);
It looks like you are using the package country_code_picker.
You could get some useful information about the user's default language preference from window.locale from dart:ui, here you can properties like the countryCode and languagueCode, which could be useful for setting a default language. Albeit, it is not certain this is the users preferred language, but an indicator nonetheless.
It appears this package lists supported countries in a List<Map<String,String>> named codes that is exposed in the package. So to be safe the data from window.locale.countryCode should be checked against this list.
Example:
import 'dart:ui';
import 'package:country_code_picker/country_code_picker.dart';
import 'package:country_code_picker/country_codes.dart';
import 'package:flutter/material.dart';
import 'package:collection/collection.dart';
class CountryPickerWithLocale extends StatefulWidget {
const CountryPickerWithLocale({Key? key, required this.onCountryChanged})
: super(key: key);
final Function(CountryCode) onCountryChanged;
#override
State<CountryPickerWithLocale> createState() =>
_CountryPickerWithLocaleState();
}
class _CountryPickerWithLocaleState extends State<CountryPickerWithLocale> {
late String userCountryCode;
String fallbackCountryCode = "UK";
#override
void initState() {
super.initState();
// Get the language set as default on the users phone
String? systemCountryCode = window.locale.countryCode;
// The package you are using has supported countries defined inside a
// "codes" map.
Map<String,String>? supportedLanguage = codes.firstWhereOrNull((element) {
return element["code"] == systemCountryCode;
});
// Use a fallback if the language is unsupported in the package, or if
// there are some issues with retrieving the country code from the locale.
userCountryCode = supportedLanguage?["code"] ?? fallbackCountryCode;
}
#override
Widget build(BuildContext context) {
return Center(
child: CountryCodePicker(
onChanged: widget.onCountryChanged,
initialSelection: userCountryCode,
showCountryOnly: false,
showOnlyCountryWhenClosed: false,
alignLeft: false,
),
);
}
}
class CountryPickerScreen extends StatelessWidget {
const CountryPickerScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: CountryPickerWithLocale(
onCountryChanged: (code) {
print(code.code);
},
),
),
);
}
}
// Some code to run the above example.
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(home: CountryPickerScreen());
}
}
void main() => runApp(const App());

Flutter Secure Storage Change Route

I have successfully implemented the flutter_secure_storage in my flutter project, when the user writes his email and password, it get's stored, but here is the thing I don't understand. How should I setup screen routes depending if the user has already logged in or not. If it is the same user, so the username and pass are stored in the secure_storage, I want him to go directly to HomeScreen(), but if there is a new user that needs to log in, so there is no data in the secure_storage, then I want him sent to LoginScreen(). I have done this so far:
import 'dart:async';
import 'package:flutter/material.dart';
import 'login_screen.dart';
import 'home_screen.dart';
import 'components/alarm_buttons.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class WelcomeScreen extends StatefulWidget {
static const String id = 'welcome_screen';
#override
_WelcomeScreenState createState() => _WelcomeScreenState();
}
class _WelcomeScreenState extends State<WelcomeScreen> {
void readData() async {
final storage = FlutterSecureStorage();
String myPassword = await storage.read(key: "p");
String myEmail = await storage.read(key: "e");
print(myEmail);
print(myPassword);
}
#override
void initState() {
final storage = FlutterSecureStorage();
Timer(
Duration(seconds: 2),
() => Navigator.pushNamed(
context,
storage == null ? LoginScreen.id : HomePage.id,
));
readData();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
AlarmButtons(
buttonColour: Colors.grey,
buttonText: 'Log In',
buttonTextColour: Colors.white,
onButtonPress: () {
Navigator.pushNamed(context, LoginScreen.id);
},
),
AlarmButtons(
buttonColour: Colors.white,
buttonText: 'Sign up',
buttonTextColour: Colors.grey,
onButtonPress: () {
Navigator.pushNamed(context, SignUpScreen.id);
},
),
],
),
),
);
}
}
Now the problem starts when I want to return to the Welcome Screen (the starting page of my app shown above), naturally it triggers the initState again and I get back to the HomePage() again. How can I dispose of that, only triggering that initState when the app starts, so after automatic login I can return to the Welcome Screen without triggering it?
Thanks in advance!
You should initial start something like a SplashScreen (or WelcomeScreen in your case). There you can decide to which screen you want to navigate based on the saved data. Example:
class SplashScreen extends StatefulWidget {
const SplashScreen({Key key}) : super(key: key);
#override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
#override
void initState() {
_startApp();
super.initState();
}
Future<void> _startApp() async {
final storage = FlutterSecureStorage();
String myEmail = await storage.read(key: "e");
if (myEmail == null) {
// TODO Navigate to Login Screen
} else {
// TODO Navigate to Home Screen
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text("Splashscreen"),
),
);
}
}

Count page transitions in Flutter using iframes [flutter web]

I would like to include another website in my own website.
For that I would like to register a callback to track site-tranitions (i.e. the user clicks on a link on the embedded site and is redirected to a different url / sub-url (?).) I currently use IFrameElement to embed a site, this would in theory allow to register event listeners, but I cannot find any documentation about that.
My main goal is to count the number of page transitions. This is my current code:
import 'package:flutter/material.dart';
import 'package:wikipoker/widgets/my_iframe.dart';
import 'package:wikipoker/widgets/player_tab.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Wikipedia Poker',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Game of Wikipedia Poker'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
buildIFrame(constraints.maxHeight, constraints.maxWidth),
],
);
},
),
);
}
String _youtube = 'https://www.youtube.com/embed/RQzhAQlg2JQ';
String _wiki = 'https://de.wikipedia.org/wiki/Hunde';
Widget buildIFrame(double height, double width) {
return Column(
children: [
IFrameWidget(
_wiki,
height,
width * (4 / 5),
),
],
);
}
}
import 'dart:html';
import 'dart:ui' as ui;
import 'package:flutter/cupertino.dart';
class IFrameWidget extends StatefulWidget {
final String _url;
double _height = 500;
double _width = 500;
IFrameWidget(this._url, this._height, this._width);
#override
State<StatefulWidget> createState() => _IFrameWidgetState();
}
class _IFrameWidgetState extends State<IFrameWidget> {
Widget _iframeWidget;
#override
void initState() {
super.initState();
final IFrameElement _iframeElement = IFrameElement();
// _iframeElement.height = '500';
// _iframeElement.width = '500';
// FIXME This does not load.
// _iframeElement.addEventListener('onLoad', (event) {
// setState(() {
// _iframeWidget = Text("Lol");
// });
// });
_iframeElement.src = widget._url;
_iframeElement.style.border = 'none';
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
'iframeElement',
(int viewId) => _iframeElement,
);
_iframeWidget = HtmlElementView(
key: UniqueKey(),
viewType: 'iframeElement',
);
}
#override
Widget build(BuildContext context) {
return SizedBox(
height: widget._height,
width: widget._width,
child: _iframeWidget,
);
}
}
The IFrameElement has some fields and methods, which look like they could be useful.
addEventListener expects a type of event, but there is no overview about what that might be.
The documentation is very incomplete for this and I have no idea which event I would like to register.
My hope is, that I can use events from the native html iframe for that.
Documentation for IFrames: https://api.flutter.dev/flutter/dart-html/IFrameElement-class.html
Old question, but I hope the answer will help someone looking for a solution:
here is described very well
Note: need to restart the IDE (at least mine refused to work without restart)