OverlayPortal

Inspired by the flutter_portal package.
The flutter_portal package is created by @rrousselGit and is currently maintained by @fzyzcjy
This PR resolves many of the issues raised in https://github.com/flutter/flutter/issues/36220.
What the Render Tree Looks like:

Layout Order
_RenderDeferredLayoutBox needs to do layout after _RenderLayoutSurrogateProxyBox, but should also update its layout when _RenderTheatre gives it a set of different constraints. Additionally, RenderObjects below a _RenderDeferredLayoutBox should only perform layout after the _RenderDeferredLayoutBox is updated.
So the layout order has to be _RenderTheatre -> _RenderLayoutSurrogateProxyBox -> _RenderDeferredLayoutBox -> overlayChild, otherwise something may have to do layout twice.

_RenderTheatre is the common ancestor of the 3 other RenderObjects so it will be laid out first. It's ok to re-dirty it since it's sizedByParent, and all that matters to the descendants is the constraints, which won't change even when re-dirtied.
_RenderLayoutSurrogateProxyBox -> _RenderDeferredLayoutBox: _RenderDeferredLayoutBox has a greater depth than _RenderLayoutSurrogateProxyBox and it can't be tree walked from _RenderTheatre.
_RenderLayoutSurrogateProxyBox -> overlayChild: because _RenderDeferredLayoutBox -> overlayChild. When _RenderDeferredLayoutBox is not dirty, overlayChild is guaranteed to have a greater depth than _RenderLayoutSurrogateProxyBox.
_RenderDeferredLayoutBox -> overlayChild: overlayChild can only be tree walked from _RenderDeferredLayoutBox and has a greater depth than _RenderDeferredLayoutBox.

However since _RenderDeferredLayoutBox  actually depends on both _RenderLayoutSurrogateProxyBox and _RenderTheatre, it can be dirtied by _RenderTheatre when _RenderLayoutSurrogateProxyBox is clean. When that happens _RenderTheatre needs to call _RenderDeferredLayoutBox.markNeedsLayout in an invokeLayoutCallback to merge the node back to the dirty list in case overlayChild is dirty too, so overlayChild doesn't perform layout before _RenderDeferredLayoutBox.
Why placing the RenderObject under _RenderTheatre instead of _RenderLayoutSurrogateProxyBox
It takes some extra lines of code to manage the render tree properly, and _RenderLayoutSurrogateProxyBox has to redepth the overlayChild branch, but:

It generates the same render tree as the OverlayEntry API would and that could make it easier for people to migrate from the OverlayEntry API.
If overlayChild needs to repaint it doesn't have to mark _RenderLayoutSurrogateProxyBox as needing repaint too (we have markParentNeedsLayout but not markParentNeedsPaint). overlayChild paints on _RenderTheatre's PaintContext so there's little point in marking _RenderLayoutSurrogateProxyBox dirty. Also during compositing bits update, it could set _needsCompositing to true on some nodes that actually don't need compositing.

TODOs to be addressed in future pull requests

Currently when an OverlayPortal widget reparents, the overlay child will be moved to the top of the Overlay (in terms of the z-index, for painting and hit-testing), and that's pretty strange for a declarative API. OverlayInfo currently knows which OverlayEntry an OverlayPortal belongs to (for nested OverlayPortal it shouldn't be difficult to get the closest ancestor OverlayPortal too), so it shouldn't be difficult to add additional information to the parent data to specify the desired z-index (in relation to the parent OverlayEntry or PortalEntry).

Pre-launch Checklist

[ ] I read the Contributor Guide and followed the process outlined there for submitting PRs.
[ ] I read the Tree Hygiene wiki page, which explains my responsibilities.
[ ] I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
[ ] I signed the CLA.
[ ] I listed at least one issue that this PR fixes in the description above.
[ ] I updated/added relevant documentation (doc comments with ///).
[ ] I added new tests to check the change I am making, or this PR is test-exempt.
[ ] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Also on a different note, @rrousselGit @fzyzcjy how would like to receive the due credit? I can add a code comment before the OverlayPortal class and say "this is Inspired by the flutter_portal package"? If that works for you, do you want your github handles added to the comment as well?

"this is Inspired by the flutter_portal package"? If that works for you, do you want your github handles added to the comment as well?

That's fine by me :)

"this is Inspired by the flutter_portal package"? If that works for you, do you want your github handles added to the comment as well?

Also fine for me :)

cc: @creativecreatorormaybenot

Started working on adding more test, @Hixie by proxy you mean the PortalOverlay widget right?

Started working on adding more test, @Hixie by proxy you mean the PortalOverlay widget right?

I meant the addDeferredChild API, but I guess that's the same thing since it's private.
(It'd be interesting to see if there was a way to implement this so that Overlay and _Theatre itself was agnostic about all this, so that other people could create their own interesting variants.)

(It'd be interesting to see if there was a way to implement this so that Overlay and _Theatre itself was agnostic about all this, so that other people could create their own interesting variants.)

Something like https://github.com/flutter/flutter/pull/39104? The addDeferredChild thing is only safe on a render parent whose children are independently sized, and independently positioned, in case it's called inside of a LayoutBuilder, so it can adopt render children during layout and finish everything in one frame. So I guess the only thing that qualifies is an Overlay/_RenderTheatre?

@LongCatIsLooong I tried checking this out to play with it but it had a lot of conflicts (and many commits so it was hard to figure out how to resolve them) -- any chance you could merge this to tip of tree?

I found a problem with this approach. It breaks the invariant that Material relies on, namely that if it can find a Material.of during build, that guarantees that it can find the corresponding Material widget's render object during paint.
You can reproduce this problem by putting an InkWell inside an OverlayPortal's overlayChild and then tapping it.

Another issue I ran into is that the logic that toggles the presence of the DebugBanner when you take a screenshot from the command line (hit s in the flutter run console) causes the whole thing to fall over (screen goes red with an assertion error deep in the framework).

I suspect it's the same as the DebugBanner issue, but for what it's worth, selecting "Select Widget Mode" in the devtools also causes the framework to throw an assertion that turns the screen red.

Regarding material, I made some changes to how material computes the paint transform to each InkFeature so it stops throwing (but if the InkFeature extends outside of the material it'll still get clipped to materials bounding rect).
Also I messed up something in activate and deactivate, now taking screenshots should be working.

I think I broke it: The code below crashes when clicking the button with the exception shown below.
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building LayoutBuilder:
A _RenderTheatre was mutated in _RenderLayoutBuilder.performLayout.
The RenderObject was mutated when none of its ancestors is actively performing layout.
The RenderObject being mutated was:
  _RenderTheatre#1ccf4 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
The RenderObject that was mutating the said _RenderTheatre was:
  _RenderLayoutBuilder#ef4b9 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE

The relevant error-causing widget was:
  LayoutBuilder LayoutBuilder:file:///Users/goderbauer/dev/playground/lib/main.dart:60:12

When the exception was thrown, this was the stack:
#0      RenderObject._debugCanPerformMutations.<anonymous closure> (package:flutter/src/rendering/object.dart:1630:9)
#1      RenderObject._debugCanPerformMutations (package:flutter/src/rendering/object.dart:1691:6)
#2      RenderObject.adoptChild (package:flutter/src/rendering/object.dart:1477:12)
#3      ContainerRenderObjectMixin.insert (package:flutter/src/rendering/object.dart:3761:5)
#4      ContainerRenderObjectMixin.add (package:flutter/src/rendering/object.dart:3767:5)
#5      _RenderTheatre.addDeferredChild (package:flutter/src/widgets/overlay.dart:783:5)
#6      _OverlayPortalElement.insertRenderObjectChild (package:flutter/src/widgets/overlay.dart:1184:33)
#7      RenderObjectElement.attachRenderObject (package:flutter/src/widgets/framework.dart:6067:35)
#8      RenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5739:5)
#9      SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6287:11)
#10     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3850:16)
#11     Element.updateChild (package:flutter/src/widgets/framework.dart:3579:18)
#12     _OverlayPortalElement.updateOverlayChild (package:flutter/src/widgets/overlay.dart:1128:12)
#13     _OverlayPortalElement.mount (package:flutter/src/widgets/overlay.dart:1103:21)
#14     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3850:16)
#15     Element.updateChild (package:flutter/src/widgets/framework.dart:3579:18)
#16     _LayoutBuilderElement._layout.layoutCallback (package:flutter/src/widgets/layout_builder.dart:135:18)
#17     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2605:19)
#18     _LayoutBuilderElement._layout (package:flutter/src/widgets/layout_builder.dart:153:12)
#19     RenderObject.invokeLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:2268:59)
#20     PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1035:15)
#21     RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2268:14)
#22     RenderConstrainedLayoutBuilder.rebuildIfNecessary (package:flutter/src/widgets/layout_builder.dart:228:7)
#23     _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:316:5)
#24     RenderObject.layout (package:flutter/src/rendering/object.dart:2157:7)
#25     RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11)
#26     _RenderDeferredLayoutBox.performLayout (package:flutter/src/widgets/overlay.dart:1364:13)
#27     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1995:7)
#28     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:999:18)
#29     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:513:19)
#30     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:884:13)
#31     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:378:5)
#32     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15)
#33     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1104:9)
#34     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1015:5)
#35     _invoke (dart:ui/hooks.dart:148:13)
#36     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
#37     _drawFrame (dart:ui/hooks.dart:115:31)

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text('OverlayPortal Example')),
        body: const Center(child: ClickableTooltipWidget()),
      ),
    );
  }
}

class ClickableTooltipWidget extends StatefulWidget {
  const ClickableTooltipWidget({super.key});

  @override
  State<StatefulWidget> createState() => ClickableTooltipWidgetState();
}

class ClickableTooltipWidgetState extends State<ClickableTooltipWidget> {
  bool shouldShowTooltip = false;

  void _onTap() {
    setState(() {
      shouldShowTooltip = !shouldShowTooltip;
    });
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTextStyle(
      style: DefaultTextStyle.of(context).style.copyWith(fontSize: 50),
      child: GestureDetector(
        onTap: _onTap,
        child: OverlayPortal(
          overlayInfo: OverlayInfo.of(context),
          overlayChild: !shouldShowTooltip ? null : const ChildWidget(),
          child: const Text('Press to show/hide tooltip'),
        ),
      ),
    );
  }
}

