everything build but untested & migration not finished

This commit is contained in:
Fabian Freund
2024-10-09 13:27:42 +02:00
parent 37d2c84d7f
commit 2c71eeb670
132 changed files with 3790 additions and 2817 deletions
@@ -1,215 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:lensai/data/models/web_page_info.dart';
import 'package:lensai/features/bangs/data/models/bang_data.dart';
import 'package:lensai/features/bangs/domain/providers.dart';
import 'package:lensai/features/bangs/presentation/widgets/site_search.dart';
import 'package:lensai/features/kagi/data/entities/modes.dart';
import 'package:lensai/features/search_browser/utils/url_builder.dart'
as uri_builder;
import 'package:lensai/features/settings/data/models/settings.dart';
import 'package:lensai/features/settings/data/repositories/settings_repository.dart';
import 'package:lensai/features/share_intent/domain/entities/shared_content.dart';
import 'package:lensai/features/web_view/presentation/controllers/switch_new_tab.dart';
import 'package:lensai/presentation/widgets/failure_widget.dart';
import 'package:lensai/presentation/widgets/website_title_tile.dart';
import 'package:lensai/utils/ui_helper.dart' as ui_helper;
import 'package:lensai/utils/uri_parser.dart' as uri_parser;
import 'package:share_plus/share_plus.dart';
class WebPageDialog extends HookConsumerWidget {
final Uri url;
final WebPageInfo? precachedInfo;
final void Function()? onDismiss;
const WebPageDialog({
required this.url,
this.precachedInfo,
this.onDismiss,
super.key,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final incognitoEnabled = ref.watch(
settingsRepositoryProvider.select(
(value) => (value.valueOrNull ?? Settings.withDefaults()).incognitoMode,
),
);
final availableBangsAsync = ref.watch(
bangDataListProvider(
filter: (
domain: url.host,
groups: null,
categoryFilter: null,
orderMostFrequentFirst: true,
),
),
);
final availableBangCount = availableBangsAsync.valueOrNull?.length;
final formKey = useMemoized(() => GlobalKey<FormState>());
final urlTextController = useTextEditingController(text: url.toString());
return Stack(
children: [
ModalBarrier(
color: Theme.of(context).dialogTheme.barrierColor ?? Colors.black54,
onDismiss: onDismiss,
),
SimpleDialog(
titlePadding: const EdgeInsets.fromLTRB(16.0, 12.0, 16.0, 0.0),
contentPadding: EdgeInsets.zero,
insetPadding: const EdgeInsets.symmetric(
horizontal: 20.0,
vertical: 24.0,
),
title: WebsiteTitleTile(url, precachedInfo: precachedInfo),
children: [
SizedBox(
//We need this to stretch the dialog, then padding from dialog is applied
width: double.maxFinite,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Form(
key: formKey,
child: TextFormField(
controller: urlTextController,
enableIMEPersonalizedLearning: !incognitoEnabled,
decoration: InputDecoration(
labelText: 'URL',
suffixIcon: (webViewController != null)
? IconButton(
onPressed: () async {
if (formKey.currentState?.validate() ?? false) {
await webViewController!.loadUrl(
urlRequest: URLRequest(
url: WebUri.uri(
uri_parser.tryParseUrl(
urlTextController.text,
eagerParsing: true,
)!,
),
),
);
onDismiss?.call();
}
},
icon: const Icon(Icons.send),
)
: null,
),
validator: (value) {
if (uri_parser.tryParseUrl(value, eagerParsing: true) !=
null) {
return null;
}
return 'Invalid URL';
},
),
),
),
),
const Divider(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: availableBangsAsync.when(
data: (availableBangs) {
if (availableBangs.isEmpty) {
return const SizedBox.shrink();
}
return SiteSearch(
domain: url.host,
availableBangs: availableBangs,
);
},
error: (error, stackTrace) => FailureWidget(
title: 'Could not load bangs',
exception: error,
),
loading: () => SiteSearch(
domain: url.host,
availableBangs: [
BangData(
websiteName: 'websiteName',
domain: 'domain',
trigger: 'trigger',
urlTemplate: 'urlTemplate',
),
],
),
),
),
if (availableBangsAsync.isLoading ||
availableBangCount == null ||
availableBangCount > 0)
const Divider(),
ListTile(
leading: const Icon(MdiIcons.contentCopy),
title: const Text('Copy address'),
onTap: () async {
await Clipboard.setData(
ClipboardData(text: url.toString()),
);
onDismiss?.call();
},
),
ListTile(
onTap: () async {
await ui_helper.launchUrlFeedback(context, url);
},
leading: const Icon(Icons.open_in_browser),
title: const Text('Launch External'),
),
ListTile(
leading: const Icon(MdiIcons.tabPlus),
title: const Text('Open in new tab'),
onTap: () async {
await ref
.read(switchNewTabControllerProvider.notifier)
.add(url);
onDismiss?.call();
},
),
ListTile(
leading: const Icon(Icons.share),
title: const Text('Share link'),
onTap: () async {
await Share.shareUri(url);
onDismiss?.call();
},
),
const Divider(),
ListTile(
leading: Icon(KagiTool.summarizer.icon),
title: const Text('Summarize'),
onTap: () async {
final summarizerUrl = uri_builder.summarizerUri(
document: SharedUrl(url),
mode: SummarizerMode.keyMoments,
);
await ref
.read(switchNewTabControllerProvider.notifier)
.add(summarizerUrl);
onDismiss?.call();
},
),
],
),
],
);
}
}
File diff suppressed because it is too large Load Diff
@@ -1,107 +0,0 @@
import 'package:flutter/material.dart';
import 'package:lensai/features/web_view/domain/entities/abstract/tab.dart';
import 'package:lensai/features/search_browser/presentation/widgets/favicon.dart';
class WebViewTab extends StatelessWidget {
final ITab tab;
final bool isActive;
final VoidCallback? onTap;
final VoidCallback? onLongPress;
final VoidCallback? onDelete;
const WebViewTab({
required this.tab,
required this.isActive,
this.onTap,
this.onLongPress,
this.onDelete,
super.key,
});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Container(
decoration: BoxDecoration(
border: Border.all(
color: isActive ? colorScheme.primary : colorScheme.outline,
width: isActive ? 2.0 : 1.0,
),
borderRadius: const BorderRadius.all(Radius.circular(16.0)),
),
child: Material(
color: colorScheme.surfaceContainerHighest,
borderRadius: const BorderRadius.all(Radius.circular(16.0)),
child: InkWell(
borderRadius: const BorderRadius.all(Radius.circular(16.0)),
onTap: onTap,
onLongPress: onLongPress,
child: Column(
children: [
Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 6.0),
child: Text(
overflow: TextOverflow.ellipsis,
tab.title ?? 'New Tab',
maxLines: 2,
),
),
),
IconButton(
visualDensity:
const VisualDensity(horizontal: -4.0, vertical: -4.0),
onPressed: onDelete,
icon: const Icon(Icons.close),
),
],
),
Row(
children: [
const SizedBox(
width: 6.0,
),
FaviconImage(
url: tab.url,
favicon: tab.favicon,
),
const SizedBox(
width: 6.0,
),
Expanded(
child: Text(
tab.url.authority,
style: Theme.of(context).textTheme.bodySmall,
),
),
],
),
const SizedBox(
height: 6,
),
if (tab.screenshot != null)
Expanded(
child: ClipRRect(
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(16.0),
bottomRight: Radius.circular(16.0),
),
child: SizedBox(
width: double.infinity,
child: Image.memory(
fit: BoxFit.fitWidth,
tab.screenshot!,
),
),
),
),
],
),
),
),
);
}
}