diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9c8617e --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2021-2022 niuhuan + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 1762ca1..0fe2a72 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ daisy ===== +[![license](https://img.shields.io/github/license/niuhuan/daisy)](https://raw.githubusercontent.com/niuhuan/daisy/master/LICENSE) +[![releases](https://img.shields.io/github/v/release/niuhuan/daisy)](https://github.com/niuhuan/daisy/releases) +[![downloads](https://img.shields.io/github/downloads/niuhuan/daisy/total)](https://github.com/niuhuan/daisy/releases) 一个简洁大方的漫画与轻小说客户端, 同时支持支持 Android / iOS / MacOS / Windows / Linux. @@ -12,10 +15,11 @@ daisy ## 软件截图 ![](images/st01.png) - ![](images/st02.png) ![](images/st03.jpg) +![](images/st04.jpg) + ## 技术架构 diff --git a/images/st04.jpg b/images/st04.jpg new file mode 100644 index 0000000..1f651db Binary files /dev/null and b/images/st04.jpg differ diff --git a/lib/screens/comic_history_screen.dart b/lib/screens/comic_history_screen.dart index e2d9fc1..b73b2f3 100644 --- a/lib/screens/comic_history_screen.dart +++ b/lib/screens/comic_history_screen.dart @@ -18,7 +18,7 @@ class _ComicHistoryScreenState extends State bool get wantKeepAlive => false; Future> _loadComic(int page) async { - return (await native.loadViewLogs(page: page)) + return (await native.loadComicViewLogs(page: page)) .map((e) => ComicInListCard( id: e.comicId, title: e.comicTitle, diff --git a/lib/screens/comics_screen.dart b/lib/screens/comics_screen.dart index 64a89ec..8410b01 100644 --- a/lib/screens/comics_screen.dart +++ b/lib/screens/comics_screen.dart @@ -95,7 +95,7 @@ class _ComicsScreenState extends State Expanded(child: Container()), Icon(Icons.loop, color: Colors.white70.withAlpha(150)), Text( - "小说", + "切换", style: TextStyle( fontSize: 10, color: Colors.white70.withAlpha(150), diff --git a/lib/screens/components/novel_pager.dart b/lib/screens/components/novel_pager.dart index 467b96d..8a5495f 100644 --- a/lib/screens/components/novel_pager.dart +++ b/lib/screens/components/novel_pager.dart @@ -3,10 +3,23 @@ import 'package:daisy/screens/novel_detail_screen.dart'; import 'package:daisy/screens/components/images.dart'; import 'package:flutter/material.dart'; import 'package:daisy/const.dart'; -import '../../utils.dart'; + +class NovelInPager { + final String cover; + final String name; + final String authors; + final int id; + + NovelInPager({ + required this.cover, + required this.name, + required this.authors, + required this.id, + }); +} class NovelPager extends StatefulWidget { - final Future> Function(int page) loadNovel; + final Future> Function(int page) loadNovel; const NovelPager(this.loadNovel, {Key? key}) : super(key: key); @@ -18,7 +31,7 @@ class _NovelPagerState extends State { // page 从0开始 int _currentPage = 0; - final List _list = []; + final List _list = []; bool _loading = false; bool _over = false; bool _fail = false; @@ -151,7 +164,7 @@ class _NovelPagerState extends State { } class NovelCardInPager extends StatelessWidget { - final NovelInFilter novel; + final NovelInPager novel; const NovelCardInPager({Key? key, required this.novel}) : super(key: key); diff --git a/lib/screens/novels_browser_screen.dart b/lib/screens/novel_browser_screen.dart similarity index 90% rename from lib/screens/novels_browser_screen.dart rename to lib/screens/novel_browser_screen.dart index 4698522..69b0f6e 100644 --- a/lib/screens/novels_browser_screen.dart +++ b/lib/screens/novel_browser_screen.dart @@ -6,14 +6,14 @@ import '../const.dart'; import '../ffi.dart'; import 'components/novel_pager.dart'; -class NovelsBrowserScreen extends StatefulWidget { - const NovelsBrowserScreen({Key? key}) : super(key: key); +class NovelBrowserScreen extends StatefulWidget { + const NovelBrowserScreen({Key? key}) : super(key: key); @override - State createState() => _NovelsBrowserScreenState(); + State createState() => _NovelBrowserScreenState(); } -class _NovelsBrowserScreenState extends State +class _NovelBrowserScreenState extends State with AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive => true; @@ -34,13 +34,16 @@ class _NovelsBrowserScreenState extends State int _process = 0; int _sort = 1; - Future> _loadNovel(int page) async { + Future> _loadNovel(int page) async { return (await native.novelList( category: _selectedNovelCategory?.tagId ?? 0, process: _process, sort: _sort, page: page, - )); + )) + .map((e) => NovelInPager( + cover: e.cover, name: e.name, authors: e.authors, id: e.id)) + .toList(); } Widget _filterBar() { diff --git a/lib/screens/novel_history_screen.dart b/lib/screens/novel_history_screen.dart new file mode 100644 index 0000000..616724d --- /dev/null +++ b/lib/screens/novel_history_screen.dart @@ -0,0 +1,54 @@ +import 'dart:convert'; + +import 'package:daisy/ffi.dart'; +import 'package:flutter/material.dart'; + +import 'components/novel_pager.dart'; + +class NovelHistoryScreen extends StatefulWidget { + const NovelHistoryScreen({Key? key}) : super(key: key); + + @override + State createState() => _NovelHistoryScreenState(); +} + +class _NovelHistoryScreenState extends State + with AutomaticKeepAliveClientMixin { + @override + bool get wantKeepAlive => false; + + Future> _loadNovel(int page) async { + return (await native.loadNovelViewLogs(page: page)) + .map((e) => NovelInPager( + id: e.novelId, + name: e.novelTitle, + cover: e.novelCover, + authors: mapTitle(e.novelAuthors), + )) + .toList(); + } + + String mapTitle(String json) { + try { + List maps = jsonDecode(json); + return maps.cast().map((e) { + try { + String title = e["title"]; + return title; + } catch (e, s) { + print("$e\n$s"); + } + return ""; + }).join("/"); + } catch (e, s) { + print("$e\n$s"); + } + return ""; + } + + @override + Widget build(BuildContext context) { + super.build(context); + return NovelPager(_loadNovel); + } +} diff --git a/lib/screens/novel_search_screen.dart b/lib/screens/novel_search_screen.dart new file mode 100644 index 0000000..bc0d0fc --- /dev/null +++ b/lib/screens/novel_search_screen.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class NovelSearchScreen extends StatefulWidget { + final String initKey; + + const NovelSearchScreen(this.initKey, {Key? key}) : super(key: key); + + @override + State createState() => _NovelSearchScreenState(); +} + +class _NovelSearchScreenState extends State { + @override + Widget build(BuildContext context) { + return const Scaffold(); + } +} diff --git a/lib/screens/novels_history_screen.dart b/lib/screens/novels_history_screen.dart deleted file mode 100644 index 8efa5a0..0000000 --- a/lib/screens/novels_history_screen.dart +++ /dev/null @@ -1,16 +0,0 @@ - -import 'package:flutter/material.dart'; - -class NovelsHistoryScreen extends StatefulWidget{ - const NovelsHistoryScreen({Key? key}) : super(key: key); - - @override - State createState() =>_NovelsHistoryScreenState(); -} - -class _NovelsHistoryScreenState extends State { - @override - Widget build(BuildContext context) { - return const Scaffold(); - } -} \ No newline at end of file diff --git a/lib/screens/novels_screen.dart b/lib/screens/novels_screen.dart index c834f2a..ce48b44 100644 --- a/lib/screens/novels_screen.dart +++ b/lib/screens/novels_screen.dart @@ -1,13 +1,12 @@ import 'package:daisy/screens/about_screen.dart'; -import 'package:daisy/screens/novels_history_screen.dart'; import 'package:daisy/screens/components/badged.dart'; import 'package:flutter/material.dart'; -import 'package:daisy/screens/novels_browser_screen.dart'; +import 'package:daisy/screens/novel_browser_screen.dart'; import 'package:flutter_search_bar/flutter_search_bar.dart'; import 'app_screen.dart'; -import 'comics_screen.dart'; -import 'novels_search_screen.dart'; +import 'novel_history_screen.dart'; +import 'novel_search_screen.dart'; class NovelsScreen extends StatefulWidget { const NovelsScreen({Key? key}) : super(key: key); @@ -94,7 +93,7 @@ class _NovelsScreenState extends State Expanded(child: Container()), Icon(Icons.loop, color: Colors.white70.withAlpha(150)), Text( - "漫画", + "切换", style: TextStyle( fontSize: 10, color: Colors.white70.withAlpha(150), @@ -169,7 +168,7 @@ class _NovelsScreenState extends State Navigator.push( context, MaterialPageRoute( - builder: (context) => NovelsSearchScreen(value), + builder: (context) => NovelSearchScreen(value), ), ); } @@ -192,9 +191,9 @@ class NavPage { const _navPages = [ NavPage( - screen: NovelsHistoryScreen(), + screen: NovelHistoryScreen(), title: "历史", icon: Icons.history, ), - NavPage(screen: NovelsBrowserScreen(), title: "浏览", icon: Icons.blur_linear), + NavPage(screen: NovelBrowserScreen(), title: "浏览", icon: Icons.blur_linear), ]; diff --git a/lib/screens/novels_search_screen.dart b/lib/screens/novels_search_screen.dart deleted file mode 100644 index 7dd3b5b..0000000 --- a/lib/screens/novels_search_screen.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:flutter/material.dart'; - -class NovelsSearchScreen extends StatefulWidget { - final String initKey; - - const NovelsSearchScreen(this.initKey, {Key? key}) : super(key: key); - - @override - State createState() => _NovelsSearchScreenState(); -} - -class _NovelsSearchScreenState extends State { - @override - Widget build(BuildContext context) { - return const Scaffold(); - } -} diff --git a/macos/Runner/bridge_generated.h b/macos/Runner/bridge_generated.h index 8d597a6..03d040e 100644 --- a/macos/Runner/bridge_generated.h +++ b/macos/Runner/bridge_generated.h @@ -67,7 +67,7 @@ void wire_comic_view_page(int64_t port_, int32_t chapter_order, int32_t page_rank); -void wire_load_view_logs(int64_t port_, int64_t page); +void wire_load_comic_view_logs(int64_t port_, int64_t page); void wire_view_log_by_comic_id(int64_t port_, int32_t comic_id); @@ -75,12 +75,30 @@ void wire_news_categories(int64_t port_); void wire_news_list(int64_t port_, int64_t id, int64_t page); +void wire_novel_categories(int64_t port_); + +void wire_novel_list(int64_t port_, int32_t category, int64_t process, int64_t sort, int64_t page); + void wire_novel_detail(int64_t port_, int32_t id); void wire_novel_chapters(int64_t port_, int32_t id); void wire_novel_content(int64_t port_, int32_t volume_id, int32_t chapter_id); +void wire_load_novel_view_logs(int64_t port_, int64_t page); + +void wire_view_log_by_novel_id(int64_t port_, int32_t novel_id); + +void wire_novel_view_page(int64_t port_, + int32_t novel_id, + int32_t volume_id, + struct wire_uint_8_list *volume_title, + int32_t volume_order, + int32_t chapter_id, + struct wire_uint_8_list *chapter_title, + int32_t chapter_order, + int64_t progress); + void wire_auto_clean(int64_t port_, int64_t time); int32_t *new_box_autoadd_i32(int32_t value); @@ -111,13 +129,18 @@ static int64_t dummy_method_to_enforce_bundling(void) { dummy_var ^= ((int64_t) (void*) wire_comic_chapter_detail); dummy_var ^= ((int64_t) (void*) wire_comment); dummy_var ^= ((int64_t) (void*) wire_comic_view_page); - dummy_var ^= ((int64_t) (void*) wire_load_view_logs); + dummy_var ^= ((int64_t) (void*) wire_load_comic_view_logs); dummy_var ^= ((int64_t) (void*) wire_view_log_by_comic_id); dummy_var ^= ((int64_t) (void*) wire_news_categories); dummy_var ^= ((int64_t) (void*) wire_news_list); + dummy_var ^= ((int64_t) (void*) wire_novel_categories); + dummy_var ^= ((int64_t) (void*) wire_novel_list); dummy_var ^= ((int64_t) (void*) wire_novel_detail); dummy_var ^= ((int64_t) (void*) wire_novel_chapters); dummy_var ^= ((int64_t) (void*) wire_novel_content); + dummy_var ^= ((int64_t) (void*) wire_load_novel_view_logs); + dummy_var ^= ((int64_t) (void*) wire_view_log_by_novel_id); + dummy_var ^= ((int64_t) (void*) wire_novel_view_page); dummy_var ^= ((int64_t) (void*) wire_auto_clean); dummy_var ^= ((int64_t) (void*) new_box_autoadd_i32); dummy_var ^= ((int64_t) (void*) new_int_32_list);