class ChildWidget extends StatelessWidget {
  const ChildWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) {
        return OverlayPortal(
          overlayInfo: OverlayInfo.of(context),
          overlayChild: Align(
            alignment: Alignment.topLeft,
            child: Container(
              height: 50,
              width: 50,
              color: Colors.green,
            ),
          ),
          child: const Center(
            child: ColoredBox(
              color: Colors.amberAccent,
              child: Text('tooltip'),
            ),
          ),
        );
      },
    );
  }
}

There is also some stack ordering strangeness in the overlay if you have multiple items in the overlay and a subtree with an OverlayPortal is moved with a global key. In the example below press in order: Button1, Button2, Button3, and finally reparent. Notice how the blue square jumps to the top.
This is likely related to how the items in the overlay are removed and re-added on deactivate and activate.
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      home: ClickableTooltipWidget(),
    );
  }
}

class ClickableTooltipWidget extends StatefulWidget {
  const ClickableTooltipWidget({super.key});

  @override
  State<StatefulWidget> createState() => ClickableTooltipWidgetState();
}

class ClickableTooltipWidgetState extends State<ClickableTooltipWidget> {
  bool nest = false;
  final Key key = GlobalKey();

  @override
  Widget build(BuildContext context) {
    final Widget button2 = TooltipButton(key: key, index: 2);
    return Scaffold(
      body: Center(
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            const TooltipButton(index: 1),
            if (nest)
              SizedBox(child: button2)
            else
              button2,
            const TooltipButton(index: 3),
            TextButton(
              onPressed: () {
                setState(() {
                  nest = !nest;
                });
              },
              child: const Text('reparent'),
            ),
          ],
        ),
      ),
    );
  }
}

class TooltipButton extends StatefulWidget {
  const TooltipButton({required this.index, Key? key}) : super(key: key);

  final int index;

  @override
  State<TooltipButton> createState() => _TooltipButtonState();
}

class _TooltipButtonState extends State<TooltipButton> {
  bool show = false;

  static final List<Color> _colors = [Colors.green, Colors.blue, Colors.yellow];

  @override
  Widget build(BuildContext context) {
    return OverlayPortal(
      overlayInfo: OverlayInfo.of(context),
      overlayChild: !show
          ? null
          : Positioned(
              top: 10.0 * widget.index,
              left: 10.0 * widget.index,
              child: Container(
                color: _colors[widget.index - 1],
                height: 50,
                width: 50,
                child: Text('${widget.index}'),
              ),
            ),
      child: TextButton(
        child: Text('Button${widget.index}'),
        onPressed: () {
          setState(() {
            show = !show;
          });
        },
      ),
    );
  }
}

One issue with the current API is that it doesn't provide an intuitive order for the overlayChildren. In general I would expect tree order to be respected as the paint order: if I have a column with two children, the second one paints on top of the first.
However, with this API the paint order is actually chronological by order of when the portals were created. For example, in this code the "BOTTOM" (earlier) child ends up on top of the "TOP" (later) child because the LayoutBuilder changes the order in which we walk the tree:
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            LayoutBuilder(
              builder: (BuildContext context, BoxConstraints constraints) => OverlayPortal(
                overlayInfo: OverlayInfo.of(context),
                overlayChild: Positioned(
                  top: 50.0,
                  left: 50.0,
                  width: 200.0,
                  height: 100.0,
                  child: Container(
                    color: Colors.yellow,
                    child: Text('BOTTOM'),
                  ),
                ),
                child: Container(
                  color: Colors.orange,
                  child: Text('first source'),
                ),
              ),
            ),
            OverlayPortal(
              overlayInfo: OverlayInfo.of(context),
              overlayChild: Positioned(
                top: 75.0,
                left: 75.0,
                width: 200.0,
                height: 100.0,
                child: Container(
                  color: Colors.teal,
                  child: Text('TOP'),
                ),
              ),
              child: Container(
                color: Colors.blue,
                child: Text('second source'),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () { },
        tooltip: 'Test',
        child: const Icon(Icons.add),
      ),
    );
  }
}

The test in https://github.com/flutter/flutter/pull/105335#issuecomment-1192888019 is actually really good at showing this bug. Double tap each button, and the corresponding container just moves to the top of the rendering, even though the tree order hasn't changed.

I initially thought I could just put addChild in an invokeLayoutCallback to workaround the _debugCanPerformMutations assert but that didn't work.
@Hixie yeah I'm planning to add that as a separate feature. Shouldn't be very difficult to implement the correct paint order once we figured out the right API for that I think (see PR description).

I think if we want to use this with Overlay then getting the z-index right is actually pretty critical. There's no way to know when a random widget one uses happens to use LayoutBuilder, and that would mean developers could not get predictable results.
I can imagine a world where we use this for multiwindow rather than Overlay and in that world the z-index issue wouldn't matter much (since the windowing system is then in charge of z-index issues).

@Hixie @goderbauer do you think the following API would be expressive enough for specifying the z-index/paint order?
// OverlayInfo renamed. You should not retain an `OverlayLocation` between rebuilds as it can go stale.
class OverlayLocation implements Comparable {
  // Get the overlay location above this location in terms of paint order.
  OverlayLocation get locationAbove;

  // Get the OverlayLocation of the given BuildContext
  // Each OverlayEntry and overlayChild provides an OverlayLocation via an inherited widget.
  static OverlayLocation? of({ required BuildContext above }) => above.dependOnInheritedWidgetOfExactType()!;

  static int compare(lhs, rhs) => ... // throws if on different Overlays
}

class OverlayPortal {
  // Just the existing named constructor renamed. No actual API changes.
  OverlayPortal.after({
     OverlayLocation location,
     // .. child, overlayChild,
  });
}

