some code about history

This commit is contained in:
DASHU
2024-09-18 07:39:50 +08:00
parent 2c7629ab3f
commit 73e8182d7b
14 changed files with 537 additions and 55 deletions

View File

@@ -5,20 +5,20 @@ import 'package:nowser/const/app_type.dart';
import 'package:nowser/const/base.dart'; import 'package:nowser/const/base.dart';
import 'package:nowser/data/app.dart'; import 'package:nowser/data/app.dart';
import '../app/app_type_component.dart'; import 'app_type_component.dart';
class AuthAppInfoComponent extends StatefulWidget { class SimpleAppInfoComponent extends StatefulWidget {
App app; App app;
AuthAppInfoComponent({required this.app}); SimpleAppInfoComponent({required this.app});
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() {
return _AuthAppInfoComponent(); return _SimpleAppInfoComponent();
} }
} }
class _AuthAppInfoComponent extends State<AuthAppInfoComponent> { class _SimpleAppInfoComponent extends State<SimpleAppInfoComponent> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var themeData = Theme.of(context); var themeData = Theme.of(context);

View File

@@ -7,8 +7,8 @@ import 'package:nowser/provider/key_provider.dart';
import 'package:nowser/util/router_util.dart'; import 'package:nowser/util/router_util.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../app/simple_app_info_component.dart';
import '../logo_component.dart'; import '../logo_component.dart';
import 'auth_app_info_component.dart';
class AuthDialogBaseComponnet extends StatefulWidget { class AuthDialogBaseComponnet extends StatefulWidget {
App app; App app;
@@ -122,7 +122,7 @@ class _AuthDialog extends State<AuthDialogBaseComponnet> {
list.add(Container( list.add(Container(
margin: baseMargin, margin: baseMargin,
child: AuthAppInfoComponent( child: SimpleAppInfoComponent(
app: widget.app, app: widget.app,
), ),
)); ));

View File

@@ -0,0 +1,123 @@
import 'package:flutter/material.dart';
import 'package:nowser/component/image_component.dart';
import 'package:nowser/const/base.dart';
class UrlListItemComponnet extends StatefulWidget {
String? image;
String title;
String url;
int? dateTime;
UrlListItemComponnet({
this.image,
required this.title,
required this.url,
this.dateTime,
});
@override
State<StatefulWidget> createState() {
return _UrlListItemComponnet();
}
}
class _UrlListItemComponnet extends State<UrlListItemComponnet> {
@override
Widget build(BuildContext context) {
var themeData = Theme.of(context);
var smallFontSize = themeData.textTheme.bodySmall!.fontSize;
Widget iconWidget = Icon(
Icons.image,
weight: 60,
);
if (widget.image != null) {
iconWidget = ImageComponent(
imageUrl: widget.image!,
width: 36,
height: 36,
fit: BoxFit.cover,
);
}
String host = widget.url;
try {
var uri = Uri.parse(widget.url);
host = uri.host;
} catch (e) {}
String time = "";
if (widget.dateTime != null) {
var dt = DateTime.fromMillisecondsSinceEpoch(widget.dateTime! * 1000);
time = "${dt.hour}:${dt.minute}";
}
return Container(
padding: EdgeInsets.only(
left: Base.BASE_PADDING,
right: Base.BASE_PADDING,
),
child: Row(
children: [
Container(
width: 60,
height: 60,
alignment: Alignment.center,
child: iconWidget,
),
Expanded(
child: Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1, color: themeData.hintColor.withOpacity(0.5)),
),
),
child: Row(
children: [
Expanded(
child: Container(
margin: EdgeInsets.only(
top: Base.BASE_PADDING_HALF,
bottom: Base.BASE_PADDING_HALF,
),
padding: EdgeInsets.only(right: Base.BASE_PADDING_HALF),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
Text(
host,
style: TextStyle(
fontSize: smallFontSize,
color: themeData.hintColor,
),
),
],
),
),
),
Container(
child: Text(
time,
style: TextStyle(
color: themeData.hintColor,
),
),
),
],
),
),
),
],
),
);
}
}

View File

