feat: iOS Reader tab — full RSS reader with article reading pane
New third tab in the iOS app with: - ReaderModels matching Reader API response shapes - ReaderAPI with all endpoints (entries, feeds, categories, counters) - ReaderViewModel with filters (Unread/Starred/All), pagination, feed management - ReaderTabView with sub-tabs and feed filter chips - EntryListView with infinite scroll, context menus, read/unread state - ArticleView with WKWebView HTML rendering, star/read toggles, Save to Brain - ArticleWebView (UIViewRepresentable WKWebView wrapper) - FeedManagementSheet with add/delete/refresh feeds, categories - Warm Atelier design consistent with existing app Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,14 @@
|
||||
A10031 /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10031; };
|
||||
A10032 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C10001; };
|
||||
A10033 /* FeedbackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10034; };
|
||||
A10040 /* ReaderModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10040; };
|
||||
A10041 /* ReaderAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10041; };
|
||||
A10042 /* ReaderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10042; };
|
||||
A10043 /* ReaderTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10043; };
|
||||
A10044 /* EntryListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10044; };
|
||||
A10045 /* ArticleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10045; };
|
||||
A10046 /* ArticleWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10046; };
|
||||
A10047 /* FeedManagementSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10047; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -76,6 +84,14 @@
|
||||
B10031 /* Date+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extensions.swift"; sourceTree = "<group>"; };
|
||||
B10033 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
B10034 /* FeedbackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbackView.swift; sourceTree = "<group>"; };
|
||||
B10040 /* ReaderModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderModels.swift; sourceTree = "<group>"; };
|
||||
B10041 /* ReaderAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderAPI.swift; sourceTree = "<group>"; };
|
||||
B10042 /* ReaderViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderViewModel.swift; sourceTree = "<group>"; };
|
||||
B10043 /* ReaderTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderTabView.swift; sourceTree = "<group>"; };
|
||||
B10044 /* EntryListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryListView.swift; sourceTree = "<group>"; };
|
||||
B10045 /* ArticleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleView.swift; sourceTree = "<group>"; };
|
||||
B10046 /* ArticleWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleWebView.swift; sourceTree = "<group>"; };
|
||||
B10047 /* FeedManagementSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedManagementSheet.swift; sourceTree = "<group>"; };
|
||||
C10001 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
D10001 /* Platform.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Platform.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -131,6 +147,7 @@
|
||||
F10007 /* Fitness */,
|
||||
F10014 /* Assistant */,
|
||||
F10021 /* Feedback */,
|
||||
F10030 /* Reader */,
|
||||
);
|
||||
path = Features;
|
||||
sourceTree = "<group>";
|
||||
@@ -268,6 +285,53 @@
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F10030 /* Reader */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F10031 /* Models */,
|
||||
F10032 /* API */,
|
||||
F10033 /* ViewModels */,
|
||||
F10034 /* Views */,
|
||||
);
|
||||
path = Reader;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F10031 /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B10040 /* ReaderModels.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F10032 /* API */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B10041 /* ReaderAPI.swift */,
|
||||
);
|
||||
path = API;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F10033 /* ViewModels */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B10042 /* ReaderViewModel.swift */,
|
||||
);
|
||||
path = ViewModels;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F10034 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B10043 /* ReaderTabView.swift */,
|
||||
B10044 /* EntryListView.swift */,
|
||||
B10045 /* ArticleView.swift */,
|
||||
B10046 /* ArticleWebView.swift */,
|
||||
B10047 /* FeedManagementSheet.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@@ -369,6 +433,14 @@
|
||||
A10030 /* Color+Extensions.swift in Sources */,
|
||||
A10031 /* Date+Extensions.swift in Sources */,
|
||||
A10033 /* FeedbackView.swift in Sources */,
|
||||
A10040 /* ReaderModels.swift in Sources */,
|
||||
A10041 /* ReaderAPI.swift in Sources */,
|
||||
A10042 /* ReaderViewModel.swift in Sources */,
|
||||
A10043 /* ReaderTabView.swift in Sources */,
|
||||
A10044 /* EntryListView.swift in Sources */,
|
||||
A10045 /* ArticleView.swift in Sources */,
|
||||
A10046 /* ArticleWebView.swift in Sources */,
|
||||
A10047 /* FeedManagementSheet.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user