feat: 首页UI,搜索,我的UI
This commit is contained in:
1 parent
7f329aef44
commit
a2b38fa1e8
22 files changed
+1382
-22
No files matched your search
@@ -0,0 +1,63 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:novyronst/tools/util/sp_tool.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
/// 本地搜索历史(SharedPreferences),key 与 [AppSp] 规则一致(`.search.history`)。
|
||||
class SearchHistoryUtil {
|
||||
SearchHistoryUtil._();
|
||||
|
||||
static const String _storageKey = 'search.history';
|
||||
static const int _maxHistory = 20;
|
||||
|
||||
static Future<List<String>> _readList(SharedPreferences prefs) async {
|
||||
final raw = prefs.getString(_storageKey);
|
||||
if (raw == null || raw.isEmpty) return [];
|
||||
try {
|
||||
final decoded = jsonDecode(raw);
|
||||
if (decoded is! List) return [];
|
||||
return decoded.map((e) => e.toString()).where((s) => s.isNotEmpty).toList();
|
||||
} catch (_) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> _writeList(SharedPreferences prefs, List<String> list) async {
|
||||
await prefs.setString(_storageKey, jsonEncode(list));
|
||||
}
|
||||
|
||||
/// 查询搜索历史列表(新记录在前)。
|
||||
static Future<List<String>> getSearchList() async {
|
||||
final prefs = await SpTool.getInstance();
|
||||
return _readList(prefs);
|
||||
}
|
||||
|
||||
/// 添加一条搜索;去重、去空白,并移到最前。
|
||||
static Future<void> addSearch(String keyword) async {
|
||||
final q = keyword.trim();
|
||||
if (q.isEmpty) return;
|
||||
|
||||
final prefs = await SpTool.getInstance();
|
||||
final list = await _readList(prefs);
|
||||
list.removeWhere((e) => e == q);
|
||||
list.insert(0, q);
|
||||
if (list.length > _maxHistory) {
|
||||
list.removeRange(_maxHistory, list.length);
|
||||
}
|
||||
await _writeList(prefs, list);
|
||||
}
|
||||
|
||||
/// 删除单条搜索记录。
|
||||
static Future<void> deleteSearch(String keyword) async {
|
||||
final prefs = await SpTool.getInstance();
|
||||
final list = await _readList(prefs);
|
||||
list.removeWhere((e) => e == keyword);
|
||||
await _writeList(prefs, list);
|
||||
}
|
||||
|
||||
/// 清空全部搜索历史。
|
||||
static Future<void> clearAllSearch() async {
|
||||
final prefs = await SpTool.getInstance();
|
||||
await prefs.remove(_storageKey);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
|
||||
class SpTool {
|
||||
static SharedPreferences? _instance;
|
||||
static final String _basePrefix = "app.";
|
||||
static Future<SharedPreferences>? _instanceFuture;
|
||||
|
||||
static Future<SharedPreferences> getInstance() {
|
||||
if (_instance != null) {
|
||||
return Future.value(_instance);
|
||||
}
|
||||
|
||||
_instanceFuture ??= SharedPreferences.getInstance().then((prefs) {
|
||||
_instance = prefs;
|
||||
return prefs;
|
||||
});
|
||||
|
||||
return _instanceFuture!;
|
||||
}
|
||||
|
||||
void setString(String key, String value) async {
|
||||
final prefs = await getInstance();
|
||||
prefs.setString("$_basePrefix$key", value);
|
||||
}
|
||||
|
||||
Future<String> getString(String key) async {
|
||||
final prefs = await getInstance();
|
||||
return prefs.getString("$_basePrefix$key") ?? '';
|
||||
}
|
||||
|
||||
void setBool(String key, bool value) async {
|
||||
final prefs = await getInstance();
|
||||
prefs.setBool("$_basePrefix$key", value);
|
||||
}
|
||||
|
||||
Future<bool> getBool(String key) async {
|
||||
final prefs = await getInstance();
|
||||
return prefs.getBool("$_basePrefix$key") ?? false;
|
||||
}
|
||||
|
||||
void setInt(String key, int value) async {
|
||||
final prefs = await getInstance();
|
||||
prefs.setInt("$_basePrefix$key", value);
|
||||
}
|
||||
|
||||
Future<int> getInt(String key) async {
|
||||
final prefs = await getInstance();
|
||||
return prefs.getInt("$_basePrefix$key") ?? 0;
|
||||
}
|
||||
|
||||
void deleteKey(String key) async {
|
||||
final prefs = await getInstance();
|
||||
prefs.remove("$_basePrefix$key");
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,11 @@ class AppBgPage extends StatelessWidget {
|
||||
const AppBgPage({
|
||||
super.key,
|
||||
this.child,
|
||||
|
||||
this.typeBg = 1,
|
||||
});
|
||||
|
||||
final Widget? child;
|
||||
final int typeBg;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -19,7 +20,10 @@ class AppBgPage extends StatelessWidget {
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: HelpImage.asset(ConstImage.pageBg, fit: BoxFit.fill),
|
||||
child: HelpImage.asset(
|
||||
typeBg==1 ? ConstImage.pageBg : ConstImage.mineBg,
|
||||
fit: BoxFit.fill
|
||||
),
|
||||
),
|
||||
child ?? SizedBox()
|
||||
],
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:novyronst/common/help/app_nav.dart';
|
||||
import 'package:novyronst/tools/widgets/novy_com_widget.dart';
|
||||
|
||||
import '../../common/const/const_color.dart';
|
||||
|
||||
|
||||
|
||||
class NovyAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
const NovyAppBar({
|
||||
super.key,
|
||||
this.title,
|
||||
this.titleWidget,
|
||||
this.leading,
|
||||
this.actions,
|
||||
this.onBack,
|
||||
this.showBackButton = true,
|
||||
this.centerTitle = true,
|
||||
this.backgroundColor,
|
||||
this.foregroundColor,
|
||||
this.elevation = 0,
|
||||
this.bottom,
|
||||
this.toolbarHeight = kToolbarHeight,
|
||||
this.titleColor,
|
||||
});
|
||||
|
||||
final String? title;
|
||||
final Color? titleColor;
|
||||
final Widget? titleWidget;
|
||||
final Widget? leading;
|
||||
final List<Widget>? actions;
|
||||
final VoidCallback? onBack;
|
||||
final bool showBackButton;
|
||||
final bool centerTitle;
|
||||
final Color? backgroundColor;
|
||||
final Color? foregroundColor;
|
||||
final double elevation;
|
||||
final PreferredSizeWidget? bottom;
|
||||
final double toolbarHeight;
|
||||
|
||||
@override
|
||||
Size get preferredSize =>
|
||||
Size.fromHeight(toolbarHeight + (bottom?.preferredSize.height ?? 0));
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return _buildNormalAppBar(context);
|
||||
}
|
||||
|
||||
PreferredSizeWidget _buildNormalAppBar(BuildContext context) {
|
||||
|
||||
final canPop = Navigator.of(context).canPop();
|
||||
|
||||
Widget? resolvedLeading = leading;
|
||||
if (resolvedLeading == null && showBackButton && canPop) {
|
||||
resolvedLeading = IconButton(
|
||||
icon: Icon(Icons.arrow_back_ios, size: 18, color: Colors.white),
|
||||
onPressed: onBack ?? () => AppNav.back(),
|
||||
);
|
||||
}
|
||||
|
||||
return AppBar(
|
||||
title: titleWidget ?? (title != null
|
||||
? NovyText(title!, fontSize: 18, fontWeight: FontWeight.bold, color: titleColor)
|
||||
: null),
|
||||
leading: resolvedLeading,
|
||||
actions: actions,
|
||||
centerTitle: centerTitle,
|
||||
backgroundColor: backgroundColor ?? ConstColor.withValue('#110D08'),
|
||||
foregroundColor: foregroundColor,
|
||||
elevation: elevation,
|
||||
scrolledUnderElevation: 0,
|
||||
toolbarHeight: toolbarHeight,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user