diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 09c4e1c..f01c799 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3271990C25BBF9C8008EA00E /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 40360520B75D3E668845C254 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 6462689146C9FF38DFEA397D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; @@ -171,6 +172,7 @@ knownRegions = ( en, Base, + "zh-Hans", ); mainGroup = 97C146E51CF9000F007C117D; productRefGroup = 97C146EF1CF9000F007C117D /* Products */; @@ -291,6 +293,7 @@ isa = PBXVariantGroup; children = ( 97C147001CF9000F007C117D /* Base */, + 3271990C25BBF9C8008EA00E /* zh-Hans */, ); name = LaunchScreen.storyboard; sourceTree = ""; @@ -302,6 +305,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -386,6 +390,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -441,6 +446,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 44b75fc..6d4e785 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -12,11 +12,6 @@ $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 - CFBundleLocalizations - - en - zh_CN - CFBundleName fluent_reader_lite CFBundlePackageType diff --git a/ios/Runner/zh-Hans.lproj/LaunchScreen.strings b/ios/Runner/zh-Hans.lproj/LaunchScreen.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/ios/Runner/zh-Hans.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index cfe7a38..5b9a4a6 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -81,5 +81,7 @@ "allLoaded": "All loaded", "removeAd": "Remove Ad", "getApiKey": "Get API ID & Key", - "getApiKeyHint": "In \"Preferences\" > \"Developer\"" + "getApiKeyHint": "In \"Preferences\" > \"Developer\"", + "prev": "Previous", + "next": "Next" } \ No newline at end of file diff --git a/lib/l10n/intl_zh.arb b/lib/l10n/intl_zh.arb index ce7ffa6..bd780ca 100644 --- a/lib/l10n/intl_zh.arb +++ b/lib/l10n/intl_zh.arb @@ -81,5 +81,7 @@ "allLoaded": "已全部加载", "removeAd": "移除广告", "getApiKey": "获取 API ID & KEY", - "getApiKeyHint": "在 “偏好设置” > “开发者” 下" + "getApiKeyHint": "在 “偏好设置” > “开发者” 下", + "prev": "前一项", + "next": "后一项" } \ No newline at end of file diff --git a/lib/models/items_model.dart b/lib/models/items_model.dart index 6a03e01..63ebb09 100644 --- a/lib/models/items_model.dart +++ b/lib/models/items_model.dart @@ -79,6 +79,7 @@ class ItemsModel with ChangeNotifier { final items = await Global.service.fetchItems(); final batch = Global.db.batch(); for (var item in items) { + if (!Global.sourcesModel.has(item.source)) continue; _items[item.id] = item; batch.insert( "items", diff --git a/lib/pages/article_page.dart b/lib/pages/article_page.dart index 34310a0..91af60a 100644 --- a/lib/pages/article_page.dart +++ b/lib/pages/article_page.dart @@ -136,9 +136,24 @@ class ArticlePageState extends State { if (isSourceFeed == null) isSourceFeed = arguments.item2; final resolvedDarkGrey = MyColors.dynamicDarkGrey.resolveFrom(context); final viewOptions = { - 0: Padding(child: Icon(Icons.rss_feed, color: resolvedDarkGrey), padding: EdgeInsets.symmetric(horizontal: 8)), - 1: Icon(Icons.article_outlined, color: resolvedDarkGrey), - 2: Icon(Icons.language, color: resolvedDarkGrey), + 0: Padding( + child: Icon( + Icons.rss_feed, + color: resolvedDarkGrey, + semanticLabel: S.of(context).rssText, + ), + padding: EdgeInsets.symmetric(horizontal: 8), + ), + 1: Icon( + Icons.article_outlined, + color: resolvedDarkGrey, + semanticLabel: S.of(context).loadFull, + ), + 2: Icon( + Icons.language, + color: resolvedDarkGrey, + semanticLabel: S.of(context).loadWebpage, + ), }; return Selector2>( selector: (context, itemsModel, sourcesModel) { @@ -186,29 +201,42 @@ class ArticlePageState extends State { return CupertinoToolbar( items: [ CupertinoToolbarItem( - icon: item.hasRead ? CupertinoIcons.circle : CupertinoIcons.smallcircle_fill_circle, + icon: item.hasRead + ? CupertinoIcons.circle + : CupertinoIcons.smallcircle_fill_circle, + semanticLabel: item.hasRead + ? S.of(context).markUnread + : S.of(context).markRead, onPressed: () { Global.itemsModel.updateItem(item.id, read: !item.hasRead); }, ), CupertinoToolbarItem( - icon: item.starred ? CupertinoIcons.star_fill : CupertinoIcons.star, + icon: item.starred + ? CupertinoIcons.star_fill + : CupertinoIcons.star, + semanticLabel: item.starred + ? S.of(context).star + : S.of(context).unstar, onPressed: () { Global.itemsModel.updateItem(item.id, starred: !item.starred); }, ), CupertinoToolbarItem( icon: CupertinoIcons.share, + semanticLabel: S.of(context).share, onPressed: () { Share.share(item.link); }, ), CupertinoToolbarItem( icon: CupertinoIcons.chevron_up, + semanticLabel: S.of(context).prev, onPressed: idx <= 0 ? null : () { loadNewItem(feed.iids[idx - 1]); }, ), CupertinoToolbarItem( icon: CupertinoIcons.chevron_down, + semanticLabel: S.of(context).next, onPressed: (idx == -1 || (idx == feed.iids.length - 1 && feed.allLoaded)) ? null : () async { diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 54ee025..01feb91 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -97,6 +97,11 @@ class _HomePageState extends State { builder: (context, hasService, child) { if (!hasService) return SetupPage(); return ScreenTypeLayout.builder( + breakpoints: ScreenBreakpoints( + tablet: 640, + watch: 0, + desktop: 1600, + ), mobile: (context) => buildLeft(context), tablet: (context) { final left = buildLeft(context, isMobile: false); diff --git a/lib/pages/item_list_page.dart b/lib/pages/item_list_page.dart index f9fdf42..18cc411 100644 --- a/lib/pages/item_list_page.dart +++ b/lib/pages/item_list_page.dart @@ -306,7 +306,10 @@ class _ItemListPageState extends State { children: [ CupertinoButton( padding: EdgeInsets.zero, - child: Icon(CupertinoIcons.checkmark_circle), + child: Icon( + CupertinoIcons.checkmark_circle, + semanticLabel: S.of(context).markAll, + ), onPressed: _openMarkAllModal, ), Consumer( @@ -316,7 +319,8 @@ class _ItemListPageState extends State { padding: EdgeInsets.zero, child: Icon((feed.filterType != FilterType.All || feed.search.length > 0) ? CupertinoIcons.line_horizontal_3_decrease_circle_fill - : CupertinoIcons.line_horizontal_3_decrease_circle + : CupertinoIcons.line_horizontal_3_decrease_circle, + semanticLabel: S.of(context).filter, ), onPressed: _openFilterModal, ); diff --git a/lib/pages/subscription_list_page.dart b/lib/pages/subscription_list_page.dart index 1bb7591..5856e0f 100644 --- a/lib/pages/subscription_list_page.dart +++ b/lib/pages/subscription_list_page.dart @@ -118,12 +118,18 @@ class _SubscriptionListPageState extends State { children: [ CupertinoButton( padding: EdgeInsets.zero, - child: Icon(CupertinoIcons.checkmark_circle), + child: Icon( + CupertinoIcons.checkmark_circle, + semanticLabel: S.of(context).markAll, + ), onPressed: _openMarkAllModal, ), CupertinoButton( padding: EdgeInsets.zero, - child: Icon(CupertinoIcons.settings), + child: Icon( + CupertinoIcons.settings, + semanticLabel: S.of(context).settings, + ), onPressed: _openSettings, ), ], diff --git a/pubspec.yaml b/pubspec.yaml index 36d4437..3f3baa2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.0+2 +version: 1.0.0+3 environment: sdk: ">=2.7.0 <3.0.0"