How to use MediaQueryList from Dart [duplicate] - dart

How to use window.matchMedia in Dart?
I have found corresponding method:
MediaQueryList matchMedia(String query)
And "MediaQueryList" method:
void addListener(MediaQueryListListener listener)
But: MediaQueryListListener has no constructor and looks like some sort of a generated stub.
I have JS example:
var mq = window.matchMedia( "(min-width: 500px)" );
// media query event handler
if (matchMedia) {
var mq = window.matchMedia("(min-width: 500px)");
mq.addListener(WidthChange);
WidthChange(mq);
}
// media query change
function WidthChange(mq) {
if (mq.matches) {
// window width is at least 500px
}
else {
// window width is less than 500px
}
}
And it has good support http://caniuse.com/#feat=matchmedia

As pointed in a comment it doesn't seem to be implemented in Dart for now.
However you can use dart:js to do that like this :
import 'dart:js';
main() {
if (context['matchMedia'] != null) {
final mq = context.callMethod('matchMedia', ['(min-width: 500px)']);
mq.callMethod('addListener', [widthChange]);
widthChange(mq);
}
}
widthChange(mq) {
if (mq['matches']) {
print('window width is at least 500px');
} else {
print('window width is less than 500px');
}
}

Related

Invoke top level function with dart:mirrors

I'm struggling with how to invoke a top level function in dart. I'd like to be able to annotate a function with #Route, find all the Route annotations, then check that the annotation is on a method, and then call that method by its symbol.
What I have so far is:
class Route {
final String url;
const Route(this.url);
}
#Route('/')
void handle() {
print('Request received');
}
void main() {
var mirrorSystem = currentMirrorSystem();
var lm = mirrorSystem.isolate.rootLibrary;
for (var mirror in lm.declarations.values) {
var metadata = mirror.metadata;
for (var im in metadata) {
if (im.reflectee is Route) {
print('Route found');
// how to invoke the function handle associated with the route annotation?
}
}
}
}
From this point i'm not sure how I would then call the method. If it was a class then I could use invoke and pass in the Symbol for the method, but that doesn't work as it's not a class.
Can anyone give me some clues? Information about the mirrors library in dart is fairly sparse unfortunately.
I worked this out. For anyone who finds this, you use the LibraryMirror on rootLibrary to invoke the top level function:
void main() {
var mirrorSystem = currentMirrorSystem();
var lm = mirrorSystem.isolate.rootLibrary;
for (var mirror in lm.declarations.values) {
var metadata = mirror.metadata;
for (var im in metadata) {
if (im.reflectee is Route && mirror is MethodMirror) {
lm.invoke(mirror.simpleName, []);
// prints 'Request received'
}
}
}
}

How to Create Dot Function in Dart or Flutter

