Rendering parts of a Wonder with the WonderSection
Dividing the Wonder into a set of sections gives us some flexibility to play around with the layout of the Wonder on the screen. As we saw earlier, these sections can be changed on the CMS with the UI automatically reflecting it. Because these sections are just a type of Content Block, you could even add other kinds of Content Blocks in between, if needed.
The Flutter counterpart of a Wonder Section
Defining the section on the CMS is only half the job. The other half lies in creating a Flutter counterpart that can deserialize the json of the wonder-section and render it using a Flutter Widget. This is managed by a custom ContentBuilder for the WonderSection (a custom ContentItem).
We define this inside a FeatureDescriptor that represents the entire Wonderous feature.
In the Vyuh Framework, a feature.dart represents one logical feature of your application. Dividing your application into a set of composable features allows us to build large scale apps with great benefits.
For our demo app, the entire Wonderous App has been represented as a feature, with the FeatureDescriptor. This descriptor exposes the content items, layouts and other aspects of a feature.
feature.dart
final feature =FeatureDescriptor( name:'wonderous', title:'Wonderous', description:'The Wonderous app as a Vyuh Feature', icon:Icons.castle_outlined, init: () async {// initializes the API keys for Unsplash and loads other environment variables }, routes: routes, // The routes we saw in the earlier article extensions: [ContentExtensionDescriptor(// Content builder for the WonderSection type contentBuilders: [ContentBuilder<WonderSection>( content:WonderSection.typeDescriptor, defaultLayout:WonderSectionLayout(), defaultLayoutDescriptor:WonderSectionLayout.typeDescriptor, ), ], ) ]);
And finally the WonderSection itself is shown below, which represents one visual part of a Wonder. The WonderSectionLayout is the default layout that knows how to render these sections, which you can see in the build() method.
Notice that all of this is completely type-safe and ensures you get the best developer-experience when dealing with CMS content.
Notice how the WonderSection type mirrors the schema in TypeScript with the same fields. As mentioned before, you get a type-safe version that you can reliably use in your Flutter code.
Rendering a single WonderSection
The previous code snippet shows how we render the various parts of the Wonder. Each section fetches the Wonder document from the CMS and renders the parts which are relevant. Instead of every section making parallel calls to fetch the Wonder, we manage all of that inside the WonderSectionBuilder . This makes use of a shared Future<Wonder> to ensure there are no duplicate network calls to fetch the Wonder.
This is shown below. The shared future is inside the WonderClient, mapped to the wonder's identifier. This identifier is extracted from the GoRouterState of the current route.
Once a wonder has been fetched, we delegate to the builder to do rest of the rendering.
The WonderClient fetches the wonders from the Sanity CMS and deserializes to a Dart type: Wonder. It also takes care of fetching photos from the Unsplash collection.
Fetching the wonder from the CMS follows a simple query that looks up the wonder by its identifier. Here is the fetchWonder() method of the WonderClient, in its entirety.