Docs
This commit is contained in:
parent
841a494503
commit
46c5432c69
6 changed files with 34 additions and 37 deletions
32
README.md
32
README.md
|
@ -1,13 +1,37 @@
|
||||||
# mc_gallery
|
# mc_gallery
|
||||||
|
|
||||||
## Dart docs explanation
|
## Dart docs explanation
|
||||||
|
The first line of docs are like normal Dart docs. The second line is less of a 'further'
|
||||||
|
explanation, and more of an active commentary for the viewer.
|
||||||
|
|
||||||
## Emulation
|
## Emulation
|
||||||
|
### Main API
|
||||||
|
The unsplash_images_api contains code for fetching data from an external website. Since I have used 'source.unsplash.com', there is no actual daa
|
||||||
|
data (in the form of protected URLs or raw JSON like Facebook API) that is sent back. So this base URL can directly be used to cache the images.<br>
|
||||||
|
|
||||||
|
But I wanted to give a more realistic procedure. So, I manually serialize the same data about the URL to JSON and then deserialize it, just a step
|
||||||
|
further on needlessly. In addition to it, constant fetch delays have added in as well. But in theory, the first serialization can be replaced by actual data-fetch,
|
||||||
|
while the rest works as expected
|
||||||
|
|
||||||
|
### Search API
|
||||||
|
Since websites also have a server-side search call that is available, functionality had been included to make use of that too. But again, this is mocked
|
||||||
|
by the steps mentioned above.
|
||||||
|
|
||||||
## Maintaining scope
|
## Maintaining scope
|
||||||
It's an 'assignment'
|
Since it's just a demo assignment, I have tried to keep the scope of the functionalities small. By that, I mean I have not fully optimized performance-critical sections,
|
||||||
|
or fixed some rare-case bugs. But instead I have left either a 'todo' for them, or mentioned that in the docs themselves
|
||||||
## Model vs. DTO
|
|
||||||
|
|
||||||
## Extra quirks
|
## Extra quirks
|
||||||
Just because I had those assets lying around
|
A lot of the empty directories and unused asset files are left in, as I used my project templated from my other templates. I decided to leave them in, in any case since they
|
||||||
|
may give a better indication about how I code, should you choose to look into them. A lot of the functionality that I used, is something that I have already made for my previous project(s),
|
||||||
|
so it was not as much work as it seems. One of my recent ones, (luckily) literally had a Gallery feature as well, for congregating social media posts into one place. So a lot of assets were reused from there.
|
||||||
|
|
||||||
|
Some of the extra quirks that I added in are:
|
||||||
|
1. Dark mode support.
|
||||||
|
2. Live search -> both for locally (cached) image files, and Web (using a website's search API).
|
||||||
|
3. Clearing image cache on app going to background, and then restarting the program (way easier on an emulator using hot restart)
|
||||||
|
+ I found it easier to directly use the change in app life cycle, than implement a pull-down-refresh
|
||||||
|
4. Logging
|
||||||
|
5. Local storage of favourites state -> on restart, the favourites stay
|
||||||
|
+ Not very useful on a real device as app restart can only be triggered with app life cycle state change, which would clear the download cache,
|
||||||
|
which would be an invalidate them -> so clearing them away with the image cache for now.
|
|
@ -1,7 +1,7 @@
|
||||||
abstract class ConstValues {
|
abstract class ConstValues {
|
||||||
static const String httpsScheme = 'https';
|
static const String httpsScheme = 'https';
|
||||||
static const String backendHost = 'source.unsplash.com';
|
static const String imagesHostServer = 'source.unsplash.com';
|
||||||
static const List<String> backendUrlPathSegments = ['user', 'c_v_r'];
|
static const List<String> imagesHostUrlPathSegments = ['user', 'c_v_r'];
|
||||||
|
|
||||||
static const int numberOfImages = 25;
|
static const int numberOfImages = 25;
|
||||||
static const int minImageSize = 50;
|
static const int minImageSize = 50;
|
||||||
|
|
|
@ -93,8 +93,8 @@ class UnsplashImagesApi implements ImagesApi {
|
||||||
|
|
||||||
Uri _imageUrlGenerator({required int imageSide}) => Uri(
|
Uri _imageUrlGenerator({required int imageSide}) => Uri(
|
||||||
scheme: ConstValues.httpsScheme,
|
scheme: ConstValues.httpsScheme,
|
||||||
host: ConstValues.backendHost,
|
host: ConstValues.imagesHostServer,
|
||||||
pathSegments: [...ConstValues.backendUrlPathSegments, '${imageSide}x$imageSide'],
|
pathSegments: [...ConstValues.imagesHostUrlPathSegments, '${imageSide}x$imageSide'],
|
||||||
);
|
);
|
||||||
|
|
||||||
static UnsplashImagesApi get locate => Locator.locate();
|
static UnsplashImagesApi get locate => Locator.locate();
|
||||||
|
|
|
@ -105,6 +105,8 @@ class ImageCarouselView extends StatelessWidget {
|
||||||
const Gap(24),
|
const Gap(24),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
// Assuming that this data is coming from an external CRM, if it is coming with the
|
||||||
|
// image itself, then add it to the DTO and the Model as well, and access it here.
|
||||||
child: MarkdownBody(data: model.strings.imageDetails),
|
child: MarkdownBody(data: model.strings.imageDetails),
|
||||||
),
|
),
|
||||||
const Gap(16),
|
const Gap(16),
|
||||||
|
|
0
test/api/images_api_test.dart
Normal file
0
test/api/images_api_test.dart
Normal file
|
@ -1,29 +0,0 @@
|
||||||
// This is a basic Flutter widget test.
|
|
||||||
//
|
|
||||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
|
||||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:mc_gallery/app.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
|
||||||
// Build our app and trigger a frame.
|
|
||||||
await tester.pumpWidget(const McgApp());
|
|
||||||
|
|
||||||
// Verify that our counter starts at 0.
|
|
||||||
expect(find.text('0'), findsOneWidget);
|
|
||||||
expect(find.text('1'), findsNothing);
|
|
||||||
|
|
||||||
// Tap the '+' icon and trigger a frame.
|
|
||||||
await tester.tap(find.byIcon(Icons.add));
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
// Verify that our counter has incremented.
|
|
||||||
expect(find.text('0'), findsNothing);
|
|
||||||
expect(find.text('1'), findsOneWidget);
|
|
||||||
});
|
|
||||||
}
|
|
Loading…
Reference in a new issue