@@ -74,10 +74,10 @@ class _WebHomeComponent extends State<WebHomeComponent> {
), onTap: () { ), onTap: () {
RouterUtil.router(context, RouterPath.WEB_TABS); RouterUtil.router(context, RouterPath.WEB_TABS);
}), }),
wrapBottomBtn(const Icon(Icons.space_dashboard), onTap: () { // wrapBottomBtn(const Icon(Icons.space_dashboard), onTap: () {
// AuthDialog.show(context); // // AuthDialog.show(context);
// AuthAppConnectDialog.show(context); // // AuthAppConnectDialog.show(context);
}), // }),
wrapBottomBtn(const Icon(Icons.segment), onTap: () { wrapBottomBtn(const Icon(Icons.segment), onTap: () {
// AuthDialog.show(context); // AuthDialog.show(context);
RouterUtil.router(context, RouterPath.ME); RouterUtil.router(context, RouterPath.ME);

View File

@@ -7,4 +7,5 @@ class RouterPath {
static const String APPS = "/apps"; static const String APPS = "/apps";
static const String ADD_REMOTE_APP = "/addRemoteApp"; static const String ADD_REMOTE_APP = "/addRemoteApp";
static const String APP_DETAIL = "/appDetail"; static const String APP_DETAIL = "/appDetail";
static const String HISTORY = "/history";
} }

View File

@@ -14,4 +14,17 @@ class BrowserHistoryDB {
var sql = "select count(1) from browser_history"; var sql = "select count(1) from browser_history";
return Sqflite.firstIntValue(await db.rawQuery(sql)); return Sqflite.firstIntValue(await db.rawQuery(sql));
} }
static Future<List<BrowserHistory>> all({DatabaseExecutor? db}) async {
List<BrowserHistory> objs = [];
List<Object?>? arguments = [];
db = await DB.getDB(db);
var sql = "select * from browser_history order by created_at desc";
List<Map<String, dynamic>> list = await db.rawQuery(sql, arguments);
for (var i = 0; i < list.length; i++) {
var json = list[i];
objs.add(BrowserHistory.fromJson(json));
}
return objs;
}
} }

View File

@@ -16,6 +16,7 @@ import 'package:nowser/provider/web_provider.dart';
import 'package:nowser/router/app_detail/app_detail_router.dart'; import 'package:nowser/router/app_detail/app_detail_router.dart';
import 'package:nowser/router/apps/add_remote_app_router.dart'; import 'package:nowser/router/apps/add_remote_app_router.dart';
import 'package:nowser/router/apps/apps_router.dart'; import 'package:nowser/router/apps/apps_router.dart';
import 'package:nowser/router/history/history_router.dart';
import 'package:nowser/router/index/index_router.dart'; import 'package:nowser/router/index/index_router.dart';
import 'package:nowser/router/keys/keys_router.dart'; import 'package:nowser/router/keys/keys_router.dart';
import 'package:nowser/router/me/me_router.dart'; import 'package:nowser/router/me/me_router.dart';
@@ -102,6 +103,7 @@ class _MyApp extends State<MyApp> {
RouterPath.APPS: (context) => AppsRouter(), RouterPath.APPS: (context) => AppsRouter(),
RouterPath.ADD_REMOTE_APP: (context) => AddRemoteAppRouter(), RouterPath.ADD_REMOTE_APP: (context) => AddRemoteAppRouter(),
RouterPath.APP_DETAIL: (context) => AppDetailRouter(), RouterPath.APP_DETAIL: (context) => AppDetailRouter(),
RouterPath.HISTORY: (context) => HistoryRouter(),
}; };
return MultiProvider( return MultiProvider(
@@ -211,6 +213,7 @@ ThemeData getLightTheme() {
labelColor: Colors.white, labelColor: Colors.white,
unselectedLabelColor: Colors.grey[200], unselectedLabelColor: Colors.grey[200],
), ),
bottomSheetTheme: BottomSheetThemeData(modalBarrierColor: Colors.red),
); );
} }

View File

