mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Use the new layout for all the widget views.
This commit is contained in:
@@ -289,6 +289,7 @@
|
||||
843E2F1E2CF2B8D300ED170F /* RSWeb in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 843E2F1C2CF2B8D300ED170F /* RSWeb */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
84411E711FE5FBFA004B527F /* SmallIconProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84411E701FE5FBFA004B527F /* SmallIconProvider.swift */; };
|
||||
8444C8F21FED81840051386C /* OPMLExporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8444C8F11FED81840051386C /* OPMLExporter.swift */; };
|
||||
8448F1E22D1E2DA30048BA50 /* WidgetLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8448F1E12D1E2DA30048BA50 /* WidgetLayout.swift */; };
|
||||
844B5B591FE9FE4F00C7C76A /* SidebarKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844B5B581FE9FE4F00C7C76A /* SidebarKeyboardDelegate.swift */; };
|
||||
844B5B5B1FEA00FB00C7C76A /* TimelineKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844B5B5A1FEA00FB00C7C76A /* TimelineKeyboardDelegate.swift */; };
|
||||
844B5B651FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 844B5B641FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist */; };
|
||||
@@ -793,6 +794,7 @@
|
||||
843E2F152CF2B43700ED170F /* RSWeb */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = RSWeb; sourceTree = "<group>"; };
|
||||
84411E701FE5FBFA004B527F /* SmallIconProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmallIconProvider.swift; sourceTree = "<group>"; };
|
||||
8444C8F11FED81840051386C /* OPMLExporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OPMLExporter.swift; sourceTree = "<group>"; };
|
||||
8448F1E12D1E2DA30048BA50 /* WidgetLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetLayout.swift; sourceTree = "<group>"; };
|
||||
844B5B581FE9FE4F00C7C76A /* SidebarKeyboardDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarKeyboardDelegate.swift; sourceTree = "<group>"; };
|
||||
844B5B5A1FEA00FB00C7C76A /* TimelineKeyboardDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineKeyboardDelegate.swift; sourceTree = "<group>"; };
|
||||
844B5B641FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = GlobalKeyboardShortcuts.plist; sourceTree = "<group>"; };
|
||||
@@ -1136,6 +1138,7 @@
|
||||
1768143D2564BCC800D98635 /* TodayWidget.swift */,
|
||||
176814452564BCD200D98635 /* StarredWidget.swift */,
|
||||
1768144D2564BCE000D98635 /* SmartFeedSummaryWidget.swift */,
|
||||
8448F1E12D1E2DA30048BA50 /* WidgetLayout.swift */,
|
||||
);
|
||||
path = "Widget Views";
|
||||
sourceTree = "<group>";
|
||||
@@ -2561,6 +2564,7 @@
|
||||
1768142D2564BCA800D98635 /* TimelineProvider.swift in Sources */,
|
||||
1701E1E725689D1E009453D8 /* Localized.swift in Sources */,
|
||||
176814652564BD7F00D98635 /* WidgetData.swift in Sources */,
|
||||
8448F1E22D1E2DA30048BA50 /* WidgetLayout.swift in Sources */,
|
||||
1768145E2564BD7B00D98635 /* WidgetDataDecoder.swift in Sources */,
|
||||
176814132564BC8A00D98635 /* WidgetBundle.swift in Sources */,
|
||||
17E0084625941887000C23F0 /* SizeCategories.swift in Sources */,
|
||||
|
||||
@@ -22,7 +22,7 @@ struct ArticleItemView: View {
|
||||
if iconImage != nil {
|
||||
iconImage!
|
||||
.resizable()
|
||||
.frame(width: 24, height: 24)
|
||||
.frame(width: WidgetLayout.feedIconSize, height: WidgetLayout.feedIconSize)
|
||||
.cornerRadius(4)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ import WidgetKit
|
||||
import SwiftUI
|
||||
|
||||
struct StarredWidgetView : View {
|
||||
|
||||
|
||||
@Environment(\.widgetFamily) var family: WidgetFamily
|
||||
@Environment(\.sizeCategory) var sizeCategory: ContentSizeCategory
|
||||
|
||||
|
||||
var entry: Provider.Entry
|
||||
|
||||
|
||||
var body: some View {
|
||||
if entry.widgetData.starredArticles.count == 0 {
|
||||
inboxZero
|
||||
@@ -23,40 +23,28 @@ struct StarredWidgetView : View {
|
||||
}
|
||||
else {
|
||||
GeometryReader { metrics in
|
||||
HStack {
|
||||
VStack {
|
||||
starredImage
|
||||
.padding(.vertical, 12)
|
||||
.padding(.leading, 8)
|
||||
Spacer()
|
||||
|
||||
}
|
||||
}
|
||||
.frame(width: metrics.size.width * 0.15)
|
||||
|
||||
Spacer()
|
||||
|
||||
starredImage
|
||||
.frame(width: WidgetLayout.titleImageSize, alignment: .leading)
|
||||
VStack(alignment:.leading, spacing: 0) {
|
||||
ForEach(0..<maxCount(), id: \.self, content: { i in
|
||||
if i != 0 {
|
||||
Divider()
|
||||
ArticleItemView(article: entry.widgetData.starredArticles[i],
|
||||
deepLink: WidgetDeepLink.starredArticle(id: entry.widgetData.starredArticles[i].id).url)
|
||||
.padding(.top, 8)
|
||||
.padding(.bottom, 4)
|
||||
.padding(.top, WidgetLayout.articleItemViewPaddingTop)
|
||||
.padding(.bottom, WidgetLayout.articleItemViewPaddingBottom)
|
||||
} else {
|
||||
ArticleItemView(article: entry.widgetData.starredArticles[i],
|
||||
deepLink: WidgetDeepLink.starredArticle(id: entry.widgetData.starredArticles[i].id).url)
|
||||
.padding(.bottom, 4)
|
||||
.padding(.bottom, WidgetLayout.articleItemViewPaddingBottom)
|
||||
}
|
||||
})
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading, metrics.size.width * 0.175)
|
||||
.padding(.leading, WidgetLayout.leftSideWidth)
|
||||
.padding([.bottom, .trailing])
|
||||
.padding(.top, 12)
|
||||
.overlay(
|
||||
VStack {
|
||||
VStack {
|
||||
Spacer()
|
||||
HStack {
|
||||
Spacer()
|
||||
@@ -68,35 +56,34 @@ struct StarredWidgetView : View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.bottom, 6)
|
||||
.padding(.horizontal)
|
||||
)
|
||||
|
||||
}.widgetURL(WidgetDeepLink.starred.url)
|
||||
|
||||
|
||||
}
|
||||
.widgetURL(WidgetDeepLink.starred.url)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var starredImage: some View {
|
||||
Image(systemName: "star.fill")
|
||||
.resizable()
|
||||
.frame(width: 30, height: 30, alignment: .center)
|
||||
.frame(width: WidgetLayout.titleImageSize, height: WidgetLayout.titleImageSize, alignment: .top)
|
||||
.cornerRadius(4)
|
||||
.foregroundColor(.yellow)
|
||||
}
|
||||
|
||||
|
||||
func maxCount() -> Int {
|
||||
var reduceAccessibilityCount: Int = 0
|
||||
if SizeCategories().isSizeCategoryLarge(category: sizeCategory) {
|
||||
reduceAccessibilityCount = 1
|
||||
}
|
||||
|
||||
|
||||
if family == .systemLarge {
|
||||
return entry.widgetData.currentStarredCount >= 7 ? (7 - reduceAccessibilityCount) : entry.widgetData.currentStarredCount
|
||||
}
|
||||
return entry.widgetData.currentStarredCount >= 3 ? (3 - reduceAccessibilityCount) : entry.widgetData.currentStarredCount
|
||||
}
|
||||
|
||||
|
||||
var inboxZero: some View {
|
||||
VStack(alignment: .center) {
|
||||
Spacer()
|
||||
@@ -105,12 +92,12 @@ struct StarredWidgetView : View {
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 30)
|
||||
.foregroundColor(.yellow)
|
||||
|
||||
|
||||
|
||||
Text(L10n.starredWidgetNoItemsTitle)
|
||||
.font(.headline)
|
||||
.foregroundColor(.primary)
|
||||
|
||||
|
||||
Text(L10n.starredWidgetNoItems)
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
@@ -119,5 +106,5 @@ struct StarredWidgetView : View {
|
||||
.multilineTextAlignment(.center)
|
||||
.padding()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ import WidgetKit
|
||||
import SwiftUI
|
||||
|
||||
struct TodayWidgetView : View {
|
||||
|
||||
|
||||
@Environment(\.widgetFamily) var family: WidgetFamily
|
||||
@Environment(\.sizeCategory) var sizeCategory: ContentSizeCategory
|
||||
|
||||
|
||||
var entry: Provider.Entry
|
||||
|
||||
|
||||
var body: some View {
|
||||
if entry.widgetData.todayArticles.count == 0 {
|
||||
inboxZero
|
||||
@@ -23,40 +23,28 @@ struct TodayWidgetView : View {
|
||||
}
|
||||
else {
|
||||
GeometryReader { metrics in
|
||||
HStack {
|
||||
VStack {
|
||||
todayImage
|
||||
.padding(.vertical, 12)
|
||||
.padding(.leading, 8)
|
||||
Spacer()
|
||||
|
||||
}
|
||||
}
|
||||
.frame(width: metrics.size.width * 0.15)
|
||||
|
||||
Spacer()
|
||||
|
||||
todayImage
|
||||
.frame(width: WidgetLayout.titleImageSize, alignment: .leading)
|
||||
VStack(alignment:.leading, spacing: 0) {
|
||||
ForEach(0..<maxCount(), id: \.self, content: { i in
|
||||
if i != 0 {
|
||||
Divider()
|
||||
ArticleItemView(article: entry.widgetData.todayArticles[i],
|
||||
deepLink: WidgetDeepLink.todayArticle(id: entry.widgetData.todayArticles[i].id).url)
|
||||
.padding(.top, 8)
|
||||
.padding(.bottom, 4)
|
||||
.padding(.top, WidgetLayout.articleItemViewPaddingTop)
|
||||
.padding(.bottom, WidgetLayout.articleItemViewPaddingBottom)
|
||||
} else {
|
||||
ArticleItemView(article: entry.widgetData.todayArticles[i],
|
||||
deepLink: WidgetDeepLink.todayArticle(id: entry.widgetData.todayArticles[i].id).url)
|
||||
.padding(.bottom, 4)
|
||||
.padding(.bottom, WidgetLayout.articleItemViewPaddingBottom)
|
||||
}
|
||||
})
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading, metrics.size.width * 0.175)
|
||||
.padding(.leading, WidgetLayout.leftSideWidth)
|
||||
.padding([.bottom, .trailing])
|
||||
.padding(.top, 12)
|
||||
.overlay(
|
||||
VStack {
|
||||
VStack {
|
||||
Spacer()
|
||||
HStack {
|
||||
Spacer()
|
||||
@@ -68,34 +56,34 @@ struct TodayWidgetView : View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.bottom, 6)
|
||||
.padding(.horizontal)
|
||||
)
|
||||
|
||||
}.widgetURL(WidgetDeepLink.today.url)
|
||||
|
||||
}
|
||||
.widgetURL(WidgetDeepLink.today.url)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var todayImage: some View {
|
||||
Image(systemName: "sun.max.fill")
|
||||
.resizable()
|
||||
.frame(width: 30, height: 30, alignment: .center)
|
||||
.frame(width: WidgetLayout.titleImageSize, height: WidgetLayout.titleImageSize, alignment: .top)
|
||||
.cornerRadius(4)
|
||||
.foregroundColor(.orange)
|
||||
}
|
||||
|
||||
|
||||
func maxCount() -> Int {
|
||||
var reduceAccessibilityCount: Int = 0
|
||||
if SizeCategories().isSizeCategoryLarge(category: sizeCategory) {
|
||||
reduceAccessibilityCount = 1
|
||||
}
|
||||
|
||||
|
||||
if family == .systemLarge {
|
||||
return entry.widgetData.todayArticles.count >= 7 ? (7 - reduceAccessibilityCount) : entry.widgetData.todayArticles.count
|
||||
}
|
||||
return entry.widgetData.todayArticles.count >= 3 ? (3 - reduceAccessibilityCount) : entry.widgetData.todayArticles.count
|
||||
}
|
||||
|
||||
|
||||
var inboxZero: some View {
|
||||
VStack(alignment: .center) {
|
||||
Spacer()
|
||||
@@ -104,12 +92,12 @@ struct TodayWidgetView : View {
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 30)
|
||||
.foregroundColor(.orange)
|
||||
|
||||
|
||||
|
||||
Text(L10n.todayWidgetNoItemsTitle)
|
||||
.font(.headline)
|
||||
.foregroundColor(.primary)
|
||||
|
||||
|
||||
Text(L10n.todayWidgetNoItems)
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
@@ -118,5 +106,5 @@ struct TodayWidgetView : View {
|
||||
.multilineTextAlignment(.center)
|
||||
.padding()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ import WidgetKit
|
||||
import SwiftUI
|
||||
|
||||
struct UnreadWidgetView : View {
|
||||
|
||||
|
||||
@Environment(\.widgetFamily) var family: WidgetFamily
|
||||
@Environment(\.sizeCategory) var sizeCategory: ContentSizeCategory
|
||||
|
||||
|
||||
var entry: Provider.Entry
|
||||
|
||||
|
||||
var body: some View {
|
||||
if entry.widgetData.currentUnreadCount == 0 {
|
||||
inboxZero
|
||||
@@ -24,24 +24,24 @@ struct UnreadWidgetView : View {
|
||||
else {
|
||||
GeometryReader { metrics in
|
||||
unreadImage
|
||||
.frame(width: metrics.size.width * 0.10, alignment: .leading)
|
||||
.frame(width: WidgetLayout.titleImageSize, alignment: .leading)
|
||||
VStack(alignment:.leading, spacing: 0) {
|
||||
ForEach(0..<maxCount(), id: \.self, content: { i in
|
||||
if i != 0 {
|
||||
Divider()
|
||||
ArticleItemView(article: entry.widgetData.unreadArticles[i],
|
||||
deepLink: WidgetDeepLink.unreadArticle(id: entry.widgetData.unreadArticles[i].id).url)
|
||||
.padding(.top, 8)
|
||||
.padding(.bottom, 4)
|
||||
.padding(.top, WidgetLayout.articleItemViewPaddingTop)
|
||||
.padding(.bottom, WidgetLayout.articleItemViewPaddingBottom)
|
||||
} else {
|
||||
ArticleItemView(article: entry.widgetData.unreadArticles[i],
|
||||
deepLink: WidgetDeepLink.unreadArticle(id: entry.widgetData.unreadArticles[i].id).url)
|
||||
.padding(.bottom, 4)
|
||||
.padding(.bottom, WidgetLayout.articleItemViewPaddingBottom)
|
||||
}
|
||||
})
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading, metrics.size.width * 0.085)
|
||||
.padding(.leading, WidgetLayout.leftSideWidth)
|
||||
.padding([.bottom, .trailing])
|
||||
.overlay(
|
||||
VStack {
|
||||
@@ -62,26 +62,26 @@ struct UnreadWidgetView : View {
|
||||
.widgetURL(WidgetDeepLink.unread.url)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var unreadImage: some View {
|
||||
Image(systemName: "largecircle.fill.circle")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20, alignment: .top)
|
||||
.frame(width: WidgetLayout.titleImageSize, height: WidgetLayout.titleImageSize, alignment: .top)
|
||||
.foregroundColor(.accentColor)
|
||||
}
|
||||
|
||||
|
||||
func maxCount() -> Int {
|
||||
var reduceAccessibilityCount: Int = 0
|
||||
if SizeCategories().isSizeCategoryLarge(category: sizeCategory) {
|
||||
reduceAccessibilityCount = 1
|
||||
}
|
||||
|
||||
|
||||
if family == .systemLarge {
|
||||
return entry.widgetData.unreadArticles.count >= 7 ? (7 - reduceAccessibilityCount) : entry.widgetData.unreadArticles.count
|
||||
}
|
||||
return entry.widgetData.unreadArticles.count >= 3 ? (3 - reduceAccessibilityCount) : entry.widgetData.unreadArticles.count
|
||||
}
|
||||
|
||||
|
||||
var inboxZero: some View {
|
||||
VStack(alignment: .center) {
|
||||
Spacer()
|
||||
@@ -94,7 +94,7 @@ struct UnreadWidgetView : View {
|
||||
Text(L10n.unreadWidgetNoItemsTitle)
|
||||
.font(.headline)
|
||||
.foregroundColor(.primary)
|
||||
|
||||
|
||||
Text(L10n.unreadWidgetNoItems)
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
@@ -103,6 +103,6 @@ struct UnreadWidgetView : View {
|
||||
.multilineTextAlignment(.center)
|
||||
.padding()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
19
Widget/Widget Views/WidgetLayout.swift
Normal file
19
Widget/Widget Views/WidgetLayout.swift
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// WidgetLayout.swift
|
||||
// NetNewsWire iOS Widget Extension
|
||||
//
|
||||
// Created by Brent Simmons on 12/26/24.
|
||||
// Copyright © 2024 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct WidgetLayout {
|
||||
|
||||
static let titleImageSize = CGFloat(20)
|
||||
static let titleImagePaddingRight = CGFloat(6)
|
||||
static let leftSideWidth = titleImageSize + titleImagePaddingRight
|
||||
static let feedIconSize = CGFloat(24)
|
||||
static let articleItemViewPaddingTop = CGFloat(8)
|
||||
static let articleItemViewPaddingBottom = CGFloat(4)
|
||||
}
|
||||
Reference in New Issue
Block a user