Suppose I want to convert a UNIX integer into DateTime Format when called upon.
(That's just an example)
I want to create a function just like .toUpperCase(); , .toString(); where function takes that particular item as argument without writing inside brackets. I did try going inside these default core functions but didn't help.
How do I do that for custom functions?
right now I'm here:
//------------- main()----------//
void main() {
int unixDT = 1619691181;
// print(unixDT.toDateString()); //<-----this is what I'm looking for
}
//------- This is a function that should be in another-separate dart file-------//
String toDateString(int dt) {
DateTime datetime = new DateTime.fromMillisecondsSinceEpoch(dt);
return datetime.toString();
}
If you need clarification, please comment down. This is my very first question on StackOverflow so I apologize for mistakes if any.
Sounds like you are looking for extension methods:
void main() {
const unixDT = 1619691181;
print(unixDT.toDateString()); // 1970-01-19 18:54:51.181
}
extension IntToDateStringExtension on int {
String toDateString() => DateTime.fromMillisecondsSinceEpoch(this).toString();
}
You can use extension methods for this situations. You can add a method in Integer. For more details https://dart.dev/guides/language/extension-methods
You can try to use this to refer to same object that is calling that method, Hope that will help
You should use extension methods
Example:
extension ExtendedDynamic on dynamic {
double toDouble() {
final sValue = this?.toString() ?? '';
final double parsedValue = double?.tryParse(sValue) ?? 0.0;
return parsedValue;
}
}
void someMethod() {
final dynamic test = 0.0;
print(test.toDouble());
}
In your case it will be like this:
extension ExtendedInt on int {
String toDateString() {
final dateString = 'your code...';
return dateString;
}
}
void someMethod() {
int unixDT = 1619691181;
print(unixDT.toDateString());
}
Important thing : Wherever you want to use this extension, you must import it
import 'package:yourProject/extensions/int_extention.dart';

Use "AdjustsFontSizeToFitWidth" when using Label in iOS

I would like to ask if there is a way to make a Xamarin.Forms.Label tell that it should use the "AdjustsFontSizeToFitWidth" when the app is run on iOS.
Is this possible, or is Xamarin.Forms.Label something completely different than the UILabel?
I was thinking that Xamarin.Form.Label "falls back" on the UILabel when it's built for iOS, is that the case?
Edit:
According to how I understood the comments I tried this, but it wouldn't work:
switch (Device.RuntimePlatform)
{
case Device.iOS:
{
_label1.AdjustsFontSizeToFitWidth = true;
break;
}
default:
{
break;
}
}
The error I'm getting is that "AdjustsFontSizeToFitWidth" isn't a property of Xamarin.Forms.Label.
Edit 2:
According to another comment I tried the following:
public class clsGridCell : ContentView
{
private Xamarin.Forms.Label _label1;
//problem is that it's not longer a Xamarin.Forms.Label, but UILabel on iOS, but I can't declare it as "var" when I want to reuse it for binding.
//declaring it as "object" would break the bindings.
public clsGridCell()
{
switch (Device.RuntimePlatform)
{
case Device.iOS:
{
_label1 = new UILabel
_label1.AdjustsFontSizeToFitWidth = true;
break;
}
default:
{
_label1 = new Xamarin.Forms.Label()
{
HorizontalTextAlignment = TextAlignment.Center,
VerticalTextAlignment = TextAlignment.Center,
};
break;
}
}
this._label1.SetBinding(Label.BackgroundColorProperty, new Binding() { Path = "BackgroundColor", Source = this });
this._label1.SetBinding(Label.TextProperty, new Binding() { Path = "Text", Source = this });
this._label1.SetBinding(Label.TextColorProperty, new Binding() { Path = "TextColor", Source = this });
The error is in line "_label1.AdjustsFontSizeToFitWidth = true;".
The error thrown is "Label doesn't contain "AdjustsFontSizeToFitWidth"".
That is because I declared it as "Label".
I did that because "var" wasn't possible in this case.
What would be an alternative way to declare it without breaking the bindings?
Declaring it as "object" would break the bindings.
Thank you!
As SushiHangover mentioned above,there are several ways to achieve your requirement.
Use Effects
In PCL
label.Effects.Add (Effect.Resolve ("MyCompany.AdjustsFontSizeEffect"));
Create class named AdjustsFontSizeEffect In iOS Project
[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(AdjustsFontSizeEffect), "AdjustsFontSizeEffect")]
namespace EffectsDemo.iOS
{
public class AdjustsFontSizeEffect : PlatformEffect
{
protected override void OnAttached ()
{
(Control as UILabel).AdjustsFontSizeToFitWidth = true;
}
protected override void OnDetached ()
{
}
}
}
Use Custom Renderers
Create class named AdjustsFontSizeEffectRenderer In iOS Project
[assembly: ExportRenderer(typeof(Label), typeof(AdjustsFontSizeEffectRenderer))]
namespace EffectsDemo.iOS
{
public class AdjustsFontSizeEffectRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.AdjustsFontSizeToFitWidth = true;
}
}
}
}
I recommend you to use Effectsin this scenario.
Refer to Why Use an Effect over a Custom Renderer?

How to request fullscreen in compiled dart

