feat: add initial dashbot package implementation

- Created a new Dashbot package with core functionalities.
- Implemented Dashbot window model and notifier for state management.
- Added UI components including Dashbot default page and home page.
- Integrated routing for Dashbot with initial routes defined.
- Included assets for Dashbot icons and set up pubspec.yaml.
- Added tests for Dashbot window notifier to ensure functionality.
- Established a basic README and CHANGELOG for the package.
This commit is contained in:
Udhay-Adithya
2025-08-31 12:15:43 +05:30
parent a3669b1685
commit b9cc42b019
25 changed files with 802 additions and 8 deletions

View File

@@ -0,0 +1,40 @@
import 'package:apidash_design_system/apidash_design_system.dart'
show kVSpacer20, kVSpacer16, kVSpacer10;
import 'package:dashbot/core/utils/dashbot_icons.dart';
import 'package:flutter/material.dart';
class DashbotDefaultPage extends StatelessWidget {
const DashbotDefaultPage({super.key});
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
kVSpacer16,
DashbotIcons.getDashbotIcon1(width: 60),
kVSpacer20,
Text(
'Hello there!',
style: TextStyle(fontSize: 22, fontWeight: FontWeight.w800),
),
kVSpacer10,
Text(
'Request not made yet',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
Text(
"Why not go ahead and make one?",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w200),
),
],
);
}
}

View File

@@ -0,0 +1,31 @@
class DashbotWindowModel {
final double width;
final double height;
final double right;
final double bottom;
final bool isActive;
const DashbotWindowModel({
this.width = 350,
this.height = 450,
this.right = 50,
this.bottom = 100,
this.isActive = false,
});
DashbotWindowModel copyWith({
double? width,
double? height,
double? right,
double? bottom,
bool? isActive,
}) {
return DashbotWindowModel(
width: width ?? this.width,
height: height ?? this.height,
right: right ?? this.right,
bottom: bottom ?? this.bottom,
isActive: isActive ?? this.isActive,
);
}
}

View File

@@ -0,0 +1,36 @@
import '../model/dashbot_window_model.dart';
import 'package:flutter/material.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'dashbot_window_notifier.g.dart';
@Riverpod(keepAlive: true)
class DashbotWindowNotifier extends _$DashbotWindowNotifier {
@override
DashbotWindowModel build() {
return const DashbotWindowModel();
}
void updatePosition(double dx, double dy, Size screenSize) {
state = state.copyWith(
right: (state.right - dx).clamp(0, screenSize.width - state.width),
bottom: (state.bottom - dy).clamp(0, screenSize.height - state.height),
);
}
void updateSize(double dx, double dy, Size screenSize) {
final newWidth =
(state.width - dx).clamp(300, screenSize.width - state.right);
final newHeight =
(state.height - dy).clamp(350, screenSize.height - state.bottom);
state = state.copyWith(
width: newWidth.toDouble(),
height: newHeight.toDouble(),
);
}
void toggleActive() {
state = state.copyWith(isActive: !state.isActive);
}
}

View File

@@ -0,0 +1,27 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'dashbot_window_notifier.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$dashbotWindowNotifierHash() =>
r'239915bec100bc33e5533291ff10233ea197d556';
/// See also [DashbotWindowNotifier].
@ProviderFor(DashbotWindowNotifier)
final dashbotWindowNotifierProvider =
NotifierProvider<DashbotWindowNotifier, DashbotWindowModel>.internal(
DashbotWindowNotifier.new,
name: r'dashbotWindowNotifierProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
? null
: _$dashbotWindowNotifierHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef _$DashbotWindowNotifier = Notifier<DashbotWindowModel>;
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

View File

@@ -0,0 +1,31 @@
import 'dashbot_routes.dart';
import '../common/pages/dashbot_default_page.dart';
import '../../features/home/view/pages/home_page.dart';
import 'package:flutter/material.dart';
Route<dynamic>? generateRoute(
RouteSettings settings,
) {
switch (settings.name) {
case (DashbotRoutes.dashbotHome):
return MaterialPageRoute(
builder: (context) => DashbotHomePage(),
);
case (DashbotRoutes.dashbotDefault):
return MaterialPageRoute(
builder: (context) => DashbotDefaultPage(),
);
// case (DashbotRoutes.dashbotChat):
// final args = settings.arguments as Map<String, dynamic>?;
// final initialPrompt = args?['initialPrompt'] as String;
// return MaterialPageRoute(
// builder: (context) => ChatScreen(
// initialPrompt: initialPrompt,
// ),
// );
default:
return MaterialPageRoute(
builder: (context) => DashbotDefaultPage(),
);
}
}

View File

@@ -0,0 +1,6 @@
class DashbotRoutes {
static const String dashbotHome = '/dashbothome';
static const String dashbotDefault = '/dashbotdefault';
static const String dashbotChat = '/dashbotchat';
static const String dashbotUnknown = '/dashbotunknown';
}

View File

@@ -0,0 +1,17 @@
import 'package:flutter/widgets.dart';
class DashbotIcons {
DashbotIcons._();
static String get dashbotIcon1 =>
'packages/dashbot/assets/dashbot_icon_1.png';
static String get dashbotIcon2 =>
'packages/dashbot/assets/dashbot_icon_2.png';
static Image getDashbotIcon1({double? width, double? height, BoxFit? fit}) {
return Image.asset(dashbotIcon1, width: width, height: height, fit: fit);
}
static Image getDashbotIcon2({double? width, double? height, BoxFit? fit}) {
return Image.asset(dashbotIcon2, width: width, height: height, fit: fit);
}
}

View File

@@ -0,0 +1,25 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../dashbot_dashboard.dart';
import '../providers/dashbot_window_notifier.dart';
void showDashbotWindow(BuildContext context, WidgetRef ref) {
final isDashbotActive = ref.read(dashbotWindowNotifierProvider).isActive;
final windowNotifier = ref.read(dashbotWindowNotifierProvider.notifier);
if (isDashbotActive) return;
final overlay = Overlay.of(context);
OverlayEntry? entry;
entry = OverlayEntry(
builder:
(context) => DashbotWindow(
onClose: () {
entry?.remove();
windowNotifier.toggleActive();
},
),
);
windowNotifier.toggleActive();
overlay.insert(entry);
}

View File

@@ -0,0 +1,2 @@
export 'show_dashbot.dart';
export 'dashbot_icons.dart';