@@ -1,6 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:nostr_sdk/utils/string_util.dart'; import 'package:nostr_sdk/utils/string_util.dart';
import 'package:nowser/data/bookmark_db.dart'; import 'package:nowser/data/bookmark_db.dart';
import 'package:nowser/util/router_util.dart';
import '../component/webview/web_info.dart'; import '../component/webview/web_info.dart';
import '../data/bookmark.dart'; import '../data/bookmark.dart';
@@ -148,6 +150,55 @@ class WebProvider extends ChangeNotifier {
BookmarkDB.insert(bookmark); BookmarkDB.insert(bookmark);
} }
void back(BuildContext context) {
var webInfo = currentWebInfo();
if (webInfo != null && webInfo.controller != null) {
webInfo.controller!.goBack();
}
}
void forward(BuildContext context) {
var webInfo = currentWebInfo();
if (webInfo != null && webInfo.controller != null) {
webInfo.controller!.goForward();
}
}
void refresh(BuildContext context) {
var webInfo = currentWebInfo();
if (webInfo != null && webInfo.controller != null) {
webInfo.controller!.reload();
}
}
bool currentGoTo(String? url) {
var webInfo = currentWebInfo();
if (webInfo != null) {
return goTo(webInfo, url);
}
return false;
}
bool goTo(WebInfo webInfo, String? url) {
if (url != null && url.startsWith("http")) {
webInfo.url = url;
webInfo.title = null;
if (webInfo.controller != null) {
webInfo.controller!.loadUrl(urlRequest: URLRequest(url: WebUri(url)));
return true;
} else {
webInfo.clone();
updateWebInfo(webInfo);
notifyListeners();
return true;
}
}
return false;
}
} }
class WebNumInfo { class WebNumInfo {

View File

@@ -0,0 +1,103 @@
import 'package:flutter/material.dart';
import 'package:nowser/component/cust_state.dart';
import 'package:nowser/component/url_list_item_componnet.dart';
import 'package:nowser/data/browser_history_db.dart';
import 'package:nowser/util/router_util.dart';
import '../../component/appbar_back_btn_component.dart';
import '../../const/base.dart';
import '../../data/browser_history.dart';
class HistoryRouter extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _HistoryRouter();
}
}
class _HistoryRouter extends CustState<HistoryRouter> {
List<BrowserHistory> historys = [];
@override
Future<void> onReady(BuildContext context) async {
historys = await BrowserHistoryDB.all();
setState(() {});
}
@override
Widget doBuild(BuildContext context) {
var themeData = Theme.of(context);
return Scaffold(
appBar: AppBar(
leading: AppbarBackBtnComponent(),
title: Text(
"Historys",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: themeData.textTheme.bodyLarge!.fontSize,
),
),
actions: [
// GestureDetector(
// onTap: () {},
// child: Container(
// padding: const EdgeInsets.all(Base.BASE_PADDING),
// child: Icon(Icons.delete_sweep_outlined),
// ),
// ),
],
),
body: ListView.builder(
itemBuilder: (context, index) {
if (index >= historys.length) {
return null;
}
Widget? dateWidget;
var history = historys[index];
if (index > 0) {
var preHistory = historys[index - 1];
var preDate = DateTime.fromMillisecondsSinceEpoch(
preHistory.createdAt! * 1000);
var currentDate =
DateTime.fromMillisecondsSinceEpoch(history.createdAt! * 1000);
if (preDate.day != currentDate.day) {
dateWidget = Container(
padding: EdgeInsets.only(
top: Base.BASE_PADDING, left: Base.BASE_PADDING * 2),
alignment: Alignment.centerLeft,
child: Text("${currentDate.month}-${currentDate.day}"),
);
}
}
var main = Container(
child: GestureDetector(
onTap: () {
RouterUtil.back(context, history.url);
},
child: UrlListItemComponnet(
image: history.favicon,
title: history.title ?? "",
url: history.url ?? "",
dateTime: history.createdAt,
),
),
);
if (dateWidget != null) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [dateWidget, main],
);
}
return main;
},
itemCount: historys.length,
),
);
}
}

View File