I'm playing around with a Dart app trying to get fullscreen mode to work. My HTML (excluding boilerplate):
<div id="fullscreen_div">
Clicking this should cause it to go fullscreen!
</div>
My Dart code:
import 'dart:html';
void main() {
var div = querySelector('#fullscreen_div');
div.onClick.listen((MouseEvent e) {
div.requestFullscreen();
print('requested fullscreen');
});
}
Here it is on DartPad.
If I've done this correctly, clicking the div once should cause the div to go into fullscreen mode. On Chromium, this works. When compiled to JavaScript (both debug and minified), this does not happen, and the console outputs:
Uncaught TypeError: undefined is not a function
This happens on both Chrome, Firefox and IE (tested on Windows 7). From what I've understood this is a common JavaScript error, and searching does not bring up anything obvious.
Any ideas why requestFullScreen won't work when dart is compiled to JS?
As pointed out in the comments (thanks Günter!), this is a known issue. #12 in that thread posted a good workaround, edited by me to be a bit more generic:
import 'dart:js';
void fullscreenWorkaround(Element element) {
var elem = new JsObject.fromBrowserObject(element);
if (elem.hasProperty("requestFullscreen")) {
elem.callMethod("requestFullscreen");
}
else {
List<String> vendors = ['moz', 'webkit', 'ms', 'o'];
for (String vendor in vendors) {
String vendorFullscreen = "${vendor}RequestFullscreen";
if (vendor == 'moz') {
vendorFullscreen = "${vendor}RequestFullScreen";
}
if (elem.hasProperty(vendorFullscreen)) {
elem.callMethod(vendorFullscreen);
return;
}
}
}
}
I used this in my code, and replaced this call
div.requestFullscreen();
with
fullscreenWorkaround(div);
which worked great. Tested and working compiled on Chrome and IE.
Here is an extended version of Tobbe hack to use the whole fullscreen API.
import 'dart:html';
import 'dart:js';
// Workaround for https://code.google.com/p/dart/issues/detail?id=4136
class FullscreenWorkaround {
static void requestFullscreen(Element element) {
_callMethods(element, [
'requestFullscreen',
'webkitRequestFullscreen',
'mozRequestFullScreen',
'msRequestFullscreen',
'oRequestFullscreen'
]);
}
static void exitFullscreen() {
_callMethods(document, [
'exitFullscreen',
'webkitExitFullscreen',
'mozCancelFullScreen',
'msExitFullscreen',
'oExitFullscreen'
]);
}
static bool get fullscreenEnabled {
var result = _getProperty(document, [
'fullscreenEnabled',
'webkitFullscreenEnabled',
'mozFullScreenEnabled',
'msFullscreenEnabled',
'oFullscreenEnabled'
]);
return result != null ? result : false;
}
static get fullscreenElement {
return _getProperty(document, [
'fullscreenElement',
'webkitFullscreenElement',
'mozFullScreenElement',
'msFullscreenElement',
'oFullscreenElement'
]);
}
static _callMethods(browserObject, List methods) {
var jsElem = new JsObject.fromBrowserObject(browserObject);
for (String methodName in methods) {
if (jsElem.hasProperty(methodName)) {
return jsElem.callMethod(methodName);
}
}
}
static _getProperty(browserObject, List properties) {
var jsElem = new JsObject.fromBrowserObject(browserObject);
for (String propertyName in properties) {
if (jsElem.hasProperty(propertyName)) {
return jsElem[propertyName];
}
}
}
}

Groovy/Grails promises/futures. There is no .resolve(1,2,3) method. Strange?

