Skip to content

Customization widgets

Cyrus Chan edited this page Dec 17, 2023 · 5 revisions

Each shipped theme have two predefined widgets which are card and tile for complete and simplified information respectfully. Mostly, these two widgets should be satsified majority applications for displaying links with rich informations.

However, if want to maximize widget design or even implements dedicated event handlers, OgHref also provides factory constructors or even allows developers to extends widgets based from OgHrefBuilder as well as it's state. This article will briefly explains two provided factory constructors that have different behaviour when handling widget updates and inherit widgets and states to build a new custom widget based on OgHrefBuilder.

Initialization

Import dependency

Unless themed packages have been added into project's dependencies which bundled builder already, it is mandated to add oghref_builder into pubspec.yaml:

dependencies:
  oghref_builder: ^3.0.0 # PLease copy version constraint from pub.dev

Initializer callback

Unlike the themed packages, builder package does not defines initializer for binding property parser into MetaFetch. Therefore, at least one parsers must be registered into MetaFetch under the main() method to ensure recognizable on various protocols:

void main() {
    MetaFetch().register(const OpenGraphPropertyParser());

    runApp(const App());
}

Using factory constructors

There are two factory constructors offers in OgHrefBuilder which named updatable and runOnce with identical parameters with default constructors.

updatable factory

OgHrefBuilder.updatable is one of the factory constructors that the widget will be rebuilt if the given URL has been changed where made from parent widget. This factory is sutable for update context dynamically (for example, editing).

runOnce factory

On the other hands, OgHrefBuilder.runOnce only build when this widgets is createad initially and no context update can be made afterward. This behaviours is more suitable for viewing context that update should be made on demand.

Extends widgets and states

The mentioned factory constructors only implements widget building and event handling under three widget builders from factorys' parameters. If decided to wrap with parent widgets or even process callbacks outside of the builder, it is preferred to extends widgets and states that to maximize ability of customizations on deploying UI or even change behaviour when updating URL.

Here is the basic code for replicate OgHrefBuilder.updatable with border defined:

// For calling methods inside the state
final GlobalKey<_CustomUpdatableOgHrefBuilderState> customUpdatableOgHrefKey = GlobalKey();

class CustomUpdatableOgHrefBuilder extends OgHrefBuilder {
    CustomUpdatableOgHrefBuilder(super.url,
      {required super.onRetrived,
      required super.onFetchFailed,
      super.onLoading,
      super.onOpenLinkFailed,
      super.openLinkConfirmation,
      super.multiInfoHandler,
      super.key});

    @override
    _CustomUpdatableOgHrefBuilderState createState() => _CustomUpdatableOgHrefBuilderState();
}

class _CustomUpdatableOgHrefBuilderState extends OgHrefBuilderState<CustomUpdatableOgHrefBuilder> {
    @override
    late Future<MetaInfo> metaInfo;

    @override
    void initState() {
        super.initState();
        _bindMemorizer();
    }

    @override
    void didUpdateWidget(covariant _UpdatableOgHrefBuilder oldWidget) {
        super.didUpdateWidget(oldWidget);
        if (oldWidget.url != widget.url) {
        _bindMemorizer();
        }
    }

    void _bindMemorizer() {
        metaInfo = constructInfo();
    }

    @override
    Widget build(BuildContext context) {
        // This method annotated with `mustCallSuper` metadata

        return Container(
            width: 300,
            height: 200,
            decoration: const BoxDecoration(
                border: Border.add(width: 1.5, color: Colors.black)
            ),
            child: super.build(context)
        );
    }
}

// Using StatefulWidget is preferred for better implementations in complex callbacks
class CustomOgHrefBuilderWrapper extends StatelessWidget {
    const CustomOgHrefBuilderWrapper({super.key});

    @override
    Widget build(BuildContext context) {
        return CustomUpdatableOgHrefBuilder(
            Uri.parse("https://example.com"),
            key: customUpdatableOgHrefKey
        );
    }
}

From given example, metaInfo is the only one properties and methods marked as abstract that it must be overridden and required to assign and update new Future to retrieve metadata from website URL. Ideally, metaInfo should be come from comstructInfo() which is responsible for create Future of getting metadata and invoke outside the state is forbidden.

Originally, the widgets which building context of metadata information has been implemented in build(BuildContext) already that it must be wrap as child widget for wrapping result of link widgets. The purpose of allowing overriding build widget is standardized a finite value of widget size such that resolving fail assertion due to unmeasured sizes for specific widgets when building context of fetched data. Therefore, it is ideally retain code of build for majority scenario.