@@ -12,6 +12,7 @@ import 'package:provider/provider.dart';
import '../../component/webview/web_home_component.dart'; import '../../component/webview/web_home_component.dart';
import '../../component/webview/webview_number_component.dart'; import '../../component/webview/webview_number_component.dart';
import 'web_control_component.dart';
class IndexWebComponent extends StatefulWidget { class IndexWebComponent extends StatefulWidget {
int index; int index;
@@ -97,18 +98,8 @@ class _IndexWebComponent extends State<IndexWebComponent> {
var url = await webInfo.controller!.getUrl(); var url = await webInfo.controller!.getUrl();
var value = await RouterUtil.router(context, var value = await RouterUtil.router(context,
RouterPath.WEB_URL_INPUT, url.toString()); RouterPath.WEB_URL_INPUT, url.toString());
if (value != null && if (value != null && value is String) {
value is String && webProvider.goTo(webInfo, value);
value.startsWith("http")) {
webInfo.url = value;
webInfo.title = null;
if (webInfo.controller != null) {
webInfo.controller!.loadUrl(
urlRequest: URLRequest(
url: WebUri(value),
));
}
} }
}, },
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
@@ -140,7 +131,7 @@ class _IndexWebComponent extends State<IndexWebComponent> {
), ),
), ),
wrapBottomBtn(const Icon(Icons.space_dashboard), wrapBottomBtn(const Icon(Icons.space_dashboard),
left: 8, right: 8), onTap: showControl, left: 8, right: 8),
wrapBottomBtn(const Icon(Icons.segment), left: 8, right: 13, wrapBottomBtn(const Icon(Icons.segment), left: 8, right: 13,
onTap: () { onTap: () {
RouterUtil.router(context, RouterPath.ME); RouterUtil.router(context, RouterPath.ME);
@@ -175,4 +166,14 @@ class _IndexWebComponent extends State<IndexWebComponent> {
), ),
); );
} }
showControl() {
showBottomSheet(
context: context,
showDragHandle: true,
builder: (context) {
return WebControlComponent();
},
);
}
} }

View File

@@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
class WebControlBtnComponent extends StatefulWidget {
String name;
Widget icon;
Function? onTap;
WebControlBtnComponent({
required this.name,
required this.icon,
this.onTap,
});
@override
State<StatefulWidget> createState() {
return _WebControlBtnComponent();
}
}
class _WebControlBtnComponent extends State<WebControlBtnComponent> {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (widget.onTap != null) {
widget.onTap!();
}
},
behavior: HitTestBehavior.translucent,
child: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
widget.icon,
Text(widget.name),
],
),
),
);
}
}

View File

@@ -0,0 +1,126 @@
import 'package:flutter/material.dart';
import 'package:nowser/const/base.dart';
import 'package:nowser/provider/web_provider.dart';
import 'package:nowser/router/index/web_control_btn_component.dart';
import 'package:provider/provider.dart';
class WebControlComponent extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _WebControlComponent();
}
}
class _WebControlComponent extends State<WebControlComponent> {
@override
Widget build(BuildContext context) {
var webProvider = Provider.of<WebProvider>(context);
var webInfo = webProvider.currentWebInfo;
return Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: EdgeInsets.only(
left: Base.BASE_PADDING,
right: Base.BASE_PADDING,
),
child: Row(
children: [
Expanded(
child: WebControlBtnComponent(
name: "Back",
icon: Icon(
Icons.chevron_left,
size: 30,
),
onTap: () {
webProvider.back(context);
},
),
),
Expanded(
child: WebControlBtnComponent(
name: "Forward",
icon: Icon(
Icons.chevron_right,
size: 30,
),
onTap: () {
webProvider.forward(context);
},
),
),
Expanded(
child: WebControlBtnComponent(
name: "Refresh",
icon: Icon(
Icons.refresh,
size: 30,
),
onTap: () {
webProvider.refresh(context);
},
),
),
Expanded(
child: WebControlBtnComponent(
name: "Stealth",
icon: Icon(
Icons.disabled_visible_outlined,
size: 30,
),
),
),
],
),
),
Container(
padding: EdgeInsets.all(Base.BASE_PADDING),
child: Row(
children: [
Expanded(
child: WebControlBtnComponent(
name: "Bookmarks",
icon: Icon(
Icons.bookmark_border,
size: 30,
),
),
),
Expanded(
child: WebControlBtnComponent(
name: "Stars",
icon: Icon(
Icons.bookmark_add_outlined,
size: 30,
),
),
),
Expanded(
child: WebControlBtnComponent(
name: "Historys",
icon: Icon(
Icons.history,
size: 30,
),
),
),
Expanded(
child: WebControlBtnComponent(
name: "Downloads",
icon: Icon(
Icons.download,
size: 30,
),
),
),
],
),
),
],
),
);
}
}