I am developing in a Grails application. What I want to do is to lock the request/response, create a promise, and let someone else resolve it, that is somewhere else in the code, and then flush the response.
What I find really strange is that the Promise promise = task {} interface has no method that resembles resolve or similar.
I need to lock the response until someone resolves the promise, which is a global/static property set in development mode.
Promise interface:
http://grails.org/doc/latest/api/grails/async/Promise.html
I have looked at the GPars doc and can't find anything there that resembles a resolve method.
How can I create a promise, that locks the response or request, and then flushes the response when someone resolves it?
You can call get() on the promise which will block until whatever the task is doing completes, but I imagine what that is not what you want. What you want seems to be equivalent to a GPars DataflowVariable:
http://gpars.org/1.0.0/javadoc/groovyx/gpars/dataflow/DataflowVariable.html
Which allows using the left shift operator to resolve the value from another thread. Currently there is no way to use the left shift operator via Grails directly, but since Grails' promise API is just a layer over GPars this can probably be accomplished by using the GPars API directly with something like:
import org.grails.async.factory.gpars.*
import groovyx.gpars.dataflow.*
import static grails.async.Promise.*
def myAction() {
def dataflowVar = new DataflowVariable()
task {
// do some calculation and resolve data flow variable
def expensiveData = ...
dataflowVar << expensiveData
}
return new GParsPromise(dataflowVar)
}
It took me quite some time to get around this and have a working answer.
I must say that it appears as if Grails is quite a long way of making this work properly.
task { }
will always execute immediatly, so the call is not put on hold until dispatch() or whatever is invoked which is a problem.
Try this to see:
public def test() {
def dataflowVar = new groovyx.gpars.dataflow.DataflowVariable()
task {
// do some calculation and resolve data flow variable
println '1111111111111111111111111111111111111111111111111111'
//dataflowVar << expensiveData
}
return new org.grails.async.factory.gpars.GparsPromise(dataflowVar);
}
If you are wondering what this is for, it is to make the lesscss refresh automatically in grails, which is a problem when you are using import statements in less. When the file is touched, the lesscss compiler will trigger a recompilation, and only when it is done should it respond to the client.
On the client side I have some javascript that keeps replacing the last using the refresh action here:
In my controller:
/**
* Refreshes link resources. refresh?uri=/resource/in/web-app/such/as/empty.less
*/
public def refresh() {
return LessRefresh.stackRequest(request, params.uri);
}
A class written for this:
import grails.util.Environment
import grails.util.Holders
import javax.servlet.AsyncContext
import javax.servlet.AsyncEvent
import javax.servlet.AsyncListener
import javax.servlet.http.HttpServletRequest
/**
* #Author SecretService
*/
class LessRefresh {
static final Map<String, LessRefresh> FILES = new LinkedHashMap<String, LessRefresh>();
String file;
Boolean touched
List<AsyncContext> asyncContexts = new ArrayList<AsyncContext>();
String text;
public LessRefresh(String file) {
this.file = file;
}
/** Each request will be put on hold in a stack until dispatchAll below is called when the recompilation of the less file finished **/
public static AsyncContext stackRequest(HttpServletRequest request, String file) {
if ( !LessRefresh.FILES[file] ) {
LessRefresh.FILES[file] = new LessRefresh(file);
}
return LessRefresh.FILES[file].handleRequest(request);
}
public AsyncContext handleRequest(HttpServletRequest request) {
if ( Environment.current == Environment.DEVELOPMENT ) {
// We only touch it once since we are still waiting for the less compiler to finish from previous edits and recompilation
if ( !touched ) {
touched = true
touchFile(file);
}
AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(10000)
asyncContexts.add (asyncContext);
asyncContext.addListener(new AsyncListener() {
#Override
void onComplete(AsyncEvent event) throws IOException {
event.getSuppliedResponse().writer << text;
}
#Override
void onTimeout(AsyncEvent event) throws IOException {
}
#Override
void onError(AsyncEvent event) throws IOException {
}
#Override
void onStartAsync(AsyncEvent event) throws IOException {
}
});
return asyncContext;
}
return null;
}
/** When recompilation is done, dispatchAll is called from LesscssResourceMapper.groovy **/
public void dispatchAll(String text) {
this.text = text;
if ( asyncContexts ) {
// Process all
while ( asyncContexts.size() ) {
AsyncContext asyncContext = asyncContexts.remove(0);
asyncContext.dispatch();
}
}
touched = false;
}
/** A touch of the lessfile will trigger a recompilation **/
int count = 0;
void touchFile(String uri) {
if ( Environment.current == Environment.DEVELOPMENT ) {
File file = getWebappFile(uri);
if (file && file.exists() ) {
++count;
if ( count < 5000 ) {
file << ' ';
}
else {
count = 0
file.write( file.getText().trim() )
}
}
}
}
static File getWebappFile(String uri) {
new File( Holders.getServletContext().getRealPath( uri ) )
}
}
In LesscssResourceMapper.groovy of the lesscsss-recources plugin:
...
try {
lessCompiler.compile input, target
// Update mapping entry
// We need to reference the new css file from now on
resource.processedFile = target
// Not sure if i really need these
resource.sourceUrlExtension = 'css'
resource.contentType = 'text/css'
resource.tagAttributes?.rel = 'stylesheet'
resource.updateActualUrlFromProcessedFile()
// ==========================================
// Call made here!
// ==========================================
LessRefresh.FILES[resource.sourceUrl.toString()]?.dispatchAll( target.getText() );
} catch (LessException e) {
log.error("error compiling less file: ${originalFile}", e)
}
...
In the index.gsp file:
<g:set var="uri" value="${"${App.files.root}App/styles/empty.less"}"/>
<link media="screen, projection" rel="stylesheet" type="text/css" href="${r.resource(uri:uri)}" refresh="${g.createLink(controller:'home', action:'refresh', params:[uri:uri])}" resource="true">
JavaScript method refreshResources to replace the previous link href=...
/**
* Should only be used in development mode
*/
function refreshResources(o) {
o || (o = {});
var timeoutBegin = o.timeoutBegin || 1000;
var intervalRefresh = o.intervalRefresh || 1000;
var timeoutBlinkAvoid = o.timeoutBlinkAvoid || 400 ;
var maxErrors = o.maxErrors || 200 ;
var xpath = 'link[resource][type="text/css"]';
// Find all link[resource]
$(xpath).each(function(i, element) {
refresh( $(element) );
});
function refresh(element) {
var parent = element.parent();
var next = element.next();
var outer = element.clone().attr('href', '').wrap('<p>').parent().html();
var uri = element.attr('refresh');
var errorCount = 0;
function replaceLink() {
var link = $(outer);
link.load(function () {
// The link has been successfully added! Now remove the other ones, then do again
errorCount = 0;
// setTimeout needed to avoid blinking, we allow duplicates for a few milliseconds
setTimeout(function() {
var links = parent.find(xpath + '[refresh="'+uri+'"]');
var i = 0;
// Remove all but this one
while ( i < links.length - 1 ) {
links[i++].remove();
}
replaceLinkTimeout();
}, timeoutBlinkAvoid );
});
link.error(function(event, handler) {
console.log('Error refreshing: ' + outer );
++errorCount;
if ( errorCount < maxErrors ) {
// Load error, it happens. Remove this & redo!
link.remove();
replaceLink();
}
else {
console.log('Refresh: Aborting!')
}
});
link.attr('href', urlRandom(uri)).get(0);
link.insertBefore(next); // Insert just after
}
function urlRandom(uri) {
return uri + "&rand=" + Math.random();
}
function replaceLinkTimeout() {
setTimeout(function() {
replaceLink();
}, intervalRefresh ) ;
}
// Waith 1s before triggering the interval
setTimeout(function() {
replaceLinkTimeout();
}, timeoutBegin);
}
};
Comments
I am unsure why Javascript style promises have not been added to the Grails stack.
You can not render or stuff like that in the onComplete. render, redirect and what not are not available.
Something tells me that Grails and Promises/Futures are not there yet. The design of the GPars libraries seems not take into account of the core features which is to resolve later. At least it is not simple to do so.
It would be great if the dispatch() method actually could be invoked with some paramaters to pass from the resolving context. I am able to go around this using static properties.
I might continue to write my own solution and possibly contribute with a more fitting solutions around the AsyncContext class, but for now, this is enough for me.
I just wanted to refresh my less resources automatically.
Phew...
EDIT:
I made it to support several number of files. It is complete now!

Resources