Closed yatendra2001 closed 1 year ago
Thanks @yatendra2001 ! That is very thoughtful and extensive.
I'd like to see a little modification to the proposed naming scheme.
The two items I see as being important
(of course, 1 can be built upon 2 - but they do not need to (should not) evolve in locked steps)
I think in the subdirectoies of each of the projects - it is important to show the very different build, bundle, test, distribution, and CI workflows required
I do think that a pure Dart language level binding is out of the scope of this project (perhaps for Rocket.Chat.Dart.SDK instead) at this time; since Flutter level implementation will have many platform specific nuances that can get into the way of such attempts.
Thanks, @Sing-Li for the feedback.
The naming convention does make a lot of sense. So we can create 2 flutter packages Rocket_Chat_Component and Rocket_Chat_API. Right?
Yesssss, CI and CD are much required in order to build a robust package. Need to define unit tests, integration tests and widget tests according to the package.
I do think that a pure Dart language level binding is out of the scope of this project (perhaps for Rocket.Chat.Dart.SDK instead) at this time; since Flutter level implementation will have many platform-specific nuances that can get into the way of such attempts. ^ We can consider the above package as a dart client that will be used by rocket_chat_component and rocket_chat_api. Otherwise, we have to define the client separately for each package.
Also, I forgot to ask, we might need to build some sample apps as well for users, so should we keep them under this repo or make another under rocket chat?
Let me know if you think it's the correct way to move forward so that I can work on laying out the repo @Sing-Li
The naming convention does make a lot of sense. So we can create 2 flutter packages Rocket_Chat_Component and Rocket_Chat_API. Right?
How about Rocket_Chat_EmbeddedChat_Component and Rocket_Chat_API ?
Yesssss, CI and CD are much required in order to build a robust package. Need to define unit tests, integration tests and widget tests according to the package.
Please show the new proposed directory structure, in the next reply, including:
.github/workflows
directories for associated Github Actions for CI - that leads to a dummy build/deploy of a skeleton artifact
test
and unit-test
directories and dummy test skeleton
changed naming convention as per above
We can consider the above package as a dart client that will be used by rocket_chat_component and rocket_chat_api. Otherwise, we have to define the client separately for each package.
I see what you mean. But I am really not certain that separation can be made at this level (given that there will be many platform specific tweaks that the Flutter layer above will demand).
Take a simple example -- if this layer is NOT created for Flutter only, then it should use Linux network and IO routines directly all the time. But since it is - it will need to use the platform specific networking facility. This case alone will make this layer rather useless as a generic Dart client - unless you rig it with a lot of conditionals during the compilation/build stage.
A pure Dart binding/SDK should allow me to create CLI clients on the minimal Linux distro such as Alpine without any UI/system encumbrances and baggage (exerted by Flutter).
Also, I forgot to ask, we might need to build some sample apps as well for users, so should we keep them under this repo or make another under rocket chat?
Yes - so for Rocket_Chat_EmbeddedChat_Component it should be existing (low complexity) Flutter App that just embed the component. We can have it in a CONTRIB or sample directory within that sub repo
And for Rocket_Chat_API it should be very simple API call and usage examples, many of them covering the entire exposed API individually and in logical groupings. We can have it in a CONTRIB or sample directory within that sub repo.
@yatendra2001 Thanks!
Sure @Sing-Li , Here's the updated layout:
- Rocket_Chat_FlutterSDK
- .gitignore
- README.md
- LICENSE
- .github/
- workflows/
- ci.yml
- packages/
- rocket_chat_embeddedchat_component/
- lib/
- models/
- bloc/
- utils/
- widgets/
- client.dart
- connection_status.dart
- ...
- pubspec.yaml
- sample_app
- test/
- unit_tests/
- ...
- integration_tests/
- ...
- widget_tests/
- ...
- rocket_chat_api/
- lib/
- src/
- api/
- models/
- ...
- extensions/
- utils/
- client.dart
- connection_status.dart
- ...
- pubspec.yaml
- sample_app
- test/
- unit_tests/
- ...
- integration_tests/
- ...
- widget_tests/
- ...
And a sample app might look like this:
- sample_app/
- lib/
- main.dart
- pubspec.yaml
- test/
- unit_tests/
- ...
- integration_tests/
- ...
- widget_tests/
- ...
- android/
- ios/
- windows/
- linux/
- macos/
Here's a brief explanation of the changes made to the layout:
.github/workflows/
: Contains the GitHub Actions workflow files.
ci.yml
: A GitHub Actions workflow file for continuous integration that builds and tests the code.test/
directories are added inside each package (rocket_chat_embeddedchat_component and rocket_chat_api)
unit_tests/
: Contains unit tests for each package.integration_tests/
: Contains integration tests for each package.widget_tests/
: Contains widget tests for each package.import 'package:flutter_test/flutter_test.dart';
import 'package:rocket_chat_api/rocket_chat_api.dart'; // Replace with package import
void main() {
group('Dummy Unit Test', () {
test('Description of the test case', () {
// Arrange: Set up the test variables, mock objects, and/or test inputs
// Act: Perform the action or function you want to test
// Assert: Check if the expected output/result matches the actual output/result
expect(actualResult, expectedResult);
});
});
}
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:rocket_chat_embeddedchat_component/widgets/some_widget.dart'; // Replace with widget import
void main() {
group('Dummy Widget Test', () {
testWidgets('Description of the test case', (WidgetTester tester) async {
// Arrange: Create the widget you want to test
final widget = SomeWidget(); // Replace with widget
// Act: Render the widget in the test environment
await tester.pumpWidget(MaterialApp(home: Scaffold(body: widget)));
// Assert: Check if the widget is present and/or behaves as expected
expect(find.byType(SomeWidget), findsOneWidget); // Replace with assertions
});
});
}
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:example/main.dart'; // Replace with example app import
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group('Dummy Integration Test', () {
testWidgets('Description of the test case', (WidgetTester tester) async {
// Arrange: Set up the test environment by rendering the app
await tester.pumpWidget(MyApp()); // Replace with app widget
// Act: Perform actions or navigation within the app
// Assert: Check if the app behaves as expected
expect(find.text('Some Text'), findsOneWidget); // Replace with assertions
});
});
}
name: Continuous Integration
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build_and_test:
name: Build and Test
runs-on: ubuntu-latest
strategy:
matrix:
flutter: [stable]
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Setup Flutter
uses: subosito/flutter-action@v1
with:
channel: ${{ matrix.flutter }}
- name: Cache dependencies
uses: actions/cache@v2
with:
path: |
packages/rocket_chat_flutter/.dart_tool/package_config.json
packages/rocket_chat_api/.dart_tool/package_config.json
example/.dart_tool/package_config.json
key: ${{ runner.os }}-flutter-${{ matrix.flutter }}-${{ hashFiles('**/pubspec.lock') }}
restore-keys: |
${{ runner.os }}-flutter-${{ matrix.flutter }}-
- name: Get dependencies
run: flutter pub get
working-directory: packages/rocket_chat_api
- name: Get dependencies
run: flutter pub get
working-directory: packages/rocket_chat_embeddedchat_component
- name: Get dependencies
run: flutter pub get
working-directory: example
- name: Run tests
run: flutter test
working-directory: packages/rocket_chat_api
- name: Run tests
run: flutter test
working-directory: packages/rocket_chat_embeddedchat_component
- name: Run tests
run: flutter test
working-directory: example
- name: Analyze code
run: flutter analyze
working-directory: packages/rocket_chat_api
- name: Analyze code
run: flutter analyze
working-directory: packages/rocket_chat_embeddedchat_component
- name: Analyze code
run: flutter analyze
working-directory: example
- name: Build example app
run: flutter build apk
working-directory: example
Note: The layout and continuous integration might evolve over time as we encounter further challenges and solutions.
Thanks!!!
Awesome. Please just make sure that you can successfully CI build to binary - the two main artifacts:
Then I think this is good to go. Looking forward to the first PR! Thanks.
Monorepo Approach
Sample Package Structure
packages/
: contains all the packages for Rocket Chat.rocket_chat_flutter/
: contains the Flutter UI package for Rocket Chat.lib/
: contains the source code for the package.models/
: contains the model classes used in the package.bloc/
: contains the blocs(state management) used in the package.utils/
: contains the utility classes used in the package.widgets/
: contains the UI components used in the package.client.dart
: contains the rocket chat client for Flutter.connection_status.dart
: contains the connection status widget used in the package....
: contains other source files used in the package.pubspec.yaml
: contains the package dependencies and other metadata.rocket_chat_flutter_core/
: contains the core package for Rocket Chat Flutter.lib/
: contains the source code for the package.src/
: contains the source code for the package.api/
: contains the Rocket Chat API classes used in the package.models/
: contains the model classes used in the package....
: contains other source files used in the package.extensions/
: contains the extension methods used in the package.utils/
: contains the utility classes used in the package.client.dart
: contains the Rocket Chat client for Flutter.connection_status.dart
: contains the connection status widget used in the package....
: contains other source files used in the package.pubspec.yaml
: contains the package dependencies and other metadata.example/
: contains the example Flutter application for the Rocket Chat Flutter SDK.lib/
: contains the source code for the example application.pubspec.yaml
: contains the package dependencies and other metadata.This structure is highly inspired by Stream Chat packages as they are currently being used by a lot of people in the flutter community.
I created a demo app, so an example app layout can be found here
I will start working on laying out the repo once you approve @Sing-Li