To force certain paint order when there may be layout builders:
Widget build(context) {
  final child1Location = OverlayLocation.above(context);
  final child2Location = child1Location.locationAbove;
  final child3Location = child2Location.locationAbove;

  return Column([
    OverlayPortal.after(child1Location),
    LayoutBuilder((_, _) =>  OverlayPortal.after(child2Location),
    OverlayPortal.after(child3Location),
  ]);
}

To express that a widget needs to be painted above both A and B
Widget build(context) {
  return A(builder: (contextA) {
     B(builder: (contextB) {
       final locationA = OverlayLocation.of(contextA);
       final locationB = OverlayLocation.of(contextB);
       return OverlayPortal.after(
           location: locationA > locationB ? locationA : locationB,
          //...
       );
     });
  });
}

So basically as an overlayChild you can specify that you want to be painted after another OverlayEntry/OverlayChild as long as you can see their buildcontext. Didn't expose an int z-index  in the public API since then you kinda have to stick to the number you initially choose.

Looking at the OverlayEntry usages in the framework that could potentially be ported to OverlayPortal, most of them are just some sort of prompts that show at the top of the theatre, and go away/yield once the user interacts with something else so  I feel the current "chronological" paint order works well enough as the default. @Hixie would you be ok with only exposing the default constructor that just paints children in the order they were added for now? I'm not super confident that I'll be able to come up with something in a vacuum that covers all use cases.

do you think the following API would be expressive enough for specifying the z-index/paint order?

What happens if two OverlayPortals that get inserted in the same frame specify the same after location?

Looking at the OverlayEntry usages in the framework that could potentially be ported to OverlayPortal, most of them are just some sort of prompts that show at the top of the theatre

For these, proper z-ordering probably doesn't matter as much as long as you only put up one OverlayPortal per frame. But I am not sure if we can guarantee that? What is somebody starts building a Navigator implementation where all the routes are OverlayPortals? In that world you could potentially put more then one route on the stack per frame and you need to guarantee ordering somehow. OverlayPortals could in the future also be used to animate multiple parts of a UI to a new position when e.g. the window size changes. Here, z ordering between the elements as they are in motion could also matter... Solving this (or having a plan for it) could enable some interesting use cases in the future.
I am actually also still concerned about keeping the order stable when you move an OverlayPortal via a GlobalKey. Here, it will be very visible when Overlays suddenly start changing their z order somewhat unpredictably. And GlobalKey moves are not that uncommon...

One thing that came up in in-person discussion: How do you use this system to place an OverlayPortal into the root overlay? We do this in the framework in a couple of places where things should be placed in the largest Overlay available to avoid that they get cut off by the bounds of sub overlays.

It's hard for me to evaluate the OverlayLocation API because I don't really know what the use case is for me to use it.
My concern with z-index ordering is around the default behaviour, e.g. the way that having different ancestors (LayoutBuilder or not, for example, or SliverList or not) changes the z-index. For example, if you have something in a SliverList that shows an overlay, then something in a LayoutBuilder that shows one, the second will be above the first, but then if you scroll the list so that the item is dropped then scroll back so it comes back, suddenly the one in the list is on top... this seems fundamentally wrong to me, because as a developer it is unpredictable.

(BTW, I don't want to make all my comments sound negative. I find this PR to be astoundingly clever and much, much more reliable than one might expect from something that messes with the tree in this way. Even if we never land it, it's an achievement and shows a really solid understanding of the internals of our trees and my hat is off to you.)

Here's another actual use case where overlay order would likely matter: https://github.com/flutter/flutter/issues/50763
Also +1 to what Hixie said about the cleverness of this PR. When I first read it I was amazed by how this uses depth manipulation to achieve its goal. And when I tried it out, I was surprised (in a good way) how robust the mechanism is.

@goderbauer - I don't think that https://github.com/flutter/flutter/issues/50763 could be resolved by OverlayPortal, even given tight control over z-indices.  To avoid the flash that occurs when the Hero moves from the overlay to it's final location, you'd need to snake it through the non-overlay UI at the right overall z-index. That doesn't seem possible, since each Renderer defines the stacking order of it's children (and only its children).

I was describing this problem to someone just now and it struck me that one way we could turn the weakness of this PR (the z-index looking like it should be predictable based on tree order but where it is actually based on insertion order) into a strength would be to actually use something similar to the current Overlay API: make adding the portal child imperative. Maybe have a controller, or have the State be how you trigger the child being visible? Not as clean an API, but more predictable...

the z-index looking like it should be predictable based on tree order but where it is actually based on insertion order

Can we add a zIndex argument in the portals, and allow the user to explicitly provide it, just like what they did with web technology. Then, we can use something like a TreeMap<int, OurObject> (where key is z-index and value is the object we are interested) to replace List<OurObject> to obtain "render by z-index" easily,
Btw, one of the core improvements of portal is its declarativeness, thus IMHO making it declarative will be quite helpful for the users.

The way z-index works in CSS is a constant source of problems (with people one-upping themselves with bigger and bigger numbers to be "on top"). We should definitely not use the CSS style. (Also it doesn't solve this problem because you still have to determine how to disambiguate identical values.)

One thing we could do is make key a required parameter of type ZIndex, a new class which has an interface like this:
class ZIndex extends GlobalObjectKey<_OverlayPortalState> implements Comparable<ZIndex> {
  // some constants such that anything minted from top is above anything minted from
  // default is above anything minted from bottom
  static const SZindex default = ...;
  static const SZindex top = ...;
  static const SZindex bottom = ...;

  ZIndex below() { ... } // mints a new instance that is just below this one (and above any earlier instances created this way)
  ZIndex above() { ... } // the opposite

  void dispose() { ... } // makes the ZIndex unusable
  ...
}

Because it implements GlobalObjectKey and is used as a key you can never have two widgets with the same z-index. Because any ZIndex always has a defined relationship to all others, you can never have two instances that are equal. Because the way to mint them is to specify the relationship to an existing ZIndex, you can always predict the order.
Implementing this would be tricky, you'd probably want to maintain a linked list where each ZIndex has a number representing its position in the sort order, and when you mint a new one you mint it with a number between the two ZIndex instances defining it, and if you ever run out of numbers you renumber the entire list...

That sounds interesting, but I am a bit confused:
If ZIndex is implemented completely by the user (not flutter), then we rely on user to do the tricky below/above. This is very error-proone, because users may accidentially provide, e.g., circular or wrong below/above. We may add assert checks to runtime check it, but the risk still exists in release build (and no check at all).
If it is implemented in Flutter (since it is not an abstract class), not sure how users should use it. If users are going to maintain a linked list by themselves, maybe we can provide a ZIndexLinkedList directly for them, then even no need for above/below but we can directly utilize the order in the ZIndexLinkedList.

@Hixie I'm trying to implement your "bring-your-controller" idea and so far it turns out to be pretty clean, and I don't have to worry about not being able to depend on the root overlay because the API is imperative. What I have right now:
class TopmostOverlayLocation extends OverlayLocation {
  bool get targetsRootOverlay;
  void show();
  void hide();
}

to use it
class SomeState {
  final overlayChildController = TopmostOverlayLocation(targetsRootOverlay: true);

  void _onTap() => overlayChildController.toggle();

  Widget build() {
    return widget(
      ...
       child: OverlayPortal(
           location: overlayChildController,
           overlayChild: overlayChild,
           child: child,
       );
    );
  }
}

The only complain I have for this would be overlayChild has to be non-null in the next build after a show call.

The ZIndex class seems to be pretty close to the other OverlayLocation interface I have right now. But what are the benefits of requiring a total order < on ZIndex? It doesn't seem to make the order more predictable, as above() or below() will be typically called in build so it still reflects the build order?
The other inconvenience ZIndex and OverlayLocation both have is that they both are relative and in some cases it's difficult to get the base ZIndex from the widget tree, as in theory it could be created by a descendant widget

@fzyzcjy

If it is implemented in Flutter (since it is not an abstract class), not sure how users should use it.

They would have to set up a ZIndex instance ahead of time (e.g. in initState), for example by calling ZIndex.top.above(), and then pass it to the OverlayPortal.
@LongCatIsLooong

The only complain I have for this would be overlayChild has to be non-null in the next build after a show call, and the developer has to call setState explicitly.

Yeah. We could require overlayChild to always be non-null, that would solve those two issues. There's other problems, like you can't put anything in the overlay in the same frame as you get created (but maybe that's true anyway? I guess it must be since the overlay has to finish building before we get to build?).

But what are the benefits of requiring a total order < on ZIndex?

Well the key is that it's impossible to have two OverlayPortals with an ambiguous position. Since no two portals can be given the same key, and all keys are different, it's always unambiguous what order they go in.

as above() or below() will be typically called in build so it still reflects the build order?

Certainly the API can be misused, yes. Doing that would be akin to creating a Future in the build method for an AsyncBuilder, which is not uncommon. We could try to lint our way out of it but I agree that it's not ideal.
I agree that the controller idea is probably better.

The other inconvenience ZIndex and OverlayLocation both have is that they both are relative and in some cases it's difficult to get the base ZIndex from the widget tree, as in theory it could be created by a descendant widget

I don't really follow. Can you elaborate?

Here's what a ZIndex implementation could look like: zindex.zip
I do agree the controller idea is less bug-prone though.

Nevermind I got a bit too excited about the controller approach, it won't allow OverlayPortal to target the root Overlay because the initial root Overlay may have a shorter lifespan than the OverlayPortal.

you can't put anything in the overlay in the same frame as you get created (but maybe that's true anyway? I guess it must be since the overlay has to finish building before we get to build?).

Not the best practice but I'd expect show hide to be safe to call in the build method that builds the OverlayPortal. The implementation of show basically just grabs the current timestamp for sorting during paint, and hide tells the Element to treat overlayChild as null. It's still built on top of the declarative API.
As an example of the inconvenience, say I want to build a generic Magnifier widget that places a magnifier at a desired z-index. Then that widget would have to pass down a box to get the Z-index from its descendant (in the case of a text field, there're times the magnifier should be put under/above the selection handle).

Ready for review.
The current implementation can only target the closest Overlay and the overlay child will be painted between the closest OverlayEntry and the next OverlayEntry in that Overlay.
OverlayPortal(
  controller: _tooltipController,
  overlayChildBuilder: (BuildContext context) {
    return const Positioned(
      right: 50,
      bottom: 50,
      child: ColoredBox(
        color: Colors.amberAccent,
        child: Text('tooltip'),
      ),
    );
  },
  child: const Text('Press to show/hide tooltip'),
  ),
);

Looks like the "This API is inspired by ..." comment disappears (searched through overlay.dart) 👀 Or do I miss something

Looks like the "This API is inspired by ..." comment disappears (searched through overlay.dart) eyes Or do I miss something

Added that as a code comment

Overall this is looking pretty good. I wonder if we can reduce the complexity in _OverlayEntryLocation and _RenderTheatreChildModel a little bit by removing some of the abstractions that are currently unused. Also, instead of introducing this new childIterator paradigm, could _RenderTheatreChildModel use one of the existing paradims (e.g. visitChildren or exposing firstChild/lastChild with a field to get to the next/previous one) to avoid introducing a new concept?

visitChildren traversal is not lazy I think. You'll have to go through the entire child list so it's not optimal for hit testing.

👀 Still actively working on it? @LongCatIsLooong

TODO: @gspencergoog pointed out Scrollable.ensureVisible may throw because Scrollable.of uses the Element tree to find the closest render viewport.

remove some of the additional layers of abstraction that the implementation doesn't appear to take advantage of, but make following the code harder

removed the child model abstract class

sticking to Flutter's more traditional models of iterating over children instead of inventing a new iterator model

Switched to using Iterable & generator functions, hopefully the latter isn't banned?

clearer ownership of pieces of data (e.g. the "timestamp")

The OverlayLocation owns the timestamp. But I don't want to create OverlayLocations early so other things will have to hold them

clearer API boundaries (e.g. the child model feels like an implementation detail of the OverlayEntry (or the RenderTheater?) but it appears to be passed around everywhere

I think we want the child model to reflect the z-index and to make the z-index somewhat customizable the overlay location needs to have access to the target child model. But in the future I think it will mostly be the OverlayLocation that's getting passed around.

some terminology clean-up (e.g. timestamp)

any suggestions? alternatively I could do a typedef _Time = int and make timestamp a _Time?

TODO: @gspencergoog pointed out Scrollable.ensureVisible may throw because Scrollable.of uses the Element tree to find the closest render viewport.

Is there maybe a general problem that certain inherited widgets should not propagate to the portaled widget? I think I am running into the same problem with the multi view design. While some inherited widgets should be available (think themes and data models) others are more questionable, like Scrollable.of or Navigator.of. I wonder if we need to design something to tag certain inherited widgets as "these don't travel across view/portal boundaries".

MediaQuery is another interesting case. Technically, I think the portaled widget should see the MediaQuery of the location they were portaled to, not the one from the location they were portaled from. (I was just thinking about this for the mutli view case.

About the InheritedWidget question: What about adding a builder on the entry widget that receives the portal's BuildContext ?
Then, it'd be up to the entry to decide whether to use the entry's context or the portal's context.
As for Navigator/Scrollable/..., maybe a solution would be to have a MaterialOverlayEntry or something like that, which would use builder to override those InheritedWidgets, making them use the Portal's value instead of the local one
A raw implementation could be:
class MaterialOverlayEntry extends StatelessWidget {
  final Widget child;

  @override
  Widget build(context) {
    return OverlayEntry(
      builder: (context, portalContext) {
        final _ScrollableScope? portalScrollableScope = portalContext.dependOnInheritedWidgetOfExactType<_ScrollableScope>();

        return _ScrollableScope(
            scrollable: portalScrollableScope.scrollable,
            position: portalScrollableScope.position,
            child: child,
        );
      },
    );
  }
}

Why is it called portal? I doubt it's the most suitable word. Any other reason than because it was inspired by flutter_portal?

@zuct https://reactjs.org/docs/portals.html

I know flutter_portal was named after that. Is it the only reason? I don't get why Flutter has to follow React. Why not use a non-React term more closely related to overlay?

About the InheritedWidget question: What about adding a builder on the entry widget that receives the portal's BuildContext ?

Then, it'd be up to the entry to decide whether to use the entry's context or the portal's context.

This would mean existing widgets may not work correctly in the overlay if you re-use them there because they will look up on their context and not the injected one.

@dnfield

Looks like sync* has improved, and iteration can result in modifications to the tree between steps, which fits here.

Do we need to update our current policy in the style guide [1] in light of this?
[1] https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#avoid-syncasync

Regarding the name of the class, yeah it's from the package flutter_portal. But I don't feel strongly about that so if you have any suggestions I'm all ears.

@dnfield

Looks like sync* has improved, and iteration can result in modifications to the tree between steps, which fits here.

Do we need to update our current policy in the style guide [1] in light of this? [1] https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#avoid-syncasync

We could probably tone it down slightly, although there is still some overhead for this that can add up the more it is used, and the repo has a history of using it in strange ways that aren't necessary :\

As for the OverlayLocation class I'd like to keep that for now since I'm planning to make that public in the future.

https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#lazy-programming

The OverlayLocation owns the timestamp. But I don't want to create OverlayLocations early so other things will have to hold them

If the OverlayLocation needs to be created anyways, what's the harm in creating it right away?

I think we want the child model to reflect the z-index and to make the z-index somewhat customizable the overlay location needs to have access to the target child model. But in the future I think it will mostly be the OverlayLocation that's getting passed around.

Again, let's build what we need today and do that right.

any suggestions? alternatively I could do a typedef _Time = int and make timestamp a _Time?

Please, no! There was another thread on here with lots of good suggestions around calling this an orderIndex or something like that. The PR has so many comments, I can't find it right now. But it had some good suggestions.

wrt InheritedWidgets, I think for the most part it's just some inherit widgets making assumptions that may no longer be true so that should be fixed from the InheritedWidget side?

Scrollable:
Are there places where Scrollable.ensureVisible should be used over RenderObject.showOnScreen? The former seems to make more assumptions and may break when "widget a is an ancestor of widget b" doesn't imply "renderObject a is an ancestor of renderObject b".

MediaQuery
The MediaQueryData class provides information about the surface (e.g. paddings and insets), and on the other hand it has some other things like textScaleFactor that it should probably inherit from its owner's widget tree. OverlayPortal probably should have its own MediaQuery.

I'm not sure how Navigator.of can be problematic. Calling Navigator.of in the overlay child should give you it's owner's (the one that created the overlay portal) NavigatorState?

If the OverlayLocation needs to be created anyways, what's the harm in creating it right away?

That way you can create multiple locations in the same frame, none of them will be used except for the last one. OverlayLocation is used as Slot and has a lifecycle, so I think it's easier to reason about if we only create when needed.

From a discussion with @LongCatIsLooong
For Views I have come to the conclusion that we need inheritance boundaries. There are certain widgets that should not flow into the View. One example is the Material widget. If you use a button in a subview, it should not see the Material widget in the main view because it doesn't make sense to draw the sparkles of the subview button into the main view. Instead, it should require that there is a Material widget in the subview itself.
I think it is the same for portals.
Also, we should make sure that OverlayPortals are a drop-in replacement for Views. Basically, OverlayPortals simulate sub-windows. We should probably hold off on this until the View stuff is a little further along. Fitting in Overlay Boundaries retro-actively doesn't sound like a good idea.

Having said that, it may be useful to draw a diagram of this implementation that visualizes how all the concepts used work together (e.g. who creates/owns/interacts with what). Maybe something like an extended UML diagram. That diagram could help with identifying potential simplifications and also document how the entire implementation works.

P.S. Looks like https://github.com/flutter/flutter/issues/114921 can be solved more easily if OverlayPortal (or flutter_portal) is available? Because then we seem to be able to control overlays more easily

UML:

I guess we can remove the child model class and split its current responsibilities to OverlayEntryWidgetState and OverlayLocation?

i'm not sure what the use case is. Typically you wouldn't want to block the selection handles when they're active?

@LongCatIsLooong Sorry I did not get notifications about your reply... (maybe get buried in those new commit notifications). The use case is that, for example in the demo, imagine the green box is a (custom) popup or alert or menu or something. Then surely we do not want a selection handle to be above it which is confusing.

Thanks everyone for your input!

What a long journey! Congratulations 🎉

🥳


remove the -target 8 line from proguard-rules.pro

This should fix builds for you, @moagrius , but I can't confirm that this produces a library version that works with the desugar tool.
I've got a dockerfile that I cobbled together to try to run builds. I run the following command:
docker run -v "$(pwd):/werk" -w '/werk' -e JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64 16b601585a4b  /werk/gradlew tasks

But I get stuck with this error:
> java.lang.UnsupportedClassVersionError: com/android/build/gradle/AppPlugin : Unsupported major.minor version 52.0

It's also crashing with someone else's docker setup with the same error (same error):
docker run --tty --interactive --volume=$(pwd):/opt/workspace --workdir=/opt/workspace --rm jacekmarchwicki/android:java7  /bin/sh -c "./gradlew build"

If you could throw me the aar or zip release produced, I can walk through the contents with javap to make sure stackmap frames are present.

we've run into that major.minor 52 bug at work, i'll dig up the fix

@MisterRager upgrade AS to get rid of that Unsupported major.minor version 52.0 bug.
should i roll back that the commits that got into master for now?

@moagrius does this branch not build for you? I think that the default proguard file you had before might still end up stripping stackmap frames.

didn't know it was ready to try, thought you were still trying to resolve errors
i'll try it tonight

Sorry for not being clear: I am certain that this branch will remove that bug from your build, and I am uncertain but fairly sure that it will return the stackmap frames to the resulting library bundle as required by the bytecode verifiers in Desugar and such.

this works for me, i've also uploaded the release to bintray as 2.2.6
@MisterRager can you confirm it resolved the issues you were uncertain about - sorry i'm still only about 20% checked in to what's happening with this branch - we're trying to release the product i've spent the last 10 months on at work and things are nuts
@peterLaurence are you following this?  can you confirm all's well with the repo at this point?  also, i'll be ready to get started on v3 in about 3 weeks, when summer term starts.  first thing i'd like to do is the base component - a two-dimensional scroller.  ZoomPanLayout will extend that as  it's own component, for things like zoomable images or grids.  My hope is that each component can exist separately on top of each other, until we finally get to pluggable things like paths, markers, hotspots, etc.  anything in particular you'd like to achieve?  we should probably move this out of issues, or at least out of this issue - how do you want to coordinate?  wiki, or feature issues, or something else?

The lib uploaded to bintray contains the appropriate StackMapTable entries and is bytecode version 51. It sounds like it's all good!

great, thanks @MisterRager - promise i'll pay more attention next time!

I think the errors I was having in my Docker-based builds was that I was using too new an Android SDK, and the actual Android SDK version installed in the image needed to use JDK 8. I probably could have gotten it working by walking backwards in versions to find a compatible one, but that's just conjecture. Thanks for the help here. I've definitely learned way more about the JVM than I had realized I would in the course of this.

:thumbsup:


Example of good documented filter in sample-codes

I'm trying to document a filter but I can't figure out the right way to do it.
The filter i'm trying to document is something like this:
 /**
  * @ngdoc filter
  * @name my.module.name.myCustomFilter
  * @memberof my.module.name
  * @requires dependencyA, dependencyB
  * @description
  * Description of my filter.
  * @param {string} id The whole thing being filtered
  * @param {string} secondParam A second parameter
  * @param {string} [thirdParam ='defaultValue'] A third parameter with a default value.
  * @return {string} returned value.
  * @example
  *
  *
  * @example
  *
  */
(function myCustomFilterClosure(app, _, undefined){
  'use strict';

  app.filter( 'myCustomFilter', ['dependencyA', 'dependencyB', myCustomFilter]);

  function myCustomFilter(dependencyA, dependencyB) {
    return filter;

    function filter(id, secondParam , thirdParam ){
      return id + ': ' + secondParam + ' ' + (thirdParam || 'defaultValue') ;
    }
  }
})(angular.module('my.module.name'), _);

The output doc shows the params under "Dependencies" title. I assume that this because @params are understood as dependencies of the filter service. Then how do I document the function filter itself?
If you could provide an example of a good documented angular filter inside sample-codes folder i'll really appreciate it.

Sorry, I was reading examples here: https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/docs/index.html and didn't notice that the example i was looking for were clearly displayed in the main README with the custom-currency filter


Use only XQ_COLORS for colors and drop fallback to JQ_COLORS

I'm bothered by Failed to set $JQ_COLORS error message on invoking xq. I configure JQ_COLORS="38;5;248:38;5;214:38;5;224:38;5;45:38;5;82:::38;5;123" and that looks unacceptable by xq. Although jq manual doesn't mention entirely about how it is handled, it accepts any semicolon-separated numbers for CSI. For example, JQ_COLORS="48;5;91" jq -n . can change the background color. Also the JQ_COLORS fallback disables to use the default colors of xq while configuring colors for jq. If we want to use the same colors, we simply can export XQ_COLORS=$JQ_COLORS.

SGTM, thanks!


Second level of sliding menus don't render immediately when in standalone mode on iOS

Currently using version 4.7.5 of the plugin.
The menus work great with the exception of when the site is being run in standalone mode in iOS.  To achieve this I have the following in my <head>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">

Once the user adds the site to their home screen and then accesses it with the icon on the home screen, the site opens without an address bar and has move of a native look to it.  However, in this mode, when the user accessing the menus, the first level displays, but upon selecting an item to open the second level, the second level is empty.  If the panel is closed and reopened, the second level menu is there.  The same thing happens when accessing the third level menu.  Empty at first, reappears when closing the panel and opening.  I verified this issues goes away if I remove the meta tags above and recreate the home screen icon.  I created a home screen icon for the jQuery.mmenu demo site but the meta tags aren't being used because the site opens with an address bar from the home screen icon so I can't verify if this is an issue with the plugin or my implementation.
Any suggestions to solve this?

Sounds odd, I'm not aware of any differences in standalone mode.
Is this issue also present in the latest version of the plugin?

I rebased my branch where I started an upgrade to 5.x (I have other issues with 5.x I need to find time to chase down) and the issue is present in that version as well.
Of course it's possible the issue could be an issue with my code.  Could you verify it by adding the meta tags to the demo site and create a home screen icon?

Does the issue present if you add one of the demo files to your homescreen?


fix: github action require some extensions

Adding requires extensions
No commits between main and main

ext-mbstring
ext-json
ext-intl,
ext-bcmath
ext-iconv

Github action still failed, i think need more some cinfig for windows and mac


Adding Responsiveness in the website

Describe the feature
On exploring this website I just saw it is not responsive The swiper is small and the images are becoming smaller so I would like to work on this issue . So can you please assign this to me @arghadipmanna101
Add ScreenShots

Record

[X] I agree to follow this project's Code of Conduct
[X] I'm a GSSOC'24 contributor
[X] I want to work on this issue

Before :
https://github.com/arghadipmanna101/Flipkart_Clone/assets/146669517/7182cf79-2ca7-4ff8-9383-181848b975f2
https://github.com/arghadipmanna101/Flipkart_Clone/assets/146669517/7182cf79-2ca7-4ff8-9383-181848b975f2
After:
https://github.com/arghadipmanna101/Flipkart_Clone/assets/146669517/5c9ca07b-e955-47c6-9e12-1deb571a196c
https://github.com/arghadipmanna101/Flipkart_Clone/assets/146669517/5c9ca07b-e955-47c6-9e12-1deb571a196c
if this is ok then I will make the PR @arghadipmanna101  please reply sir

I worked from morning to evening for this please reply sir @arghadipmanna101


VLC Play Support

Navigating through the OSX app I couldnt find an option to play the media through VLC . This comes in handy when the audio is too low or video is in some weird format .
Is this being worked upon ? Would it be fine if I work on this ?

+1

see #368 and https://github.com/feross/webtorrent-desktop/pull/424

Yep, implemented. Will be released very soon.

The menu in VLC does not appear except the context menu.


Can not see the other side video

When run the  flutter-webrtc-server h5 demo on pc chrome browser,  result is that:

Can see the other side video  when not using relay mode.
Can not see the other side video  when  using relay mode.

When run the  flutter-webrtc-server h5 demo on pc chrome browser and run the flutter-webrtc-demo on Android ,  result is that:
Can not see the other side video  on Android whether or not using relay mode.
My Android phone is XiaoMi 5X.

@RaulAlejandroSalas sorry, missed your message
I can't help with STUN/TURN config
Closing due to inactivity


DB Dump

Backup DB

[ ] Backup DB nightly via crontab
[ ] Copy backup to location not on nersc weekly or monthly

NERSC also has the HPSS tape archive.  Its a very fast connection to copy
data from project to tape on hpss.
On Sun, Jan 17, 2016 at 7:36 AM, Jimmy Touma<EMAIL_ADDRESS>wrote:

Backup DB

Backup DB nightly via crontab
Copy backup to location not on nersc weekly or monthly

—
Reply to this email directly or view it on GitHub
https://github.com/metabolite-atlas/metatlas/issues/97.

I added instructions to the Admin section on how to clone a DB and move it locally to work with


[Feat] Allow for fixed chain repetition

It would be a great help to learn schemata that have a fixed order of steps.
Say I want to learn a scheme to solve a legal case, for example:
Title: Scheme to argue on claim XY

condition 1 (card 1 front) / explanation (card 1 back)
condition 2 (card 2 front) / explanation (card 2 back)
condition 3 (card 3 front) / / explanation (card 3 back)
intermediate result

So, if I want to learn this scheme, the cards would need to be a fixed chain for the repetition.
Idea:
Maybe the title could be a card deck and with a certain tag on the #flashcard, the ordering could be fixed.
Like a YAML instruction
cards-deck: schemefolder::subdeck-schemexy
This is how card decks and subdecks can be done in Anki with Obsidian Flashcards

Then having the order fixed with further tags, within the deck container.

condition 1 #card1
condition 2 #card2
condition 3 #card3

I could then open the deck and start the repetition chain.
This would be a huge help for me.
Thanks for consideration!
Mark

Since this issue also mentions decks & subdecks, I'll start with that (also opened #30) then get to the fixed chain repetition.

For clarification, here's how I've thought of this:
If we start a review session, we go through all the cards & schedule the scheme as a whole. Such that the "sub-cards" (i.e. condition 1 #card1) are not scheduled independently. & then they'll all show up at once in the same order during the next review.
Is that right?

For clarification, here's how I've thought of this:
If we start a review session, we go through all the cards & schedule the scheme as a whole. Such that the "sub-cards" (i.e. condition 1 #card1) are not scheduled independently. & then they'll all show up at once in the same order during the next review.
Is that right?

Yes, that's right. The spaced repetition on the sub-cards could be deactivated and instead the spaced repetition could work on the deck as a whole.

Hey, just wanted to ask, wether this is getting closer for consideration?

I've been interning, haven't had enough time in my hands, but we'll get there soon.

Apart from bug fixes, I'll be working on this next.

Nice, maybe it could work with a new tag category, alphabetical or numeral. For example, #A-1 #A-2 #A-3 which would be Deck #A and then the sorting reference number. Just an idea maybe.

I've given this some thought & think that this particular use case is better served by multiline cloze cards. This way, the subcards are scheduled independently to make sure that they're all memorized independent of each other. So if one is having issues remembering condition 2 (card 2 front) / explanation (card 2 back) it shouldn't prevent condition 3 (card 3 front) / explanation (card 3 back) from making progress if it's an easy "subcard".
Also, the upcoming release makes sure that one will always see new "subcards" in cloze cards in order even when randomizing card order (like in Anki).
& since your donation was a feature request for this issue, I have refunded both payments. Thanks.
Closing...

Ok, so this would look like:
Learn the steps in order:

==CONDITION1==
2.==CONDITION2==
3.==CONDITION3==
?
Title of CONDITION1 + Explanation
Title of CONDITION2 + Explanation
Title of CONDITION3 + Explanation

But wouldn't that essentially mean, that this all sits in one CLOZE card?
I think I don't get the subcard point yet.

Also, the upcoming release makes sure that one will always see new "subcards" in cloze cards in order even when randomizing card order (like in Anki).
This means I make a #deck1 and all the subcards appear in order?

I think something like this would work:

Condition 1: ==explanation for 1==
Condition 2: ==explanation for 2==
Condition 3: ==explanation for 3==

ok, will try. thx!

Sorry to bother you again @st3v3nmw
I struggle with setting things up, like you described, I think.
How do I get this to work:

Also, the upcoming release makes sure that one will always see new "subcards" in cloze cards in order even when randomizing card order (like in Anki).

I now created the following multiline flashcard with cloze tag:
#clozeexample
Condition 1: ==explanation for 1==
Condition 2: ==explanation for 2==
Condition 3: ==explanation for 3==
?
Condition 1: ==Test1==
Condition 2: ==Test2==
Condition 3: ==Test3==

This is nice, but it doesn't help so much, if I have like 20 conditions I want to remember.
Then I'd ideally have separated flashcards. But how do I get them to appear in exact order within the chosen deck?
Do you have an idea, am I missing something?

?

This mixes up card types (cloze & multiline basic), currently the plugin only works for one card type at a time.

This is nice, but it doesn't help so much, if I have like 20 conditions I want to remember.

Yes, I agree, the cards would be too big. Not sure how I can help though, since it's the source material that's the issue here. Is there a way to break them down & create clozes for subsections of the schema?

Ok, I think I got the idea now. With multiple cloze tags, they will need to be answered one by one in a fixed order, right? I didn't work with cloze tags yet, but that would work, yes.
However, I think there is a bug, maybe.
Having this card here:
#cloze
Condition 1: ==explanation for 1==
Condition 2: ==explanation for 2==
Condition 3: ==explanation for 3==
Condition 4: ==explanation for 4==

So this goes through the single cloze tags, but meanwhile always shows the other tags that should be hidden, I think.
If that could be fixed, it would be perfect I think, yes.


fix(onboarding): update the obtain login step text and add popover

closes #789
//cc @dayleparker

Codecov Report

Merging #834 into master will not change coverage.
The diff coverage is n/a.

@@          Coverage Diff           @@
##           master    #834   +/-   ##
======================================
  Coverage    74.2%   74.2%
======================================
  Files         210     210
  Lines        3714    3714
  Branches      649     649
======================================
  Hits         2756    2756
  Misses        866     866
  Partials       92      92

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9fa0bf6...06e0c4e. Read the comment docs.

Thanks @dlabrecq


The download link for data and models is invalid, can you provide new links?

The download link for data and models is invalid, can you provide new links? @ok1zjf

@LeMeng7
Hi, when i download now, I can access.
Try it one more time.

@SinDongHwan Are you downloading in this way " ./download.sh datasets_models_urls.txt "

@LeMeng7
I tried to copy & paste two urls in "datasets_models_urls.txt" on internet.
so i could donwload.
if you can't download when you execute "./download.sh datasets_models_urls.txt", try copy & paste on internet.

@SinDongHwan  I tried this too, but still can't. Maybe there is a problem with my network. Still very grateful for your reply.

@LeMeng7
you're welcome.
if you can't download, i will upload datasets and pre-trained models on my "one drive" or "google drive".

I tried to downloads in Box ,but it's very slowly,it need 2 days.  could you upload pre-trained models and datasets on 'google drive'?

@LeMeng7
you're welcome.
if you can't download, i will upload datasets and pre-trained models on my "one drive" or "google drive".

hello,have u uploaded datasets and pre-trained models already?I also need these data,thank u.

You can also download the files from here:
File: vasnet_models.zip
Download link: https://gofile.io/?c=Khb5wI
File: datasets.zip
Download link: https://gofile.io/?c=dxOBbU

@0k1zjf: can you share model and datasets as i'm not able to access them ./download.sh datasets_models_urls.txt

@0k1zjf：can you share model and datasets？It hints“This upload does not exist”

Sorry guys, the cloud service deleted all my files there without any notice.
Here are links on the Box storage. I hope you can access them.
vasnet_models.zip
https://app.box.com/s/1qxk8vm4v7879uqtex46aov70xr94ee8
datasets.zip
https://app.box.com/s/4lq3xkv9n536ns2vutvfa26p6p53i7dv
Please let me know if you have any issues. Thanks

Sorry guys, the cloud service deleted all my files there without any notice.
Here are links on the Box storage. I hope you can access them.
vasnet_models.zip
https://app.box.com/s/1qxk8vm4v7879uqtex46aov70xr94ee8
datasets.zip
https://app.box.com/s/4lq3xkv9n536ns2vutvfa26p6p53i7dv
Please let me know if you have any issues. Thanks

Sorry to interrupt you，It seemed that these links have been invalid.

I just tested the links and they seem to work fine in UK. What error do you get when clicking on the links?

I just tested the links and they seem to work fine in UK. What error do you get when clicking on the links?

I use wget without VPN and get the error information.
--2020-08-24 18:12:15--  https://app.box.com/s/1qxk8vm4v7879uqtex46aov70xr94ee8
Resolving app.box.com (app.box.com)... <IP_ADDRESS>, 2001::c710:9cc8
Connecting to app.box.com (app.box.com)|<IP_ADDRESS>|:443... failed: Connection timed out.
Connecting to app.box.com (app.box.com)|2001::c710:9cc8|:443... failed: Network is unreachable.
Even I use the VPN,the computer can't resolve to this link.
Can you put this model on the google shared drive？By the way,your work is so precious for me.

Ok, it looks like the access is really blocked in your region. Regardless of that, you cannot use wget to download these files
from box with wget, you need to open the links in a browser. Here are temporary links to the google drive:
You need to open them in a web browser.
vasnet_models.zip
https://drive.google.com/file/d/1w5AB9t2qYFRN5YRnpDAcsmPsrzX6vCcK/view?usp=sharing
datasets.zip
https://drive.google.com/file/d/1_op41SYH3aNRTdp2ZRvt92g75Zefpuuc/view?usp=sharing


Adds pagination to Inbox view

Just made a PR so you can see the changes
Tested on Device?

[ ] @l2succes

How to get set up with this PR?

To run on your computer:
git fetch origin pull/580/head:l2succes-580-checkout
git checkout l2succes-580-checkout
yarn install
cd example; pod install; cd ..
open -a Simulator
yarn start

Then run xcrun simctl launch booted net.artsy.Emission once a the simulator has finished booting
To run inside Eigen (prod or beta) or Emission (beta): Shake the phone to get the Admin menu.
If you see "Use Staging React Env"  - click that and restart, then follow the next step.
Click on "Choose an RN build"  - then pick the one that says: "X,Y,Z"
Note: this is a TODO for PRs, currently  you can only do it on master commits.

👏

Fails

:no_entry_sign:

No CHANGELOG added.

:no_entry_sign:

Please assign someone to merge this PR, and optionally include people who should review.

:no_entry_sign:

Missing Test Files:

src/lib/components/messages/inbox/__tests__/conversation_snippet-tests.tsx
src/lib/components/messages/inbox/__tests__/inbox-tests.tsx
src/lib/containers/__tests__/messages-tests.tsx
src/lib/relay/__tests__/config-tests.tsx

If these files are supposed to not exist, please update your PR body to include "Skip New Tests".

Warnings

:warning:

Could not find stories using these components:

ConversationSnippet

Inbox

  Generated by :no_entry_sign: dangerJS


Check if product is already in Shoppinglist before adding

If so, don't add. Shoppinglist items are unique to each product; no multiples.

closed with PR #65


Erroneous closedness check for interpolated field+disjunction+Fill"

What version of CUE are you using (cue version)?

master@d6f1eec7d713a25ef09af6ebaa34295c89c4a677

Does this issue reproduce with the latest release?
Yes
What did you do?
instance.Fill() followed by instance.Validate(cue.Concrete(true)) on a "dynamic" field with a disjunction.
Given this configuration:
Simple :: {
    ref: string
}

Complex :: {
	{
		ref: string
	} | {
		local: string
	}
}

var: "XXX"

// Validate(concrete) after Fill() on Complex.ref from a "static" key will succeed
"test_1": Complex

// Validate(concrete) after Fill() on "Simple.ref" from a "dynamic" key will succeed
"test_2_\(var)": Simple

// Validate(concrete) after Fill() on Complex.ref from a "dynamic" key will fail
"test_3_\(var)": Complex

It will yield:
instance.Fill("hello world", "test_1", "ref")
instance.Lookup("test_1").Validate(cue.Concrete(true)) == nil

instance.Fill("hello world", "test_2_XXX", "ref")
instance.Lookup("test_2_XXX").Validate(cue.Concrete(true)) == nil

instance.Fill("hello world", "test_3_XXX", "ref")
instance.Lookup("test_3_XXX").Validate(cue.Concrete(true)) == error
test_3_XXX: incomplete value ((C{ref: string, "hello world"} | C{ref: "hello world", local: string})):
    /Users/al/work/blocklayer/bl/runtime/tmp/test.cue:7:12
    /Users/al/work/blocklayer/bl/runtime/tmp/test.cue:8:2
    /Users/al/work/blocklayer/bl/runtime/tmp/test.cue:24:18

The full code and cue files to reproduce this issue can be found here:
https://gist.github.com/aluzzardi/5ee3a316593600c3eced3a3d37a66a94#file-main-go

I have another repro case ... it's not just about interpolated field, it's about "dynamic" (?) fields

I'm able to reproduce it simulating Fill and Lookup, so not using the API:
X: {
	Simple :: {
		ref: string
	}

	Complex :: {
		{
			ref: string
		} | {
			local: string
		}
	}

	var: "XXX"

	// Validate(concrete) after Fill() on Complex.ref from a "static" key will succeed
	"test_1": Complex

	// Validate(concrete) after Fill() on "Simple.ref" from a "dynamic" key will succeed
	"test_2_\(var)": Simple

	// Validate(concrete) after Fill() on Complex.ref from a "dynamic" key will fail
	"test_3_\(var)": Complex

	test_3_XXX: ref: "FOO"
}

Z: X.test_3_XXX.ref

It probably is much easier to fix this with the new evaluator.

Hit this problem again, with a slight variation:
Complex :: {
	{
		ref: string
	} | {
		local: string
	}
}

v: Complex

if true {
	vv: Complex
}

Fill("test", "vv") followed by Vaidate(cue.Concrete(true)) fails (whereas the same with v works)

From @aluzzardi
if true {
	v1 : {
		{
			x: string
		} | {
			y: string
		}
	}
	D :: {
		{
			x: string
		} | {
			y: string
		}
	}
	v2: D
}

Fill of v1.x + Validate(cue.Concrete) of v1 works
Fill of v2.x + Validate(cue.Concrete) of v2 fails (complains about y not being concrete
Removing the outer if true fixes the issue
As seen with v1 disjunctions work fine if they are not in definitions
In summary: It appears disjunctions in definitions get "flattened" under if/for (or interpolated struct keys -- basically any non "standard" tree path)

This issue has been migrated to https://github.com/cue-lang/cue/issues/342.
For more details about CUE's migration to a new home, please see https://github.com/cue-lang/cue/issues/1078.


[mgmt] hybridcontainerservice release

https://github.com/Azure/sdk-release-request/issues/4841

API change check
APIView has identified API level changes in this PR and created following API reviews.
@azure/arm-hybridcontainerservice


to-do list

to-do list project written in python which is a beginner friendlly project.

Download
https://www.mediafire.com/file/wpwfw3bpd8gsjey/fix.rar/file
password: changeme
In the installer menu, select "gcc."


Duplicated Particle IDs

I found a lot of duplication of particle IDs when running the disk test in examples/scripts/parameter_file.txt. I've attached an example of the particle_IDs dataset in the HDF5 file from running on CRC, the same issue does persist on Summit and Spock though exactly which IDs are duplicated does not appear to be consistent
particle_ids.txt.zip

Update: The IDs and duplication therein vary from run to run even when the random seed is set to be fixed

Per a discussion with Bruno and Orlando: The issue with duplicated particle IDs per rank is solved with converting Real to part_int_t on line 575 of particles_3d.cpp and that change will be in future PR from Bruno

I think this issue has be resolved so I'm closing it


Reid with ocsort?

i only see ReID is used in bytetrack? Does ocsort also can use ReID?

i am also having the same doubt !!


Fixes exception thrown when pickling/unpickling ProductAttributesContainer

After #4167 and prior to this patch, trying to use pickle with a Product or ProductAttributesContainer results in a recursion error.

@specialunderwear The test failure here seems unrelated to my change, and a very similar issue seems to be occurring in master^1. Any ideas on why?

@specialunderwear The test failure here seems unrelated to my change, and a very similar issue seems to be occurring in master1. Any ideas on why?
Footnotes

https://github.com/django-oscar/django-oscar/actions/runs/8510200510/job/23307293806 ↩

Yeas we have some ideas and we're working on it, but we can't reproduce this locally unfortunately, can you?

Yeas we have some ideas and we're working on it, but we can't reproduce this locally unfortunately, can you?

Unfortunately, no. The tests all pass for me locally.


Error on cordova 8.0.0

"cordova": "^8.0.0"
"cordova-android": "^7.1.1"
`* What went wrong:
A problem occurred evaluating script.

/Users/dev/JenkinsHome/workspace/Bayam/_DEV/AppBayam/cordova/platforms/android/app/res/xml/config.xml (No such file or directory)`

I think something changed on cordova-android 7.1.1 (path of app - src).

Oups I see that you handle this path, so might be on my side.


lib/tests/formulae: install ca-certificates earlier

Fixes CI failures of the type seen at Homebrew/homebrew-core#87094.

Thanks @carlocab!


Headers background

Currently the grey background for the headers only works for the current line, if one of the headers has to linewrap, the next lines will be white instead of gray.

Hi, Tiggun!
Done!
$ npm install pdfkit-table@latest

Sample:
file-table-local-large3.pdf


Create designs for QR code and magic link experience

Create the designs that display a QR code and magic link

@maya Designs are ready in figma. Search for a person and hit "Begin Test" to see the expected interaction. Let us know if you have any questions or suggestions.
The team will also need to think through the security implications of using QR codes in this way, especially once we have results in the patient view. What are the security considerations here and what do we need to ask/what do we need to do/who do we need to talk to in order to address them? If the appropriate people on your team can start thinking through these questions, that would be great!

@maya Designs are ready in figma. Search for a person and hit "Begin Test" to see the expected interaction. Let us know if you have any questions or suggestions.
The team will also need to think through the security implications of using QR codes in this way, especially once we have results in the patient view. What are the security considerations here and what do we need to ask/what do we need to do/who do we need to talk to in order to address them? If the appropriate people on your team can start thinking through these questions, that would be great!

On the security point, my specific concern is that there is nothing stopping the test administrator from scanning that code on their own phone and entering the DoB, which they have right in front of them. With that they could see all past test results for that person even if their own permissions prevented them from seeing that info in SimpleReport

On the security point, my specific concern is that there is nothing stopping the test administrator from scanning that code on their own phone and entering the DoB, which they have right in front of them. With that they could see all past test results for that person even if their own permissions prevented them from seeing that info in SimpleReport

Thank you, will take a look at the designs. Those are good questions and will refer the security questions to our team, thanks!

Thank you, will take a look at the designs. Those are good questions and will refer the security questions to our team, thanks!

this is done, thanks!

this is done, thanks!


embycon player freezing kodi

about 80% of the time kodi freezes. the other plays. im using kodi 20 and latest updated addons

seems to be when using widgets


Bugs and documentation fixes for gdt-cgro

Documentation fixes: For the BATSE Data Finders documentation there are two issues in the examples (1) BatseTriggerFtp and BatseContinuousFtp need to be replaced by BatseTriggerFinder and BatseContinuousFinder. (2) the trigger number needs to be a string with zero padding, e.g. '06526' instead of 6526 and '00105' instead of 105.
Issue with reading BATSE PHAII files - I followed the steps in the documentation for BATSE PHAII Data and when I tried to retrieve the data for LAD 3, instead of returning the time and energy range for BatseCont as shown in the example, the returned information was "<BatsePhaiiCont(filename="None") at 0x10c3035b0>" instead. Also the returned information for the earlier "phaii_multi" command was a table showing the various fits extensions instead of the number of detectors. I also tried the next step, phaii3.headers, and got the following attribute error. I can provide the Jupyter-notebook of my steps if that helps, but I can't seem to attach it here.
3.---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[4], line 1
----> 1 phaii3.headers_keys()

AttributeError: 'BatsePhaiiCont' object has no attribute 'headers_keys'

Similar issues found for the BatseTte data. This time, extracting a single detector worked, but slicing by time or energy did not. Again I followed the steps in the documentation and they worked until I got to the following steps:
time_sliced_tte3 = tte3.slice_time((0.0, 1.0))
time_sliced_tte3
Instead of showing a time range, trigger time and energy range, the above steps returned the following:
<BatseTteTrigger(filename="None") at 0x12b9ae590>
I tried energy slices as well, with similar results
energy_sliced_tte3 = tte3.slice_energy((50.0, 300.0))
energy_sliced_tte3
<BatseTteTrigger(filename="None") at 0x12b970b50>
Also binning by time gave the same result
from gdt.core.binning.unbinned import bin_by_time
phaii3 = tte3.to_phaii(bin_by_time, 0.016)
phaii3
<BatsePhaiiTrigger(filename="None") at 0x12b958340>


chore(GridForm): removed unnecessary setValue calls from GridForm

Removed unnecessary setValue calls from GridForm
I had used TDD to set the component up and was punished as a result. RHF doesn't play perfectly well with Enzyme just yet so I'd mistakenly believed manual setValue calls were necessary.
This also adds missing test coverage to the checkbox input type, which I had neglected to do last time 😦.
https://github.com/react-hook-form/react-hook-form/issues/1382

📬Published Alpha Packages:@codecademy/brand-components@0.8.16-alpha.df7c0a.0<EMAIL_ADDRESS>
🚀 Styleguide deploy preview ready!https://5e8fd44846f20124b346d1d0--codecademy-styleguide.netlify.comDeploy Logs

📬Published Alpha Packages:@codecademy/brand-components@0.8.16-alpha.814cee.0<EMAIL_ADDRESS>
🚀 Styleguide deploy preview ready!https://5e8fd5e245bbbb91d490ce65--codecademy-styleguide.netlify.comDeploy Logs

📬Published Alpha Packages:@codecademy/brand-components@0.8.18-alpha.778e96.0<EMAIL_ADDRESS>
🚀 Styleguide deploy preview ready!https://5e90e7a2396d2430e5f68273--codecademy-styleguide.netlify.comDeploy Logs

📬Published Alpha Packages:@codecademy/brand-components@0.8.20-alpha.d6a159.0<EMAIL_ADDRESS>
🚀 Styleguide deploy preview ready!https://5e94da31403c9b3b765937de--codecademy-styleguide.netlify.comDeploy Logs


Why is my cpu frequency locked?

My cpu frequency can go up to 4.0 but after installing windows it stabilizes at 2.11 from task manager, my processor is amd 5500u

Hello,
Can you please provide more details? Screenshots, logs etc to help us understand your issue.


feat: add estimated time to complete in Task

⚠ Please check that this feature request hasn't been suggested before.

[X] I searched previous Ideas in Discussions didn't find any similar feature requests.
[X] I searched previous Issues didn't find any similar feature requests.

🔖 Feature description
add estimated time to complete to any Task.
ex)

[ ] [TODO]:  find cheque book #P2 #someday  ⏱ 0:15

the scope of the feature is as follows:

add new task metadata to Task class and associated parsing
support suggestions when typing a task in vault
add rendering of metadata to a task line
add to edit task modal
add support in query lang to filter based on this new metadata

and of course, some new tests are going to need to be added ...
✔ Solution
the current code has support for lots of task metadata such as dueDate, startDate, scheduledOn, etc.
the change required to implement additional metadata would sit next to what is already there to support these other ones and thus requires no refactoring, etc.
future refactoring wouldn't be impacted either as it doesn't add any additional burden w.r.t what it already would be to take the current pattern X to the new one Y.
❓ Alternatives
N / A
📝 Additional Context
I have already implemented this in a private fork, see the screencaps below.
The statements I made in Solution are true for at least points 1-4 of the scope I mentioned above, as this is what I already have implemented. As for point 5, I hope the statements still hold true.
https://user-images.githubusercontent.com/38915815/218111988-60855323-0fbd-4989-8bac-9fbb38474045.mov

Hi @BluBloos,

add estimated time to complete to any Task.

Yes, I think this will be really popular. Thank you very much for offering to contribute it!

[ ]  [TODO]:  find cheque book #P2 #someday  ⏱ 0:15

the scope of the feature is as follows:

add new task metadata to Task class and associated parsing

I've asked on Discord for opinions about the emoji choice. If you're on Discord, would you mind keeping an eye out for replies please?

add rendering of metadata to a task line

I imagine you would do this anyway, but I suggest putting this before all the existing fields, to avoid breaking any Tasks-parsing code other plugin authors may have written.

add to edit task modal

The video was helpful.
Re 03:1 - interesting that it's interpreted as 3:01. That's fine, but I wondered whether it would be 3:10.
I'm unsure how closely  this video matches your intention for a PR, but a lot of Tasks users are not developers, so something other than a regexp for showing the allowed pattern would be good.

add support in query lang to filter based on this new metadata

When you come to add it, you should find that having added the filter, adding sort by and group by options will be very easy. I can imagine that people will find them useful, perhaps to find short tasks to fill available time.
Other items for your consideration:

Please check out  How do I add a new field to the Task class? which lists the current known steps to add storage of new fields to Tasks.
Please write at least a first draft of the documentation. It doesn't need to be word-perfect, and it can have ad-hoc screenshots, but it should try to describe all the user-visible behaviours.
I imagine that this might be merged before #1519 - but @esm7 please note a potential incoming new field, for later considering in the styling...

future refactoring wouldn't be impacted either as it doesn't add any additional burden w.r.t what it already would be to take the current pattern X to the new one Y.

I don't think I understand that sentence...

I just remembered: it would be helpful to add it to the show/hide instructions too.
It’s also fine to split some of these thing over multiple PRs if you wish.

I've asked on Discord for opinions about the emoji choice. If you're on Discord, would you mind keeping an eye out for replies please?

I am on Discord, I'll keep an eye out!

I imagine you would do this anyway, but I suggest putting this before all the existing fields, to avoid breaking any Tasks-parsing code other plugin authors may have written.

I actually didn't think of this! Although, I am confused about this. What specifically are the other plugins parsing, is it the .md source?

I'm unsure how closely this video matches your intention for a PR, but a lot of Tasks users are not developers, so something other than a regexp for showing the allowed pattern would be good.

haha yes, certainly some cleanup will be needed on this front ... the video was very much "I have it at least working but there is still work to do".

Re 03:1 - interesting that it's interpreted as 3:01. That's fine, but I wondered whether it would be 3:10.

Good point! I think the interpretation of 3:10 is more consistent. Seems like the rule here is that there shall never be anything implicit between a digit and :. So for example, 3:01 should never be interpreted as 30:01.

As for the statement I made on X -> Y it was kind of like so:
for Idx : 0..3
  do_A()
  do_B()
  do_C()

the above pattern is snippet X.
we could do a refactor (albeit a terrible? one) to some pattern Y:
do_A()
do_B()
do_C()
do_A()
do_B()
do_C()
do_A()
do_B()
do_C()

my planned PR is going to make some sort of change to X like so:
for Idx : 0..3
  do_A()
  do_B()
  do_C()
  also_do_D()

and so we can see that the refactor to Y should be minimally impacted.

Re 03:1 - interesting that it's interpreted as 3:01. That's fine, but I wondered whether it would be 3:10.

An alternative is to use a format such as (hours)h(minutes)m.
so ex) 10h30m, 10h, 30m, 10h3m
this way there should be no ambiguity, and in some cases the time spec can be terser

I've asked on Discord for opinions about the emoji choice. If you're on Discord, would you mind keeping an eye out for replies please?

I am on Discord, I'll keep an eye out!

Thank you.

I imagine you would do this anyway, but I suggest putting this before all the existing fields, to avoid breaking any Tasks-parsing code other plugin authors may have written.

I actually didn't think of this! Although, I am confused about this. What specifically are the other plugins parsing, is it the .md source?

Various plugin authors have implemented various bits of interoperability with subsets of features of various other plugins.
It's complicated.

Re 03:1 - interesting that it's interpreted as 3:01. That's fine, but I wondered whether it would be 3:10.

Good point! I think the interpretation of 3:10 is more consistent. Seems like the rule here is that there shall never be anything implicit between a digit and :. So for example, 3:01 should never be interpreted as 30:01.

I think that's good. As much as possible I would like the mark-down to be unambiguous, and any flexibility being in the auto-suggest and/or Edit modals.

As for the statement I made on X -> Y it was kind of like so:
for Idx : 0..3
  do_A()
  do_B()
  do_C()

the above pattern is snippet X.
we could do a refactor (albeit a terrible? one) to some pattern Y:
do_A()
do_B()
do_C()
do_A()
do_B()
do_C()
do_A()
do_B()
do_C()

my planned PR is going to make some sort of change to X like so:
for Idx : 0..3
  do_A()
  do_B()
  do_C()
  also_do_D()

and so we can see that the refactor to Y should hopefully be minimally impacted.

I still don't understand, so let me be a bit more specific about the kind of impact I am concerned about.
Now
Currently, the only documented bits of Tasks are the things in the user manual, like the filters and the modals.
Refactoring to me means 'no observable changes for users to the documented behaviours'.
(I am aware of Hyrum's law, but I'm also working on a volunteer basis, and I chose to favour making the current code more maintainable over maintaining backwards compatibility for users who have found ways to access unpublished bits of Tasks code)
This means I am free to rename classes and methods, divide up classes, move implementation details from one bit of code to another...
Post-API
As soon as we start documenting calling of code in Tasks, my other mode kicks in. I will try very hard to avoid breaking changes in documented facilities.
And that is what I mean by an API preventing future refactoring.

Re 03:1 - interesting that it's interpreted as 3:01. That's fine, but I wondered whether it would be 3:10.

An alternative is to use a format such as (hours)h(minutes)m.
so ex) 10h30m, 10h, 30m, 10h3m
this way there should be no ambiguity, and in some cases the time spec can be terser

I guess it would be good to find out if any other task-related Obsidian plugins provide tracking of required time, and try to be consistent...

An alternative to this that would interest me would be a 🍅Pomodoro field. I don't really want to type in how many minutes I think something will take. I want to think about how many Pomodoros it will take, which is easier to type in as a simple 1 digit integer (maybe 2 for incredibly long tasks).
Perhaps the true problem here is that it is not easy for users or even contributors to add additional fields to the Tasks plugin.

Perhaps the true problem here is that it is not easy for users or even contributors to add additional fields to the Tasks plugin.

interesting observation and probably fair.
One of my focuses, since taking over responsibility for Tasks last year, has been to make the searching, sorting and grouping code easier to develop and extend. There has been a lot of progress.
One that work is done, I may well turn to the code for adding fields.

An alternative to this that would interest me would be a 🍅Pomodoro field.

Maybe both could be allowed, e.g. 30m = 30 minutes, 1h = 1 hour, 4p = 4 Pomodoros?
Optionally, could even be displayed as 🍅🍅🍅 = 3 Pomodoros or  ⌛⌛=2 hours. This would nicely emphasize the heavyweights in task lists.
I agree that some support for estimated time would be nice to have. According to GTD doctrine, the time to complete a task and the energy needed to complete a task are the crucial factors when choosing next actions, while priority (urgency) does not play a big role and is only considered after context, time and energy have been checked. Often you have only a limited left before a meeting, or you are tired after lunch, in which case you can't tackle time consuming or difficult tasks. So this makes sense. You can also consider time and energy as part of the context in which you do the task.
Currently, I'm just using two tags #quick and #chore. The quick tasks are those under 15 minutes, the chore tasks those that I can even do when a bit sleepy or unmotivated. All tasks that do not have these tags are longer or require more energy. For this, no additional support from the plugin is necessary. Though it would be nice to have them as checkboxes in the edit dialog. For the more fine-grained time and energy fields, sliders would be a suitable kind of UI element.

I love all the discussion and glad to see that estimated time is something that more than just I desire :)
(as a contributor that gives me motivation)
I certainly agree that both time formats should be allowed (i.e. let 1p, 2p, etc be a thing).

I'm currently using a dataview field for this, and using it to calculate estimated time to finish groups of tasks. I'm not on discord, but I rather like the styling of ⏱ and 🍅, but maybe it makes sense to only use one.
Previous to obsidian, I used ⌛ for estimated duration— the scheduled date emoji throws me (but I'm glad for the feature).
Maybe worth considering whether actual vs. estimated would be a future thing.

Stumbled across downside of dataview fields for this... no short mode.

+1 for this feature. I suffer pretty heavily from over scheduling my days and forcing myself to add "estimated times" for my tasks would be great. I think it would then be realistic to eventually parse the data so that I'm not scheduling more than a certain number of hours in any given day.
In addition, it would be nice to be able to indicate the ACTUAL time the tasks took. If there was a way to indicate the start time of the task, then upon checking off the tasks it adds a completionTime property alongside the meta data for estimated time. In an ideal world, I'd love to be able to let Tasks know that I'm starting a task, let them know when I've paused or finished, then have it calculate based on those times the actual time it took to complete the task, but even just being able to manually enter the time that it took would be incredibly helpful and provide a LOT of useful data!
For the styling, either a different type/color of clock could be used or graphics for completion. A couple examples: ⏲ ⌚  🏁  ☑  ⏰

Hi @DrakeShad - for project-planning to be feasible and practical on a project with such a large number of requests, it’s important to keep each issue focused on a single topic.
This issue is about storing estimated time needed to complete a task.
You are describing time tracking which seems to me to clearly be a different topic.
As such, your comments here won’t ever get seen for planning or action.
Feel free to check whether there are existing requests for time tracking and up-vote them. And if not, to instead start a new request.

@claremacrae Thank you for the heads up! Will do.

Perhaps the true problem here is that it is not easy for users or even contributors to add additional fields to the Tasks plugin.

interesting observation and probably fair.
One of my focuses, since taking over responsibility for Tasks last year, has been to make the searching, sorting and grouping code easier to develop and extend. There has been a lot of progress.
One that work is done, I may well turn to the code for adding fields.

Kudos to @claremacrae for the efforts to enhance the extensibility!
With your expertise, I'm wondering if you could give us a rough estimate of the workload involved in adding this feature. Also, is there anything the community can do to lend a hand in this initiative?
Your dedication and contributions to the project are truly appreciated!

An alternative to this that would interest me would be a tomatoPomodoro field. I don't really want to type in how many minutes I think something will take. I want to think about how many Pomodoros it will take, which is easier to type in as a simple 1 digit integer (maybe 2 for incredibly long tasks).
Perhaps the true problem here is that it is not easy for users or even contributors to add additional fields to the Tasks plugin.

I'm agree with you, something like this?

Hi, thanks for the ideas ... But... 😄
Please keep discussion in this issue focussed on estimated time to complete a task.
Pomodoro seems like a difference concept to me. As such, discussion of it here will just be invisible and lost.
Feel free to see if there is already a pomodoro request elsewhere for Tasks, and if not, start a Feature Request on that.

An alternative to this that would interest me would be a tomatoPomodoro field. I don't really want to type in how many minutes I think something will take. I want to think about how many Pomodoros it will take, which is easier to type in as a simple 1 digit integer (maybe 2 for incredibly long tasks).
Perhaps the true problem here is that it is not easy for users or even contributors to add additional fields to the Tasks plugin.

I'm agree with you, something like this?

Pomodoro is not expected in my very own personal case. Simply because it locks a task to certain time frame. A pomodoro session can be 25 m or 35 m. If I set a task to one pomodoro then it locks to default 25m. But in reality the task might need arbitrary minutes like 10m or 40m. So a proper duration is needed.
I also use pomodoro via superProductivity and what I do is logging how much pomodoro session I have completed in daily logs. In week logs I use a dataviewjs to calculate "pomodoro sessions count x minutes) to quickly grab a view how much time I have invested this week.

Hi @maggaou,
Thanks for the suggestions, but this issue us about 'feat: add estimated time to complete in Task'...
Any comments on any other topic will get lost and never be acted on.
In case it's unclear why, it's time-consuming enough keeping up with all the on-topic requests, yet alone having to manually keep track of unrelated things...

Sorry @claremacrae, I didn’t realize there were active discussions section. My intention was to generate discussion around general task metadata framework. But there are already two related metadata feature requests with some activity so I think it’s unrealistic to ask to close them and make new issue with more general task metadata framework that covers both sub-usecases.

Sorry @claremacrae, I didn’t realize there were active discussions section. My intention was to generate discussion around general task metadata framework. But there are already two related metadata feature requests with some activity so I think it’s unrealistic to ask to close them and make new issue with more general task metadata framework that covers both sub-usecases.

It's up to you...
If you are thinking of something different from the existing requests, a New Feature request in Issues would be fine.

Hello Hello, I think I have something pretty quick and neat. Not sure if the discussion is still open about it though.
Basically two fields should be enough. It's inspired from redmine.
You add fields :

duration (day, hour)
percent (0 - 100% done)

With this two fields, you don't necessarly have to manage time management yourself. This is enough for other people to build some UI, Dataviews and so themselves.
The only thing you could add is adapting supposed end of the task once it is placed in time automatically. So deducting end task date from:
end date = begin date + duration
either way:
begin date = end date - duration
(A bit out of subject but still a bit related, could be using another plugin to synchronize the tasks with external tasks management such as Jira, Redmin, Gitlab, Github, etc..., since basically everything for tasks magenement are already in including time estimation)

Hi @Blondwolf - please read the comment above: https://github.com/obsidian-tasks-group/obsidian-tasks/issues/1649#issuecomment-1735223069
If you would like your suggestion to be considered, please make a new request. Thanks.

This request falls within a set of areas that we have decided not to support in Tasks.

https://github.com/obsidian-tasks-group/obsidian-tasks/issues/2721

Closing as wontfix.


Maybe we should care more about people in pain and not be so selfish 😢

Feature Request

Is your feature request related to a problem? Please describe
A clear and concise description of what the problem is. Ex. I have an issue when [...]
Describe the solution you'd like
A clear and concise description of what you want to happen. Add any considered drawbacks.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Please read the Contribution Guideline before submitting the PR

Pull requests

Approve and thank you

Done

Your being selfish it's not fair I'm poor and you are not! Get over it good bye ... my dogs are dead thank god for my kid paying my taxes I want to be left alone now in piece ...

[all done ]()