View File

@@ -8,6 +8,7 @@ import 'package:nowser/const/router_path.dart';
import 'package:nowser/data/auth_log_db.dart'; import 'package:nowser/data/auth_log_db.dart';
import 'package:nowser/data/bookmark_db.dart'; import 'package:nowser/data/bookmark_db.dart';
import 'package:nowser/data/browser_history_db.dart'; import 'package:nowser/data/browser_history_db.dart';
import 'package:nowser/main.dart';
import 'package:nowser/provider/app_provider.dart'; import 'package:nowser/provider/app_provider.dart';
import 'package:nowser/provider/key_provider.dart'; import 'package:nowser/provider/key_provider.dart';
import 'package:nowser/router/me/me_router_log_item_component.dart'; import 'package:nowser/router/me/me_router_log_item_component.dart';
@@ -157,6 +158,13 @@ class _MeRouter extends CustState<MeRouter> {
num: historyNum, num: historyNum,
name: "History", name: "History",
iconData: Icons.history, iconData: Icons.history,
onTap: () async {
var url = await RouterUtil.router(context, RouterPath.HISTORY);
print("url $url");
if (webProvider.currentGoTo(url)) {
RouterUtil.back(context);
}
},
)); ));
webItemList.add(MeRouterWebItemComponent( webItemList.add(MeRouterWebItemComponent(
num: downloadNum, num: downloadNum,

View File

@@ -8,10 +8,13 @@ class MeRouterWebItemComponent extends StatefulWidget {
IconData iconData; IconData iconData;
Function? onTap;
MeRouterWebItemComponent({ MeRouterWebItemComponent({
this.num, this.num,
required this.name, required this.name,
required this.iconData, required this.iconData,
this.onTap,
}); });
@override @override
@@ -26,39 +29,46 @@ class _MeRouterWebItemComponent extends State<MeRouterWebItemComponent> {
var themeData = Theme.of(context); var themeData = Theme.of(context);
var cardColor = themeData.cardColor; var cardColor = themeData.cardColor;
return Container( return GestureDetector(
alignment: Alignment.center, onTap: () {
// margin: widget.margin, if (widget.onTap != null) {
widget.onTap!();
}
},
child: Container( child: Container(
width: 80, alignment: Alignment.center,
padding: const EdgeInsets.only( // margin: widget.margin,
left: Base.BASE_PADDING, child: Container(
right: Base.BASE_PADDING, width: 80,
top: Base.BASE_PADDING, padding: const EdgeInsets.only(
bottom: Base.BASE_PADDING, left: Base.BASE_PADDING,
), right: Base.BASE_PADDING,
decoration: BoxDecoration( top: Base.BASE_PADDING,
color: cardColor, bottom: Base.BASE_PADDING,
borderRadius: BorderRadius.circular(Base.BASE_PADDING), ),
), decoration: BoxDecoration(
child: Column( color: cardColor,
mainAxisSize: MainAxisSize.min, borderRadius: BorderRadius.circular(Base.BASE_PADDING),
children: [ ),
Icon(widget.iconData), child: Column(
Text( mainAxisSize: MainAxisSize.min,
widget.name, children: [
maxLines: 1, Icon(widget.iconData),
overflow: TextOverflow.ellipsis, Text(
style: TextStyle( widget.name,
fontSize: themeData.textTheme.bodySmall!.fontSize! - 2, maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: themeData.textTheme.bodySmall!.fontSize! - 2,
),
), ),
), Text(
Text( "${widget.num ?? 0}",
"${widget.num ?? 0}", maxLines: 1,
maxLines: 1, overflow: TextOverflow.ellipsis,
overflow: TextOverflow.ellipsis, ),
), ],
], ),
), ),
), ),
); );