- Added support for the Grid layout on iPhone, with one or two columns. Works fairly well.
- Bumped up the feed title & date/author font size again.
- Now markes as read on scroll when the card is scrolled halfway off the top.
This commit is contained in:
David Sinclair 2023-03-30 10:36:31 -07:00
parent eb94e7bc7f
commit f703d58b94
7 changed files with 87 additions and 46 deletions

View file

@ -139,6 +139,11 @@ class DetailViewController: BaseViewController {
} }
} }
/// Returns `true` if the device is an iPhone, otherwise `false`.
@objc var isPhone: Bool {
return UIDevice.current.userInterfaceIdiom == .phone
}
/// Returns `true` if the window is in portrait orientation, otherwise `false`. /// Returns `true` if the window is in portrait orientation, otherwise `false`.
@objc var isPortraitOrientation: Bool { @objc var isPortraitOrientation: Bool {
return view.window?.windowScene?.interfaceOrientation.isPortrait ?? false return view.window?.windowScene?.interfaceOrientation.isPortrait ?? false
@ -258,7 +263,7 @@ class DetailViewController: BaseViewController {
/// Moves the story pages controller to a Grid layout cell content (automatically removing it from the previous parent). /// Moves the story pages controller to a Grid layout cell content (automatically removing it from the previous parent).
func prepareStoriesForGridView() { func prepareStoriesForGridView() {
guard let storyPagesViewController else { guard !isPhone, let storyPagesViewController else {
return return
} }
@ -338,7 +343,7 @@ class DetailViewController: BaseViewController {
} }
private func adjustTopConstraint() { private func adjustTopConstraint() {
if UIDevice.current.userInterfaceIdiom != .phone { if !isPhone {
if view.window?.windowScene?.traitCollection.horizontalSizeClass == .compact { if view.window?.windowScene?.traitCollection.horizontalSizeClass == .compact {
topContainerTopConstraint.constant = -50 topContainerTopConstraint.constant = -50
} else { } else {
@ -388,7 +393,7 @@ private extension DetailViewController {
func checkViewControllers() { func checkViewControllers() {
let isTop = layout == .top let isTop = layout == .top
if layout == .left { if layout == .left || isPhone {
if feedDetailViewController != nil { if feedDetailViewController != nil {
remove(viewController: feedDetailViewController) remove(viewController: feedDetailViewController)
@ -459,7 +464,7 @@ private extension DetailViewController {
appDelegate.feedDetailViewController.changedLayout() appDelegate.feedDetailViewController.changedLayout()
if layout != .grid { if layout != .grid || isPhone {
moveStoriesToDetail() moveStoriesToDetail()
} }
} }

View file

@ -261,7 +261,7 @@ struct CardContentView: View {
.padding(.leading, 24) .padding(.leading, 24)
Text(story.feedName) Text(story.feedName)
.font(font(named: "WhitneySSm-Medium", size: 11)) .font(font(named: "WhitneySSm-Medium", size: 12))
.lineLimit(1) .lineLimit(1)
.foregroundColor(feedColor) .foregroundColor(feedColor)
} }
@ -315,7 +315,7 @@ struct CardContentView: View {
Spacer() Spacer()
Text(story.dateAndAuthor) Text(story.dateAndAuthor)
.font(font(named: "WhitneySSm-Medium", size: 11)) .font(font(named: "WhitneySSm-Medium", size: 12))
.foregroundColor(dateAndAuthorColor) .foregroundColor(dateAndAuthorColor)
.padding(.top, 5) .padding(.top, 5)
} }

View file

@ -69,7 +69,7 @@ struct FeedDetailGridView: View {
} }
} }
if cache.isGrid { if cache.isGrid && !cache.isPhone {
EmptyView() EmptyView()
.id(storyViewID) .id(storyViewID)
} else if let story = cache.selected { } else if let story = cache.selected {
@ -134,7 +134,7 @@ struct FeedDetailGridView: View {
.onPreferenceChange(CardKey.self) { .onPreferenceChange(CardKey.self) {
print("pref change for '\(story.title)': \($0)") print("pref change for '\(story.title)': \($0)")
if let value = $0.first, value.frame.minY < 0 { if let value = $0.first, value.frame.minY < -(value.frame.size.height / 2) {
print("pref '\(story.title)': scrolled off the top") print("pref '\(story.title)': scrolled off the top")
feedDetailInteraction.read(story: story) feedDetailInteraction.read(story: story)
@ -153,7 +153,7 @@ struct FeedDetailGridView: View {
@ViewBuilder @ViewBuilder
func makeStoryView(cache: StoryCache) -> some View { func makeStoryView(cache: StoryCache) -> some View {
if cache.isGrid, let story = cache.selected { if cache.isGrid, !cache.isPhone, let story = cache.selected {
StoryView(cache: cache, story: loaded(story: story), interaction: feedDetailInteraction) StoryView(cache: cache, story: loaded(story: story), interaction: feedDetailInteraction)
// .frame(height: storyHeight) // .frame(height: storyHeight)
} }

View file

@ -2390,40 +2390,52 @@ didEndSwipingSwipingWithState:(MCSwipeTableViewCellState)state
}]; }];
} }
if ([[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPhone) { [appDelegate addSplitControlToMenuController:viewController];
[appDelegate addSplitControlToMenuController:viewController];
NSString *preferenceKey = @"story_titles_position";
NSArray *titles;
NSArray *values;
if (appDelegate.detailViewController.isPhone) {
titles = @[@"List", @"Grid"];
values = @[@"titles_on_left", @"titles_in_grid"];
} else {
titles = @[@"Left", @"Top", @"Bottom", @"Grid"];
values = @[@"titles_on_left", @"titles_on_top", @"titles_on_bottom", @"titles_in_grid"];
}
[viewController addSegmentedControlWithTitles:titles values:values preferenceKey:preferenceKey selectionShouldDismiss:YES handler:^(NSUInteger selectedIndex) {
[self.appDelegate.detailViewController updateLayoutWithReload:YES];
}];
if (self.appDelegate.detailViewController.storyTitlesInGrid) {
preferenceKey = @"grid_columns";
NSString *preferenceKey = @"story_titles_position"; if (appDelegate.detailViewController.isPhone) {
NSArray *titles = @[@"Left", @"Top", @"Bottom", @"Grid"]; titles = @[@"Auto Cols", @"1", @"2"];
NSArray *values = @[@"titles_on_left", @"titles_on_top", @"titles_on_bottom", @"titles_in_grid"]; values = @[@"auto", @"1", @"2"];
} else {
titles = @[@"Auto Cols", @"1", @"2", @"3", @"4"];
values = @[@"auto", @"1", @"2", @"3", @"4"];
}
[viewController addSegmentedControlWithTitles:titles values:values preferenceKey:preferenceKey selectionShouldDismiss:YES handler:^(NSUInteger selectedIndex) { [viewController addSegmentedControlWithTitles:titles values:values defaultValue:@"auto" preferenceKey:preferenceKey selectionShouldDismiss:NO handler:^(NSUInteger selectedIndex) {
[self.appDelegate.detailViewController updateLayoutWithReload:YES]; [self.appDelegate.detailViewController updateLayoutWithReload:YES];
}]; }];
if (self.appDelegate.detailViewController.storyTitlesInGrid) { preferenceKey = @"grid_height";
NSString *preferenceKey = @"grid_columns"; titles = @[@"XS", @"Short", @"Medium", @"Tall", @"XL"];
NSArray *titles = @[@"Auto Cols", @"2", @"3", @"4"]; values = @[@"xs", @"short", @"medium", @"tall", @"xl"];
NSArray *values = @[@"auto", @"2", @"3", @"4"];
[viewController addSegmentedControlWithTitles:titles values:values defaultValue:@"medium" preferenceKey:preferenceKey selectionShouldDismiss:NO handler:^(NSUInteger selectedIndex) {
[viewController addSegmentedControlWithTitles:titles values:values defaultValue:@"auto" preferenceKey:preferenceKey selectionShouldDismiss:NO handler:^(NSUInteger selectedIndex) { [self.appDelegate.detailViewController updateLayoutWithReload:YES];
[self.appDelegate.detailViewController updateLayoutWithReload:YES]; }];
}];
preferenceKey = @"grid_height";
titles = @[@"XS", @"Short", @"Medium", @"Tall", @"XL"];
values = @[@"xs", @"short", @"medium", @"tall", @"xl"];
[viewController addSegmentedControlWithTitles:titles values:values defaultValue:@"medium" preferenceKey:preferenceKey selectionShouldDismiss:NO handler:^(NSUInteger selectedIndex) {
[self.appDelegate.detailViewController updateLayoutWithReload:YES];
}];
}
} }
if (!self.appDelegate.detailViewController.storyTitlesInGrid) { if (!self.appDelegate.detailViewController.storyTitlesInGrid) {
NSString *preferenceKey = @"story_list_preview_text_size"; preferenceKey = @"story_list_preview_text_size";
NSArray *titles = @[@"Title", @"content_preview_small.png", @"content_preview_medium.png", @"content_preview_large.png"]; titles = @[@"Title", @"content_preview_small.png", @"content_preview_medium.png", @"content_preview_large.png"];
NSArray *values = @[@"title", @"short", @"medium", @"long"]; values = @[@"title", @"short", @"medium", @"long"];
[viewController addSegmentedControlWithTitles:titles values:values preferenceKey:preferenceKey selectionShouldDismiss:NO handler:^(NSUInteger selectedIndex) { [viewController addSegmentedControlWithTitles:titles values:values preferenceKey:preferenceKey selectionShouldDismiss:NO handler:^(NSUInteger selectedIndex) {
[self.appDelegate resizePreviewSize]; [self.appDelegate resizePreviewSize];
@ -2447,9 +2459,9 @@ didEndSwipingSwipingWithState:(MCSwipeTableViewCellState)state
}]; }];
} }
NSString *preferenceKey = @"feed_list_font_size"; preferenceKey = @"feed_list_font_size";
NSArray *titles = @[@"XS", @"S", @"M", @"L", @"XL"]; titles = @[@"XS", @"S", @"M", @"L", @"XL"];
NSArray *values = @[@"xs", @"small", @"medium", @"large", @"xl"]; values = @[@"xs", @"small", @"medium", @"large", @"xl"];
[viewController addSegmentedControlWithTitles:titles values:values preferenceKey:preferenceKey selectionShouldDismiss:NO handler:^(NSUInteger selectedIndex) { [viewController addSegmentedControlWithTitles:titles values:values preferenceKey:preferenceKey selectionShouldDismiss:NO handler:^(NSUInteger selectedIndex) {
[self.appDelegate resizeFontSize]; [self.appDelegate resizeFontSize];

View file

@ -141,6 +141,10 @@ class StoryCache: ObservableObject {
return appDelegate.detailViewController.layout == .grid return appDelegate.detailViewController.layout == .grid
} }
var isPhone: Bool {
return appDelegate.detailViewController.isPhone
}
@Published var before = [Story]() @Published var before = [Story]()
@Published var selected: Story? @Published var selected: Story?
@Published var after = [Story]() @Published var after = [Story]()
@ -288,13 +292,13 @@ class StorySettings {
// } // }
var gridColumns: Int { var gridColumns: Int {
if NewsBlurAppDelegate.shared.isCompactWidth {
return 1
}
guard let pref = UserDefaults.standard.string(forKey: "grid_columns"), let columns = Int(pref) else { guard let pref = UserDefaults.standard.string(forKey: "grid_columns"), let columns = Int(pref) else {
//TODO: 🚧 could have extra logic to determine the ideal number of columns //TODO: 🚧 could have extra logic to determine the ideal number of columns
return 4 if NewsBlurAppDelegate.shared.isCompactWidth {
return 1
} else {
return 4
}
} }
return columns return columns

View file

@ -287,7 +287,7 @@
} }
- (void)deferredEnableScrolling { - (void)deferredEnableScrolling {
self.webView.scrollView.scrollEnabled = !self.appDelegate.detailViewController.storyTitlesInGrid; self.webView.scrollView.scrollEnabled = self.appDelegate.detailViewController.isPhone || !self.appDelegate.detailViewController.storyTitlesInGrid;
} }
- (void)viewDidDisappear:(BOOL)animated { - (void)viewDidDisappear:(BOOL)animated {
@ -1817,7 +1817,7 @@
[self.activityIndicator stopAnimating]; [self.activityIndicator stopAnimating];
self.webView.scrollView.scrollEnabled = !self.appDelegate.detailViewController.storyTitlesInGrid; self.webView.scrollView.scrollEnabled = self.appDelegate.detailViewController.isPhone || !self.appDelegate.detailViewController.storyTitlesInGrid;
[self loadHTMLString:self.fullStoryHTML]; [self loadHTMLString:self.fullStoryHTML];
self.fullStoryHTML = nil; self.fullStoryHTML = nil;
@ -1837,7 +1837,7 @@
self.webView.hidden = NO; self.webView.hidden = NO;
[self.webView setNeedsDisplay]; [self.webView setNeedsDisplay];
if (self == self.appDelegate.storyPagesViewController.currentPage && self.appDelegate.detailViewController.storyTitlesInGrid) { if (self == self.appDelegate.storyPagesViewController.currentPage && !self.appDelegate.detailViewController.isPhone && self.appDelegate.detailViewController.storyTitlesInGrid) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// [self.appDelegate.feedDetailViewController changedStoryHeight:self.webView.scrollView.contentSize.height]; // [self.appDelegate.feedDetailViewController changedStoryHeight:self.webView.scrollView.contentSize.height];
[self.appDelegate.feedDetailViewController reload]; [self.appDelegate.feedDetailViewController reload];

View file

@ -202,6 +202,26 @@
<key>Key</key> <key>Key</key>
<string>override_scroll_read_filter</string> <string>override_scroll_read_filter</string>
</dict> </dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Story titles layout</string>
<key>Titles</key>
<array>
<string>Titles in list</string>
<string>Titles in grid</string>
</array>
<key>DefaultValue</key>
<string>titles_on_left</string>
<key>Values</key>
<array>
<string>titles_on_left</string>
<string>titles_in_grid</string>
</array>
<key>Key</key>
<string>story_titles_position</string>
</dict>
<dict> <dict>
<key>Type</key> <key>Type</key>
<string>PSMultiValueSpecifier</string> <string>PSMultiValueSpecifier</string>