diff --git a/assets/flutter.db b/assets/flutter.db index 42a8730..e8fc819 100644 Binary files a/assets/flutter.db and b/assets/flutter.db differ diff --git a/assets/version.json b/assets/version.json new file mode 100644 index 0000000..79dcc07 --- /dev/null +++ b/assets/version.json @@ -0,0 +1,3 @@ +{ + "dbVersion": 2 +} \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index eaa2835..e0f7b2a 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -9,13 +9,13 @@ PODS: - path_provider (0.0.1): - Flutter - Reachability (3.2) - - share (0.5.2): + - share (0.0.1): - Flutter - shared_preferences (0.0.1): - Flutter - - sqflite (0.0.1): + - sqflite (0.0.2): - Flutter - - FMDB (~> 2.7.2) + - FMDB (>= 2.7.5) - url_launcher (0.0.1): - Flutter @@ -55,11 +55,11 @@ SPEC CHECKSUMS: FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 - share: bae0a282aab4483288913fc4dc0b935d4b491f2e - shared_preferences: 430726339841afefe5142b9c1f50cb6bd7793e01 - sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0 - url_launcher: a1c0cc845906122c4784c542523d8cacbded5626 + share: 0b2c3e82132f5888bccca3351c504d0003b3b410 + shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d + sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 + url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c -COCOAPODS: 1.10.0 +COCOAPODS: 1.10.1 diff --git a/lib/app/res/str_unit.dart b/lib/app/res/str_unit.dart index b03b11a..e15c25d 100644 --- a/lib/app/res/str_unit.dart +++ b/lib/app/res/str_unit.dart @@ -5,7 +5,7 @@ class StrUnit { // 小文字大小 - static const String version = 'V1.5.0'; + static const String version = 'V1.5.1'; static const String appName = 'Flutter Unit'; static const String galleryInfo = """ diff --git a/lib/blocs/global/global_bloc.dart b/lib/blocs/global/global_bloc.dart index 13953ba..48ca757 100644 --- a/lib/blocs/global/global_bloc.dart +++ b/lib/blocs/global/global_bloc.dart @@ -1,7 +1,8 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_unit/app/res/cons.dart'; import 'package:flutter_unit/app/res/sp.dart'; -import 'package:flutter_unit/repositories/app_storage.dart'; +import 'package:flutter_unit/repositories/app_start.dart'; +import 'package:flutter_unit/repositories/local_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'global_event.dart'; @@ -13,11 +14,11 @@ import 'global_state.dart'; class GlobalBloc extends Bloc { - final AppStorage storage; + final AppStart storage; GlobalBloc(this.storage):super(GlobalState()); - Future get sp => storage.sp; + Future get sp => LocalStorage.sp; @override Stream mapEventToState(GlobalEvent event) async* { @@ -29,8 +30,7 @@ class GlobalBloc extends Bloc { // 切换字体事件处理 : 固化索引 + 产出新状态 if (event is EventSwitchFontFamily) { int familyIndex = Cons.fontFamilySupport.indexOf(event.family); - await sp - ..setInt(SP.fontFamily, familyIndex); + await sp..setInt(SP.fontFamily, familyIndex); yield state.copyWith(fontFamily: event.family); } diff --git a/lib/model/widget_model.dart b/lib/model/widget_model.dart index c3f67c3..406d334 100644 --- a/lib/model/widget_model.dart +++ b/lib/model/widget_model.dart @@ -25,7 +25,7 @@ class WidgetModel extends Equatable { final String name; final String nameCN; final WidgetFamily family; - final bool collected; + final bool deprecated; final WidgetType type; final List links; final double lever; @@ -39,7 +39,7 @@ class WidgetModel extends Equatable { this.name, this.nameCN, this.family, - this.collected, + this.deprecated, this.links, this.type, this.lever, @@ -55,21 +55,23 @@ class WidgetModel extends Equatable { name: po.name, nameCN: po.nameCN, family: Convert.toFamily(po.family), - image: convertImage(po.image), + image: convertImage(po.name), lever: po.lever, - collected: po.collected == 1, + deprecated: po.deprecated == 1, info: po.info, links: formatLinkTo(po.linkWidget), ); } - static convertImage(String image) { - return image.isEmpty ? null : AssetImage(image); + static convertImage(String name) { + // return image.isEmpty ? null : AssetImage(image); + return null; } + @override String toString() { - return 'WidgetModel{id: $id, name: $name,collected: $collected}'; + return 'WidgetModel{id: $id, name: $name, nameCN: $nameCN, family: $family, deprecated: $deprecated, type: $type, links: $links, lever: $lever, image: $image, info: $info}'; } static List formatLinkTo(String links) { @@ -81,6 +83,4 @@ class WidgetModel extends Equatable { } return links.split(',').map((e)=>int.parse(e)).toList(); } - - } diff --git a/lib/repositories/app_start.dart b/lib/repositories/app_start.dart new file mode 100644 index 0000000..6194fea --- /dev/null +++ b/lib/repositories/app_start.dart @@ -0,0 +1,91 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:flutter/services.dart'; +import 'package:flutter_unit/app/res/cons.dart'; +import 'package:flutter_unit/app/res/sp.dart'; +import 'package:flutter_unit/blocs/global/global_state.dart'; +import 'package:flutter_unit/repositories/local_db.dart'; +import 'package:path/path.dart' as path; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:sqflite/sqflite.dart'; + +import 'local_storage.dart'; + +/// create by 张风捷特烈 on 2020-03-04 +/// contact me by email 1981462002@qq.com +/// 说明: 本地存储访问对象,用于读取配置数据,及初始化Database和SharedPreferences + +class AppStart { + // 初始化 App 固化的配置数据 + Future initApp() async { + SharedPreferences prefs = await LocalStorage.sp; + //数据库不存在,执行拷贝 + String databasesPath = await getDatabasesPath(); + String dbPath = path.join(databasesPath, "flutter.db"); + + bool shouldCopy = await _checkShouldCopy(dbPath); + + if (shouldCopy) { + await _doCopyAssetsDb(dbPath); + } else { + print("=====flutter.db 已存在===="); + } + + await LocalDb.instance.initDb(); + + bool showBg = prefs.getBool(SP.showBackground) ?? true; + int themeIndex = prefs.getInt(SP.themeColorIndex) ?? 4; + int fontIndex = prefs.getInt(SP.fontFamily) ?? 1; + int codeIndex = prefs.getInt(SP.codeStyleIndex) ?? 0; + int itemStyleIndex = prefs.getInt(SP.itemStyleIndex) ?? 0; + + return GlobalState( + showBackGround: showBg, + themeColor: Cons.themeColorSupport.keys.toList()[themeIndex], + fontFamily: Cons.fontFamilySupport[fontIndex], + itemStyleIndex: itemStyleIndex, + codeStyleIndex: codeIndex); + } + + Future _checkShouldCopy(String dbPath) async { + bool shouldCopy = false; + String versionStr = await rootBundle.loadString('assets/version.json'); + int dbVersion = await json.decode(versionStr)['dbVersion']; + int versionInSP = + await LocalStorage.getInt(LocalStorage.dbVersionKey) ?? -1; + + // 版本升级,执行拷贝 + if (dbVersion > versionInSP) { + shouldCopy = true; + await LocalStorage.saveInt(LocalStorage.dbVersionKey,dbVersion); + } + + //非 release模式,执行拷贝 + const isPro = bool.fromEnvironment('dart.vm.product'); + if (!isPro) { + shouldCopy = true; + } + + //数据库不存在,执行拷贝 + if (!File(dbPath).existsSync()) { + shouldCopy = true; + } + + return shouldCopy; + } + + Future _doCopyAssetsDb(String dbPath) async { + Directory dir = Directory(path.dirname(dbPath)); + if (!dir.existsSync()) { + await dir.create(recursive: true); + } + ByteData data = await rootBundle.load("assets/flutter.db"); + List bytes = + data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); + await File(dbPath).writeAsBytes(bytes, flush: true); + + print("=====flutter.db==== assets ======拷贝完成===="); + } +} diff --git a/lib/repositories/app_storage.dart b/lib/repositories/app_storage.dart deleted file mode 100644 index ab0eb23..0000000 --- a/lib/repositories/app_storage.dart +++ /dev/null @@ -1,81 +0,0 @@ -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:flutter/services.dart'; -import 'package:flutter_unit/app/res/cons.dart'; -import 'package:flutter_unit/app/res/sp.dart'; -import 'package:flutter_unit/blocs/global/global_state.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:sqflite/sqflite.dart'; -import 'package:path/path.dart' as path; - -/// create by 张风捷特烈 on 2020-03-04 -/// contact me by email 1981462002@qq.com -/// 说明: 本地存储访问对象,用于读取配置数据,及初始化Database和SharedPreferences - -class AppStorage { - SharedPreferences _sp; - Database _database; - - Future get sp async { - _sp = _sp ?? await SharedPreferences.getInstance(); - return _sp; - } - - Future get db async { - _database = _database ?? await initDb(); - return _database; - } - - // 初始化 App 固化的配置数据 - Future initApp() async { - SharedPreferences prefs = await sp; - _database = await initDb(); - - bool showBg = prefs.getBool(SP.showBackground) ?? true; - int themeIndex = prefs.getInt(SP.themeColorIndex) ?? 4; - int fontIndex = prefs.getInt(SP.fontFamily) ?? 1; - int codeIndex = prefs.getInt(SP.codeStyleIndex) ?? 0; - int itemStyleIndex = prefs.getInt(SP.itemStyleIndex) ?? 0; - - return GlobalState( - showBackGround: showBg, - themeColor: Cons.themeColorSupport.keys.toList()[themeIndex], - fontFamily: Cons.fontFamilySupport[fontIndex], - itemStyleIndex: itemStyleIndex, - codeStyleIndex: codeIndex); - } - - // 初始化数据库 - Future initDb() async { - String databasesPath = await getDatabasesPath(); - String dbPath = path.join(databasesPath, "flutter.db"); - bool exists = await databaseExists(dbPath); - const isPro = bool.fromEnvironment('dart.vm.product'); //是否release模式 - - if (!isPro) { - if (!exists) { - await Directory(path.dirname(dbPath)).create(recursive: true); - } - ByteData data = await rootBundle.load(path.join("assets", "flutter.db")); - List bytes = - data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); - await File(dbPath).writeAsBytes(bytes, flush: true); - print("==== debug ===== assets ======拷贝完成===="); - return await openDatabase(dbPath, readOnly: false); - } - - if (!exists) { - await Directory(path.dirname(dbPath)).create(recursive: true); - ByteData data = await rootBundle.load(path.join("assets", "flutter.db")); - List bytes = - data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); - await File(dbPath).writeAsBytes(bytes, flush: true); - print("==== release ===== assets ======拷贝完成===="); - } else { - print("========= 数据库 ======已存在===="); - } - _database = await openDatabase(dbPath, readOnly: false); - return _database; - } -} diff --git a/lib/repositories/bean/widget_po.dart b/lib/repositories/bean/widget_po.dart index 6cddc55..fcb8953 100644 --- a/lib/repositories/bean/widget_po.dart +++ b/lib/repositories/bean/widget_po.dart @@ -9,10 +9,9 @@ class WidgetPo extends Equatable { final int id; final String name; final String nameCN; - final int collected; + final int deprecated; final int family; final double lever; - final String image; final String info; final String linkWidget; @@ -20,11 +19,10 @@ class WidgetPo extends Equatable { {this.id, this.name, this.nameCN, - this.collected, + this.deprecated, this.family, this.lever, this.linkWidget, - this.image, this.info}); factory WidgetPo.fromJson(Map map) { @@ -33,9 +31,8 @@ class WidgetPo extends Equatable { name: map['name'], nameCN: map["nameCN"], family: map["family"], - collected: map["collected"] ?? 0, + deprecated: map["deprecated"] ?? 0, lever: map["lever"].toDouble(), - image: map["image"], linkWidget: map["linkWidget"], info: map["info"]); } @@ -46,9 +43,8 @@ class WidgetPo extends Equatable { "name": this.name, "nameCN": this.nameCN, "family": this.family, - "collected": this.collected, + "deprecated": this.deprecated, "lever": this.lever, - "image": this.image, "linkWidget": this.linkWidget, "info": this.info }; @@ -56,10 +52,10 @@ class WidgetPo extends Equatable { @override String toString() { - return 'WidgetPo{id: $id, name: $name, nameCN: $nameCN, collected: $collected, family: $family, lever: $lever, image: $image, info: $info}'; + return 'WidgetPo{id: $id, name: $name, nameCN: $nameCN, deprecated: $deprecated, family: $family, lever: $lever, info: $info}'; } @override List get props => - [id, name, nameCN, collected, family, lever, image, info]; + [id, name, nameCN, deprecated, family, linkWidget, lever, info]; } diff --git a/lib/repositories/dao/category_dao.dart b/lib/repositories/dao/category_dao.dart index f3274f3..941036b 100644 --- a/lib/repositories/dao/category_dao.dart +++ b/lib/repositories/dao/category_dao.dart @@ -1,7 +1,7 @@ import 'package:sqflite/sqflite.dart'; -import '../app_storage.dart'; +import '../app_start.dart'; import '../bean/category_po.dart'; @@ -19,16 +19,14 @@ import '../bean/category_po.dart'; //"""; class CategoryDao { - final AppStorage storage; + final Database db; - CategoryDao(this.storage); + CategoryDao(this.db); - Future get _db async =>await storage.db; Future insert(CategoryPo category) async { //插入方法 - final db = await _db; String addSql = //插入数据 "INSERT INTO " "category(id,name,color,info,priority,image,created,updated) " @@ -47,7 +45,6 @@ class CategoryDao { Future update(CategoryPo widget) async { //插入方法 - final db = await _db; String updateSql = //插入数据 "UPDATE category SET name=? , color=? ,info=?, priority=?,image=?,updated=? " "WHERE id = ?"; @@ -67,7 +64,6 @@ class CategoryDao { Future addWidget(int categoryId,int widgetId,) async { - final db = await _db; String addSql = //插入数据 "INSERT INTO " "category_widget(widgetId,categoryId) " @@ -79,7 +75,6 @@ class CategoryDao { } Future addWidgets(int categoryId,List widgetIds) async { - final db = await _db; String addSql = //插入数据 "INSERT INTO " "category_widget(widgetId,categoryId) VALUES "; @@ -99,7 +94,6 @@ class CategoryDao { } Future existByName(String name) async { - final db = await _db; String sql = //插入数据 "SELECT COUNT(name) as count FROM category " "WHERE name = ?"; @@ -111,7 +105,6 @@ class CategoryDao { } Future>> queryAll() async { - final db = await _db; List> data = await db.rawQuery( "SELECT c.id,c.name,c.info,c.color,c.image,c.created,c.updated,c.priority,COUNT(cw.categoryId) as `count`" "FROM category AS c " @@ -123,7 +116,6 @@ class CategoryDao { } Future> categoryWidgetIds(int id) async { - final db = await _db; List> data = await db.rawQuery( "SELECT categoryId FROM `category_widget`" "WHERE widgetId = ?", @@ -134,7 +126,6 @@ class CategoryDao { Future deleteCollect(int id) async { - final db = await _db; await db.execute( "DELETE FROM category_widget " "WHERE categoryId = ?", @@ -146,7 +137,6 @@ class CategoryDao { } Future clear() async { - final db = await _db; await db.execute( "DELETE FROM category_widget " "WHERE categoryId >0"); @@ -157,7 +147,6 @@ class CategoryDao { Future removeWidget(int categoryId, int widgetId) async { //插入方法 - final db = await _db; String deleteSql = //插入数据 "DELETE FROM " "category_widget WHERE categoryId = ? AND widgetId = ? "; @@ -169,7 +158,6 @@ class CategoryDao { } Future existWidgetInCollect(int categoryId, int widgetId) async { - final db = await _db; String sql = //插入数据 "SELECT COUNT(id) as count FROM category_widget " "WHERE categoryId = ? AND widgetId = ?"; @@ -199,7 +187,6 @@ class CategoryDao { "WHERE id IN (SELECT widgetId FROM category_widget WHERE categoryId = ?) " "ORDER BY lever DESC"; - final db = await _db; return await db.rawQuery(querySql,[categoryId]); } @@ -209,7 +196,6 @@ class CategoryDao { "WHERE id IN (SELECT widgetId FROM category_widget WHERE categoryId = ?) " "ORDER BY lever DESC"; - final db = await _db; var data = await db.rawQuery(querySql,[categoryId]); return data.map((e) => e["id"]).toList(); } diff --git a/lib/repositories/dao/like_dao.dart b/lib/repositories/dao/like_dao.dart new file mode 100644 index 0000000..605ed48 --- /dev/null +++ b/lib/repositories/dao/like_dao.dart @@ -0,0 +1,64 @@ +import 'package:sqflite/sqflite.dart'; + +class LikeDao { + final Database db; + + LikeDao(this.db); + + Future> likeWidgetIds() async { + var result = await db.rawQuery("SELECT widget_id FROM like_widget"); + var ids = result.map((e) => e['widget_id']).toList(); + return ids; + } + + // 如果已喜欢,取消喜欢 + // 如果未喜欢,设为喜欢 + Future toggleCollect(int widgetId) async { + bool liked = await isLiked(widgetId); + + if (liked) { + await unlike(widgetId, check: false); + } else { + await like(widgetId, check: false); + } + } + + Future like(int widgetId, {bool check = true}) async { + if (check) { + // 如果 like ,直接取消,不执行 like 操作 + bool liked = await isLiked(widgetId); + if (liked) return 0; + } + + return await db.rawInsert( + "INSERT INTO " + "like_widget(widget_id) " + "VALUES (?);", + [widgetId]); + } + + Future unlike(int widgetId, {bool check = true}) async { + if (check) { + // 如果未 like ,直接取消,不执行 unlike 操作 + bool liked = await isLiked(widgetId); + if (!liked) return; + } + await db.execute( + "DELETE FROM like_widget " + "WHERE widget_id = ?", + [widgetId]); + } + + // 判断组件是否已 liked + Future isLiked(int widgetId) async { + var data = await db.rawQuery( + "Select count(id) as `count` FROM like_widget " + "WHERE widget_id = ?", + [widgetId]); + if (data.length > 0) { + var result = data[0]; + return result['count'] as int > 0; + } + return false; + } +} diff --git a/lib/repositories/dao/node_dao.dart b/lib/repositories/dao/node_dao.dart index 3e0ae9e..e295f71 100644 --- a/lib/repositories/dao/node_dao.dart +++ b/lib/repositories/dao/node_dao.dart @@ -1,18 +1,19 @@ import 'package:flutter_unit/repositories/bean/node_po.dart'; +import 'package:sqflite/sqflite.dart'; -import '../app_storage.dart'; +import '../app_start.dart'; class NodeDao { - final AppStorage storage; + final Database db; - NodeDao(this.storage); + + NodeDao(this.db); Future insert(NodePo widget) async { //插入方法 - final db = await storage.db; String addSql = //插入数据 "INSERT INTO " "node(widgetId,name,priority,subtitle,code) " @@ -28,14 +29,12 @@ class NodeDao { Future>> queryAll() async { //插入方法 - final db = await storage.db; return await db.rawQuery("SELECT * " "FROM node"); } //根据 id 查询组件 node Future>> queryById(int id) async { - final db = await storage.db; return await db.rawQuery( "SELECT name,subtitle,code " "FROM node " diff --git a/lib/repositories/dao/widget_dao.dart b/lib/repositories/dao/widget_dao.dart index 02e61e9..11b7767 100644 --- a/lib/repositories/dao/widget_dao.dart +++ b/lib/repositories/dao/widget_dao.dart @@ -1,45 +1,40 @@ import 'package:flutter_unit/model/enums.dart'; +import 'package:sqflite/sqflite.dart'; -import '../app_storage.dart'; +import '../app_start.dart'; import '../bean/widget_po.dart'; class WidgetDao { - final AppStorage storage; + final Database db; - - WidgetDao(this.storage); + WidgetDao(this.db); Future insert(WidgetPo widget) async { //插入方法 - final db = await storage.db; String addSql = //插入数据 "INSERT INTO " - "widget(id,name,nameCN,collected,family,lever,image,linkWidget,info) " - "VALUES (?,?,?,?,?,?,?,?,?);"; + "widget(id,name,nameCN,deprecated,family,lever,linkWidget,info) " + "VALUES (?,?,?,?,?,?,?,?);"; return await db.transaction((tran) async => await tran.rawInsert(addSql, [ widget.id, widget.name, widget.nameCN, - widget.collected, + widget.deprecated, widget.family, widget.lever, - widget.image, widget.linkWidget, widget.info ])); } Future>> queryAll() async { - final db = await storage.db; - return await db.rawQuery("SELECT * " - "FROM widget"); + return await db.rawQuery("SELECT * FROM widget"); } Future>> queryByFamily(WidgetFamily family) async { - final db = await storage.db; return await db.rawQuery( "SELECT * " "FROM widget WHERE family = ? ORDER BY lever DESC", @@ -50,8 +45,6 @@ class WidgetDao { if (ids.length == 0) { return []; } - final db = await storage.db; - String sql = "SELECT * " "FROM widget WHERE id in (${'?,' * (ids.length - 1)}?) "; @@ -59,40 +52,11 @@ class WidgetDao { } Future>> search(SearchArgs arguments) async { - final db = await storage.db; return await db.rawQuery( "SELECT * " "FROM widget WHERE name like ? AND lever IN(?,?,?,?,?) ORDER BY lever DESC", ["%${arguments.name}%", ...arguments.stars]); } - - Future>> toggleCollect(int id) async { - final db = await storage.db; - List> data = await db.rawQuery('SELECT collected FROM widget WHERE id = ?', [id]); - bool collected = data.toList()[0]['collected']==1; - return await db.rawQuery( - "UPDATE widget SET collected = ? " - "WHERE id = ?", - [collected ? 0 : 1, id]); - } - - Future>> queryCollect() async { - final db = await storage.db; - return await db.rawQuery("SELECT * " - "FROM widget WHERE collected = 1 ORDER BY family,lever DESC"); - } - - Future collected(int id) async { - final db = await storage.db; - List> data = await db.rawQuery("SELECT collected " - "FROM widget WHERE id = ?"); - - if(data.length>0){ - return data[0]['collected'] == 1; - } - return false; - } - } class SearchArgs { diff --git a/lib/repositories/local_db.dart b/lib/repositories/local_db.dart new file mode 100644 index 0000000..9434647 --- /dev/null +++ b/lib/repositories/local_db.dart @@ -0,0 +1,50 @@ +import 'package:flutter_unit/repositories/dao/like_dao.dart'; +import 'package:path/path.dart' as path; +import 'package:sqflite/sqflite.dart'; + +import 'dao/category_dao.dart'; +import 'dao/node_dao.dart'; +import 'dao/widget_dao.dart'; + +class LocalDb { + Database _database; + + LocalDb._(); + + static LocalDb instance = LocalDb._(); + + WidgetDao _widgetDao; + CategoryDao _categoryDao; + NodeDao _nodeDao; + LikeDao _likeDao; + + WidgetDao get widgetDao => _widgetDao; + + CategoryDao get categoryDao => _categoryDao; + + NodeDao get nodeDao => _nodeDao; + + LikeDao get likeDao => _likeDao; + + Database get db => _database; + + Future initDb({String name = "flutter.db"}) async { + if (_database != null) return; + String databasesPath = await getDatabasesPath(); + String dbPath = path.join(databasesPath, name); + + _database = await openDatabase(dbPath); + + _widgetDao = WidgetDao(_database); + _categoryDao = CategoryDao(_database); + _nodeDao = NodeDao(_database); + _likeDao = LikeDao(_database); + + print('初始化数据库....'); + } + + Future closeDb() async { + await _database.close(); + _database = null; + } +} diff --git a/lib/repositories/dao/local_storage.dart b/lib/repositories/local_storage.dart similarity index 76% rename from lib/repositories/dao/local_storage.dart rename to lib/repositories/local_storage.dart index 1dc574e..3eb9afe 100644 --- a/lib/repositories/dao/local_storage.dart +++ b/lib/repositories/local_storage.dart @@ -8,6 +8,7 @@ class LocalStorage { static String tokenKey= "token_key"; static String userKey= "user_key"; + static String dbVersionKey= "db_version_key"; static SharedPreferences _sp; @@ -27,6 +28,14 @@ class LocalStorage { return (await sp).get(key); } + static Future saveInt(String key, int value) async { + return (await sp).setInt(key, value); + } + + static Future getInt(String key) async { + return (await sp).getInt(key); + } + static Future remove(String key) async { return (await sp).remove(key); } diff --git a/lib/repositories/rep/category_repository.dart b/lib/repositories/rep/category_repository.dart index 49d3f5a..7cac3d2 100644 --- a/lib/repositories/rep/category_repository.dart +++ b/lib/repositories/rep/category_repository.dart @@ -26,7 +26,6 @@ abstract class CategoryRepository { // 根据 Category 数据 同步 收藏集 Future syncCategoryByData(String data,String likeData); - //添加收藏集 Future addCategory(CategoryPo categoryPo); diff --git a/lib/repositories/rep/impl/catagory_db_repository.dart b/lib/repositories/rep/impl/catagory_db_repository.dart index 934912a..ffb0cce 100644 --- a/lib/repositories/rep/impl/catagory_db_repository.dart +++ b/lib/repositories/rep/impl/catagory_db_repository.dart @@ -6,9 +6,11 @@ import 'package:flutter_unit/model/widget_model.dart'; import 'package:flutter_unit/repositories/bean/category_po.dart'; import 'package:flutter_unit/repositories/bean/widget_po.dart'; import 'package:flutter_unit/repositories/dao/category_dao.dart'; +import 'package:flutter_unit/repositories/local_db.dart'; import 'package:flutter_unit/repositories/rep/category_repository.dart'; +import 'package:sqflite/sqflite.dart'; -import '../../app_storage.dart'; +import '../../app_start.dart'; @@ -19,13 +21,10 @@ import '../../app_storage.dart'; /// 说明: class CategoryDbRepository implements CategoryRepository { - final AppStorage storage; - CategoryDao _categoryDao; + CategoryDao get _categoryDao => LocalDb.instance.categoryDao; - CategoryDbRepository(this.storage) { - _categoryDao = CategoryDao(storage); - } + Database get db => LocalDb.instance.db; @override Future addCategory(CategoryPo categoryPo) async { @@ -102,8 +101,6 @@ class CategoryDbRepository implements CategoryRepository { @override Future> loadLikesData() async { - - final db = await storage.db; var likes = await db.rawQuery("SELECT id " "FROM widget WHERE collected = 1 ORDER BY family,lever DESC"); var likesData = likes.map((e) => e['id']).toList(); @@ -114,7 +111,6 @@ class CategoryDbRepository implements CategoryRepository { Future _setLikes(List ids) async { if(ids.isEmpty) return; - final db = await storage.db; String sql = 'UPDATE widget SET collected = 1 WHERE '; for(int i=0;i LocalDb.instance.widgetDao; + NodeDao get _nodeDao => LocalDb.instance.nodeDao; + LikeDao get _likeDao => LocalDb.instance.likeDao; @override Future> loadWidgets(WidgetFamily family) async { @@ -39,10 +36,10 @@ class WidgetDbRepository implements WidgetRepository { @override Future> loadLikeWidgets() async { - List> data = await _widgetDao.queryCollect(); + List likeIds = await _likeDao.likeWidgetIds(); + List> data = await _widgetDao.queryByIds(likeIds); List widgets = data.map((e) => WidgetPo.fromJson(e)).toList(); - List list = widgets.map(WidgetModel.fromPo).toList(); - return list; + return widgets.map(WidgetModel.fromPo).toList(); } @override @@ -71,12 +68,12 @@ class WidgetDbRepository implements WidgetRepository { Future toggleLike( int id, ) { - return _widgetDao.toggleCollect(id); + return _likeDao.toggleCollect(id); } @override - Future collected(int id) async{ - return await _widgetDao.collected(id); + Future collected(int id) async{ + return await _likeDao.like(id); } } diff --git a/lib/repositories/rep/widget_repository.dart b/lib/repositories/rep/widget_repository.dart index c28dbd8..507195c 100644 --- a/lib/repositories/rep/widget_repository.dart +++ b/lib/repositories/rep/widget_repository.dart @@ -19,5 +19,5 @@ abstract class WidgetRepository { Future> loadLikeWidgets(); - Future collected(int id); + Future collected(int id); } diff --git a/lib/user_system/bloc/authentic/bloc.dart b/lib/user_system/bloc/authentic/bloc.dart index 365b1de..3c9328b 100644 --- a/lib/user_system/bloc/authentic/bloc.dart +++ b/lib/user_system/bloc/authentic/bloc.dart @@ -3,7 +3,7 @@ import 'dart:convert'; import 'package:bloc/bloc.dart'; import 'package:flutter_unit/app/utils/http_utils/http_util.dart'; -import 'package:flutter_unit/repositories/dao/local_storage.dart'; +import 'package:flutter_unit/repositories/local_storage.dart'; import 'package:flutter_unit/user_system/model/user.dart'; import 'package:jwt_decoder/jwt_decoder.dart'; diff --git a/lib/views/components/project/items/widget/coupon_widget_list_item.dart b/lib/views/components/project/items/widget/coupon_widget_list_item.dart index 882a498..b855f63 100644 --- a/lib/views/components/project/items/widget/coupon_widget_list_item.dart +++ b/lib/views/components/project/items/widget/coupon_widget_list_item.dart @@ -119,9 +119,11 @@ class CouponWidgetListItem extends StatelessWidget { Expanded( child: Text(data.name, overflow: TextOverflow.ellipsis, - style: const TextStyle( + style: TextStyle( fontSize: 17, fontWeight: FontWeight.bold, + decoration: (data.deprecated)?TextDecoration.lineThrough:TextDecoration.none, + decorationThickness: 2, shadows: [ Shadow(color: Colors.white, offset: Offset(.3, .3)) ])), diff --git a/lib/views/components/project/items/widget/simple_widget_list_item.dart b/lib/views/components/project/items/widget/simple_widget_list_item.dart index 1a3fb36..96425c6 100644 --- a/lib/views/components/project/items/widget/simple_widget_list_item.dart +++ b/lib/views/components/project/items/widget/simple_widget_list_item.dart @@ -118,9 +118,11 @@ class SimpleWidgetListItem extends StatelessWidget { Expanded( child: Text(data.name, overflow: TextOverflow.ellipsis, - style: const TextStyle( + style: TextStyle( fontSize: 17, fontWeight: FontWeight.bold, + decoration: (data.deprecated)?TextDecoration.lineThrough:TextDecoration.none, + decorationThickness: 2, shadows: [ Shadow(color: Colors.white, offset: Offset(.3, .3)) ])), diff --git a/lib/views/components/project/items/widget/techno_widget_list_item.dart b/lib/views/components/project/items/widget/techno_widget_list_item.dart index 2a41ce9..3bebbf9 100644 --- a/lib/views/components/project/items/widget/techno_widget_list_item.dart +++ b/lib/views/components/project/items/widget/techno_widget_list_item.dart @@ -112,9 +112,11 @@ class TechnoWidgetListItem extends StatelessWidget { Expanded( child: Text(data.name, overflow: TextOverflow.ellipsis, - style: const TextStyle( + style: TextStyle( fontSize: 17, fontWeight: FontWeight.bold, + decoration: (data.deprecated)?TextDecoration.lineThrough:TextDecoration.none, + decorationThickness: 2, shadows: [ Shadow(color: Colors.white, offset: Offset(.3, .3)) ])), diff --git a/lib/views/pages/app/bloc_wrapper.dart b/lib/views/pages/app/bloc_wrapper.dart index d875881..6fae612 100644 --- a/lib/views/pages/app/bloc_wrapper.dart +++ b/lib/views/pages/app/bloc_wrapper.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_unit/repositories/app_storage.dart'; +import 'package:flutter_unit/repositories/app_start.dart'; +import 'package:flutter_unit/repositories/local_db.dart'; import 'package:flutter_unit/repositories/rep/impl/catagory_db_repository.dart'; import 'package:flutter_unit/repositories/rep/impl/widget_db_repository.dart'; import 'package:flutter_unit/repositories/rep/widget_repository.dart'; @@ -16,7 +17,7 @@ import 'package:flutter_unit/blocs/bloc_exp.dart'; /// contact me by email 1981462002@qq.com /// 说明: Bloc提供器包裹层 -final AppStorage storage = AppStorage(); +final AppStart storage = AppStart(); class BlocWrapper extends StatefulWidget { final Widget child; @@ -28,9 +29,9 @@ class BlocWrapper extends StatefulWidget { } class _BlocWrapperState extends State { - final WidgetRepository repository = WidgetDbRepository(storage); + final WidgetRepository repository = WidgetDbRepository(); - final categoryBloc = CategoryBloc(repository: CategoryDbRepository(storage)); + final categoryBloc = CategoryBloc(repository: CategoryDbRepository()); final authBloc = AuthenticBloc()..add(const AppStarted()); @override @@ -79,6 +80,7 @@ class _BlocWrapperState extends State { void dispose() { categoryBloc.close(); authBloc.close(); + LocalDb.instance.closeDb(); super.dispose(); } } diff --git a/lib/views/pages/category/category_page.dart b/lib/views/pages/category/category_page.dart index 32fe945..3f6596e 100644 --- a/lib/views/pages/category/category_page.dart +++ b/lib/views/pages/category/category_page.dart @@ -3,13 +3,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_unit/app/router/unit_router.dart'; import 'package:flutter_unit/blocs/bloc_exp.dart'; +import 'package:flutter_unit/model/category_model.dart'; import 'package:flutter_unit/views/components/permanent/circle.dart'; import 'package:flutter_unit/views/components/project/default/loading_shower.dart'; -import 'package:flutter_unit/views/components/project/no_more_widget.dart'; - -import 'package:flutter_unit/model/category_model.dart'; import 'package:flutter_unit/views/components/project/dialogs/delete_category_dialog.dart'; import 'package:flutter_unit/views/components/project/items/category_list_item.dart'; +import 'package:flutter_unit/views/components/project/no_more_widget.dart'; import 'edit_category_panel.dart'; import 'empty_category.dart'; @@ -26,7 +25,6 @@ class CategoryPage extends StatelessWidget { @override Widget build(BuildContext context) { return BlocBuilder(builder: (ctx, state) { - print(state); if (state is CategoryLoadedState) { return CustomScrollView( slivers: [ @@ -47,18 +45,21 @@ class CategoryPage extends StatelessWidget { _buildContent(BuildContext context, CategoryLoadedState state) { return SliverPadding( - padding: EdgeInsets.only(top:10, left: 10, right: 10, bottom: 0), + padding: const EdgeInsets.only(top: 10, left: 10, right: 10, bottom: 0), sliver: SliverGrid( delegate: SliverChildBuilderDelegate( - (_, index) => Container( - child: GestureDetector( - onTap: () => _toDetailPage(context, state.categories[index]), - child: CategoryListItem( - data: state.categories[index], - onDeleteItemClick: (model) => _deleteCollect(context, model), - onEditItemClick: (model) => _editCollect(context, model), - )), - ), + (_, index) => Container( + child: GestureDetector( + onTap: () => + _toDetailPage(context, state.categories[index]), + child: CategoryListItem( + data: state.categories[index], + onDeleteItemClick: (model) => + _deleteCollect(context, model), + onEditItemClick: (model) => + _editCollect(context, model), + )), + ), childCount: state.categories.length), gridDelegate: gridDelegate), ); diff --git a/lib/views/pages/widget_detail/widget_detail_page.dart b/lib/views/pages/widget_detail/widget_detail_page.dart index 1487118..f84712c 100644 --- a/lib/views/pages/widget_detail/widget_detail_page.dart +++ b/lib/views/pages/widget_detail/widget_detail_page.dart @@ -203,7 +203,9 @@ class _WidgetDetailPageState extends State { elevation: 2, shadowColor: Colors.orange, backgroundColor: Theme.of(context).primaryColor, - labelStyle: const TextStyle(fontSize: 12, color: Colors.white), + labelStyle: TextStyle(fontSize: 12, color: Colors.white, + decoration: (e.deprecated)?TextDecoration.lineThrough:TextDecoration.none, + decorationThickness: 2,), label: Text('${e.name}'), )) .toList(), @@ -245,6 +247,8 @@ class WidgetDetailTitle extends StatelessWidget { model.nameCN, style: TextStyle( fontSize: 20, + decoration: (model.deprecated)?TextDecoration.lineThrough:TextDecoration.none, + decorationThickness: 2, color: Color(0xff1EBBFD), fontWeight: FontWeight.bold), ), diff --git a/pubspec.yaml b/pubspec.yaml index edc29a7..6c355fb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_unit description: A new Flutter application. -version: 1.5.0 +version: 1.5.1 author: 张风捷特烈 <1981462002@qq.com> homepage: https://juejin.cn/user/149189281194766/posts @@ -41,6 +41,7 @@ flutter: - assets/images/head_icon/ - assets/images/widgets/ - assets/flutter.db + - assets/version.json fonts: # 配置字体,可配置多个,支持ttf和otf,ttc等字体资源 - family: IndieFlower #字体名