Storing of feed entries and fetched property bugfix
This commit is contained in:
@@ -28,43 +28,46 @@
|
||||
54E88320211B509D00064188 /* ModalFeedEdit.m in Sources */ = {isa = PBXBuildFile; fileRef = 54E8831E211B509D00064188 /* ModalFeedEdit.m */; };
|
||||
54E88321211B509D00064188 /* ModalFeedEdit.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54E8831F211B509D00064188 /* ModalFeedEdit.xib */; };
|
||||
54F39C2E210BE1F700AEE730 /* DBv1.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 54ACC28221061B3B0020715F /* DBv1.xcdatamodeld */; };
|
||||
54FE73D021220DEC003EAC65 /* StoreCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = 54FE73CF21220DEC003EAC65 /* StoreCoordinator.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1968E7919BAA36F042FCB717 /* PyHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyHandler.h; sourceTree = "<group>"; };
|
||||
1968EF7567E06D2A5BB3481A /* PyHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PyHandler.m; sourceTree = "<group>"; };
|
||||
54209E922117325100F3B5EF /* DrawImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DrawImage.h; sourceTree = "<group>"; };
|
||||
54209E932117325100F3B5EF /* DrawImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DrawImage.m; sourceTree = "<group>"; };
|
||||
544B01182114B41200386E5C /* ModalSheet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ModalSheet.h; sourceTree = "<group>"; };
|
||||
544B01192114B41200386E5C /* ModalSheet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ModalSheet.m; sourceTree = "<group>"; };
|
||||
544B011B2114EE9100386E5C /* AppHook.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppHook.h; sourceTree = "<group>"; };
|
||||
544B011C2114EE9100386E5C /* AppHook.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppHook.m; sourceTree = "<group>"; };
|
||||
54209E922117325100F3B5EF /* DrawImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawImage.h; sourceTree = "<group>"; };
|
||||
54209E932117325100F3B5EF /* DrawImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DrawImage.m; sourceTree = "<group>"; };
|
||||
544B01182114B41200386E5C /* ModalSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModalSheet.h; sourceTree = "<group>"; };
|
||||
544B01192114B41200386E5C /* ModalSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ModalSheet.m; sourceTree = "<group>"; };
|
||||
544B011B2114EE9100386E5C /* AppHook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppHook.h; sourceTree = "<group>"; };
|
||||
544B011C2114EE9100386E5C /* AppHook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppHook.m; sourceTree = "<group>"; };
|
||||
544FBD4421064AEB008A260C /* Python.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Python.framework; path = System/Library/Frameworks/Python.framework; sourceTree = SDKROOT; };
|
||||
544FBD4621064B2F008A260C /* getFeed.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = getFeed.py; sourceTree = "<group>"; usesTabs = 0; };
|
||||
544FBD4821064DF0008A260C /* feedparser521.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = feedparser521.py; sourceTree = "<group>"; usesTabs = 0; };
|
||||
546FC43B21188AD5007CC3A3 /* SettingsFeeds.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SettingsFeeds.h; sourceTree = "<group>"; };
|
||||
546FC43C21188AD5007CC3A3 /* SettingsFeeds.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SettingsFeeds.m; sourceTree = "<group>"; };
|
||||
546FC43B21188AD5007CC3A3 /* SettingsFeeds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsFeeds.h; sourceTree = "<group>"; };
|
||||
546FC43C21188AD5007CC3A3 /* SettingsFeeds.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsFeeds.m; sourceTree = "<group>"; };
|
||||
546FC43E21188C78007CC3A3 /* SettingsFeeds.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SettingsFeeds.xib; sourceTree = "<group>"; };
|
||||
546FC44021189975007CC3A3 /* SettingsGeneral.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SettingsGeneral.h; sourceTree = "<group>"; };
|
||||
546FC44121189975007CC3A3 /* SettingsGeneral.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SettingsGeneral.m; sourceTree = "<group>"; };
|
||||
546FC44021189975007CC3A3 /* SettingsGeneral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsGeneral.h; sourceTree = "<group>"; };
|
||||
546FC44121189975007CC3A3 /* SettingsGeneral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsGeneral.m; sourceTree = "<group>"; };
|
||||
546FC44221189975007CC3A3 /* SettingsGeneral.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SettingsGeneral.xib; sourceTree = "<group>"; };
|
||||
546FC4462118A8E6007CC3A3 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Preferences.xib; sourceTree = "<group>"; };
|
||||
54ACC27C21061B3B0020715F /* baRSS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = baRSS.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
54ACC27F21061B3B0020715F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
54ACC28021061B3B0020715F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
54ACC27F21061B3B0020715F /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
54ACC28021061B3B0020715F /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
54ACC28321061B3B0020715F /* DBv1.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = DBv1.xcdatamodel; sourceTree = "<group>"; };
|
||||
54ACC28521061B3C0020715F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
54ACC28821061B3C0020715F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/Main.xib; sourceTree = "<group>"; };
|
||||
54ACC28A21061B3C0020715F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
54ACC28B21061B3C0020715F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
54ACC29321061E270020715F /* NewsController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NewsController.h; sourceTree = "<group>"; };
|
||||
54ACC29421061E270020715F /* NewsController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NewsController.m; sourceTree = "<group>"; };
|
||||
54ACC29621061FBA0020715F /* Preferences.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Preferences.h; sourceTree = "<group>"; };
|
||||
54ACC29721061FBA0020715F /* Preferences.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Preferences.m; sourceTree = "<group>"; };
|
||||
54E8831D211B509D00064188 /* ModalFeedEdit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ModalFeedEdit.h; sourceTree = "<group>"; };
|
||||
54E8831E211B509D00064188 /* ModalFeedEdit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ModalFeedEdit.m; sourceTree = "<group>"; };
|
||||
54ACC28B21061B3C0020715F /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
54ACC29321061E270020715F /* NewsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewsController.h; sourceTree = "<group>"; };
|
||||
54ACC29421061E270020715F /* NewsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewsController.m; sourceTree = "<group>"; };
|
||||
54ACC29621061FBA0020715F /* Preferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Preferences.h; sourceTree = "<group>"; };
|
||||
54ACC29721061FBA0020715F /* Preferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Preferences.m; sourceTree = "<group>"; };
|
||||
54E8831D211B509D00064188 /* ModalFeedEdit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModalFeedEdit.h; sourceTree = "<group>"; };
|
||||
54E8831E211B509D00064188 /* ModalFeedEdit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ModalFeedEdit.m; sourceTree = "<group>"; };
|
||||
54E8831F211B509D00064188 /* ModalFeedEdit.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ModalFeedEdit.xib; sourceTree = "<group>"; };
|
||||
54EC3E1D211D03C100E314F4 /* FeedConfig+Print.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FeedConfig+Print.h"; sourceTree = "<group>"; };
|
||||
54EC3E1D211D03C100E314F4 /* FeedConfig+Print.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FeedConfig+Print.h"; sourceTree = "<group>"; };
|
||||
54FE73CE21220DEC003EAC65 /* StoreCoordinator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StoreCoordinator.h; sourceTree = "<group>"; };
|
||||
54FE73CF21220DEC003EAC65 /* StoreCoordinator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StoreCoordinator.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -148,6 +151,8 @@
|
||||
544B011C2114EE9100386E5C /* AppHook.m */,
|
||||
54ACC27F21061B3B0020715F /* AppDelegate.h */,
|
||||
54ACC28021061B3B0020715F /* AppDelegate.m */,
|
||||
54FE73CE21220DEC003EAC65 /* StoreCoordinator.h */,
|
||||
54FE73CF21220DEC003EAC65 /* StoreCoordinator.m */,
|
||||
54ACC29321061E270020715F /* NewsController.h */,
|
||||
54ACC29421061E270020715F /* NewsController.m */,
|
||||
54209E922117325100F3B5EF /* DrawImage.h */,
|
||||
@@ -271,6 +276,7 @@
|
||||
54E88320211B509D00064188 /* ModalFeedEdit.m in Sources */,
|
||||
1968E0AE14B8E8A90E194980 /* PyHandler.m in Sources */,
|
||||
54209E942117325100F3B5EF /* DrawImage.m in Sources */,
|
||||
54FE73D021220DEC003EAC65 /* StoreCoordinator.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
@property (readonly, strong) NSPersistentContainer *persistentContainer;
|
||||
|
||||
- (IBAction)saveAction:(id)sender;
|
||||
- (void)preferencesClosed;
|
||||
@end
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#import "PyHandler.h"
|
||||
#import "DrawImage.h"
|
||||
#import "Preferences.h"
|
||||
#import "StoreCoordinator.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
@property (weak) IBOutlet NSMenu *statusMenu;
|
||||
@@ -42,6 +43,7 @@
|
||||
self.statusItem.image.template = YES;
|
||||
[PyHandler prepare];
|
||||
printf("up and running\n");
|
||||
// [StoreCoordinator deleteUnreferencedFeeds];
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||
@@ -75,6 +77,7 @@
|
||||
}
|
||||
}];
|
||||
NSUndoManager *um = [[NSUndoManager alloc] init];
|
||||
um.groupsByEvent = NO;
|
||||
um.levelsOfUndo = 30;
|
||||
_persistentContainer.viewContext.undoManager = um;
|
||||
}
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
<attribute name="title" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<relationship name="config" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="FeedConfig" inverseName="feed" inverseEntity="FeedConfig" syncable="YES"/>
|
||||
<relationship name="items" optional="YES" toMany="YES" deletionRule="Cascade" ordered="YES" destinationEntity="FeedItem" inverseName="feed" inverseEntity="FeedItem" syncable="YES"/>
|
||||
<fetchedProperty name="tags" optional="YES" syncable="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="Feed" predicateString="(SELF.tags.feedItem=$FETCH_SOURCE.items)"/>
|
||||
</fetchedProperty>
|
||||
</entity>
|
||||
<entity name="FeedConfig" representedClassName="FeedConfig" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
|
||||
@@ -42,7 +39,7 @@
|
||||
<relationship name="feedItem" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="FeedItem" inverseName="tags" inverseEntity="FeedItem" syncable="YES"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="Feed" positionX="-209" positionY="-3" width="128" height="239"/>
|
||||
<element name="Feed" positionX="-209" positionY="-3" width="128" height="210"/>
|
||||
<element name="FeedConfig" positionX="-20" positionY="-126" width="128" height="180"/>
|
||||
<element name="FeedItem" positionX="-20" positionY="81" width="128" height="165"/>
|
||||
<element name="FeedTag" positionX="187" positionY="171" width="128" height="75"/>
|
||||
|
||||
@@ -23,6 +23,5 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface NewsController : NSObject
|
||||
|
||||
+ (void)downloadFeed:(NSString*)url withBlock:(nullable void (^)(NSDictionary* result, NSError* error))block;
|
||||
@end
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#import "NewsController.h"
|
||||
#import "PyHandler.h"
|
||||
#import "DBv1+CoreDataModel.h"
|
||||
|
||||
@interface NewsController ()
|
||||
@end
|
||||
@@ -35,35 +34,6 @@
|
||||
|
||||
- (IBAction)updateAllFeeds:(NSMenuItem *)sender {
|
||||
NSLog(@"update all");
|
||||
NSDictionary * obj = [PyHandler getFeed:@"https://feeds.feedburner.com/simpledesktops" withEtag:nil andModified:nil];
|
||||
NSLog(@"obj = %@", obj);
|
||||
// TODO: check status code
|
||||
/*
|
||||
Feed *a = [[Feed alloc] initWithEntity:Feed.entity insertIntoManagedObjectContext:self.managedObjectContext];
|
||||
a.title = obj[@"feed"][@"title"];
|
||||
a.subtitle = obj[@"feed"][@"subtitle"];
|
||||
a.author = obj[@"feed"][@"author"];
|
||||
a.link = obj[@"feed"][@"link"];
|
||||
a.published = obj[@"feed"][@"published"];
|
||||
a.icon = obj[@"feed"][@"icon"];
|
||||
a.etag = obj[@"header"][@"etag"];
|
||||
a.date = obj[@"header"][@"date"];
|
||||
a.modified = obj[@"header"][@"modified"];
|
||||
for (NSDictionary *entry in obj[@"entries"]) {
|
||||
FeedItem *b = [[FeedItem alloc] initWithEntity:FeedItem.entity insertIntoManagedObjectContext:self.managedObjectContext];
|
||||
b.title = entry[@"title"];
|
||||
b.subtitle = entry[@"subtitle"];
|
||||
b.author = entry[@"author"];
|
||||
b.link = entry[@"link"];
|
||||
b.published = entry[@"published"];
|
||||
b.summary = entry[@"summary"];
|
||||
for (NSString *tag in entry[@"tags"]) {
|
||||
FeedTag *c = [[FeedTag alloc] initWithEntity:FeedTag.entity insertIntoManagedObjectContext:self.managedObjectContext];
|
||||
c.name = tag;
|
||||
[b addTagsObject:c];
|
||||
}
|
||||
[a addItemsObject:b];
|
||||
}*/
|
||||
}
|
||||
|
||||
- (IBAction)openAllUnread:(NSMenuItem *)sender {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@protocol ModalFeedConfigEdit <NSObject>
|
||||
- (void)updateRepresentedObject; // must call [item.managedObjectContext refreshAllObjects]
|
||||
- (void)updateRepresentedObject; // must call [item.managedObjectContext refreshObject:item mergeChanges:YES];
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#import "ModalFeedEdit.h"
|
||||
#import "NewsController.h"
|
||||
#import "StoreCoordinator.h"
|
||||
#import "FeedConfig+CoreDataProperties.h"
|
||||
|
||||
@interface ModalFeedEdit()
|
||||
@@ -38,8 +39,9 @@
|
||||
@property (strong) NSError *feedError;
|
||||
@property (strong) NSDictionary *feedResult;
|
||||
|
||||
@property (assign) BOOL shouldEvaluate;
|
||||
@property (assign) BOOL lateEvaluation;
|
||||
@property (assign) BOOL shouldSaveObject;
|
||||
@property (assign) BOOL objectNeedsSaving;
|
||||
@property (assign) BOOL objectIsModified;
|
||||
@end
|
||||
|
||||
@implementation ModalFeedEdit
|
||||
@@ -48,7 +50,9 @@
|
||||
[super viewDidLoad];
|
||||
self.previousURL = @"";
|
||||
self.refreshNum.intValue = 30;
|
||||
self.shouldEvaluate = NO;
|
||||
self.shouldSaveObject = NO;
|
||||
self.objectNeedsSaving = NO;
|
||||
self.objectIsModified = NO;
|
||||
|
||||
FeedConfig *fc = [self feedConfigOrNil];
|
||||
if (fc) {
|
||||
@@ -65,21 +69,30 @@
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
FeedConfig *item = [self feedConfigOrNil];
|
||||
if (self.shouldEvaluate && self.lateEvaluation && item) {
|
||||
if (!item.name || [item.name isEqualToString:@""]) {
|
||||
[self setTitleFromFeed];
|
||||
if (![item.name isEqualToString: self.name.stringValue]) // only if result isnt empty as well
|
||||
item.name = self.name.stringValue;
|
||||
[item.managedObjectContext refreshAllObjects];
|
||||
if (self.shouldSaveObject) {
|
||||
if (self.objectNeedsSaving)
|
||||
[self updateRepresentedObject];
|
||||
NSUndoManager *um = [self feedConfigOrNil].managedObjectContext.undoManager;
|
||||
[um endUndoGrouping];
|
||||
if (!self.objectIsModified) {
|
||||
[um disableUndoRegistration];
|
||||
[um undoNestedGroup];
|
||||
[um enableUndoRegistration];
|
||||
} else {
|
||||
[StoreCoordinator save];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateRepresentedObject {
|
||||
FeedConfig *item = [self feedConfigOrNil];
|
||||
if (item) {
|
||||
if (!self.shouldSaveObject) { // first call to this method
|
||||
[item.managedObjectContext.undoManager beginUndoGrouping];
|
||||
}
|
||||
self.shouldSaveObject = YES;
|
||||
self.objectNeedsSaving = NO; // after this method it is saved
|
||||
|
||||
// if's to prevent unnecessary undo groups if nothing has changed
|
||||
if (![item.name isEqualToString: self.name.stringValue])
|
||||
item.name = self.name.stringValue;
|
||||
@@ -90,11 +103,17 @@
|
||||
if (item.refreshUnit != self.refreshUnit.indexOfSelectedItem)
|
||||
item.refreshUnit = (int16_t)self.refreshUnit.indexOfSelectedItem;
|
||||
|
||||
self.shouldEvaluate = YES;
|
||||
self.lateEvaluation = NO;
|
||||
// TODO: append feed result
|
||||
NSLog(@"here i want to set it");
|
||||
[item.managedObjectContext refreshAllObjects];
|
||||
|
||||
if (self.feedResult) {
|
||||
Feed *rss = [StoreCoordinator createFeedFromDictionary:self.feedResult];
|
||||
if (item.feed)
|
||||
[item.managedObjectContext deleteObject:(NSManagedObject*)item.feed];
|
||||
item.feed = rss;
|
||||
}
|
||||
if ([item.managedObjectContext hasChanges]) {
|
||||
self.objectIsModified = YES;
|
||||
[item.managedObjectContext refreshObject:item mergeChanges:YES];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,17 +137,15 @@
|
||||
if (obj.object == self.url && [self urlHasChanged]) {
|
||||
self.previousURL = self.url.stringValue;
|
||||
self.feedResult = nil;
|
||||
NSLog(@"setting result to nil");
|
||||
self.feedError = nil;
|
||||
[self.spinnerURL startAnimation:nil];
|
||||
[self.spinnerName startAnimation:nil];
|
||||
[NewsController downloadFeed:self.previousURL withBlock:^(NSDictionary *result, NSError *error) {
|
||||
self.feedResult = result;
|
||||
NSLog(@"got results back");
|
||||
self.feedError = error; // warning indicator .hidden is bound to feedError
|
||||
// TODO: play error sound?
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self.lateEvaluation = YES; // stays YES if this block runs after updateRepresentedObject:
|
||||
self.objectNeedsSaving = YES; // stays YES if this block runs after updateRepresentedObject:
|
||||
[self setTitleFromFeed];
|
||||
[self.spinnerURL stopAnimation:nil];
|
||||
[self.spinnerName stopAnimation:nil];
|
||||
@@ -186,7 +203,7 @@
|
||||
NSString *name = ((NSTextField*)self.view).stringValue;
|
||||
if (![item.name isEqualToString: name]) {
|
||||
item.name = name;
|
||||
[item.managedObjectContext refreshAllObjects];
|
||||
[item.managedObjectContext refreshObject:item mergeChanges:YES];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
/** Manages the NSOutlineView and Feed creation and editing */
|
||||
@interface SettingsFeeds : NSViewController <NSOutlineViewDataSource, NSOutlineViewDelegate>
|
||||
|
||||
@end
|
||||
|
||||
@@ -101,12 +101,14 @@ static NSString *dragNodeType = @"baRSS-feed-drag";
|
||||
|
||||
[self.view.window beginSheet:[ModalSheet modalWithView:self.modalController.view] completionHandler:^(NSModalResponse returnCode) {
|
||||
if (returnCode == NSModalResponseOK) {
|
||||
[self.undoManager beginUndoGrouping];
|
||||
if (!existingItem) { // create new item
|
||||
FeedConfig *item = [self insertSortedItemAtSelection];
|
||||
item.type = (group ? 0 : 1);
|
||||
self.modalController.representedObject = item;
|
||||
}
|
||||
[self.modalController updateRepresentedObject];
|
||||
[self.undoManager endUndoGrouping];
|
||||
}
|
||||
self.modalController = nil;
|
||||
}];
|
||||
@@ -328,6 +330,12 @@ static NSString *dragNodeType = @"baRSS-feed-drag";
|
||||
NSLog(@"%@", str);
|
||||
}
|
||||
|
||||
/**
|
||||
Go through all children recursively and prepend the string with spaces as nesting
|
||||
@param obj Root Node or parent Node
|
||||
@param str An initialized @c NSMutableString to append to
|
||||
@param prefix Should be @c @@"" for the first call
|
||||
*/
|
||||
- (void)traverseChildren:(NSTreeNode*)obj appendString:(NSMutableString*)str prefix:(NSString*)prefix {
|
||||
[str appendFormat:@"%@%@\n", prefix, [obj.representedObject readableDescription]];
|
||||
prefix = [prefix stringByAppendingString:@" "];
|
||||
|
||||
31
baRSS/StoreCoordinator.h
Normal file
31
baRSS/StoreCoordinator.h
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
// Copyright (c) 2018 Oleg Geier
|
||||
//
|
||||
// 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.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class Feed;
|
||||
|
||||
@interface StoreCoordinator : NSObject
|
||||
+ (void)save;
|
||||
+ (void)deleteUnreferencedFeeds;
|
||||
+ (Feed*)createFeedFromDictionary:(NSDictionary*)obj;
|
||||
@end
|
||||
77
baRSS/StoreCoordinator.m
Normal file
77
baRSS/StoreCoordinator.m
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
// Copyright (c) 2018 Oleg Geier
|
||||
//
|
||||
// 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.
|
||||
|
||||
#import "StoreCoordinator.h"
|
||||
#import "AppDelegate.h"
|
||||
#import "DBv1+CoreDataModel.h"
|
||||
|
||||
@implementation StoreCoordinator
|
||||
|
||||
+ (NSManagedObjectContext*)getContext {
|
||||
return [(AppDelegate*)[NSApp delegate] persistentContainer].viewContext;
|
||||
}
|
||||
|
||||
+ (void)save {
|
||||
[(AppDelegate*)[NSApp delegate] saveAction:nil];
|
||||
}
|
||||
|
||||
+ (void)deleteUnreferencedFeeds {
|
||||
NSManagedObjectContext *moc = [self getContext];
|
||||
NSFetchRequest *fr = [NSFetchRequest fetchRequestWithEntityName:Feed.entity.name];
|
||||
fr.predicate = [NSPredicate predicateWithFormat:@"config = NULL"];
|
||||
NSBatchDeleteRequest *bdr = [[NSBatchDeleteRequest alloc] initWithFetchRequest:fr];
|
||||
NSError *err;
|
||||
[moc executeRequest:bdr error:&err];
|
||||
if (err) NSLog(@"%@", err);
|
||||
}
|
||||
|
||||
+ (Feed*)createFeedFromDictionary:(NSDictionary*)obj {
|
||||
NSManagedObjectContext *moc = [self getContext];
|
||||
Feed *a = [[Feed alloc] initWithEntity:Feed.entity insertIntoManagedObjectContext:moc];
|
||||
a.title = obj[@"feed"][@"title"];
|
||||
a.subtitle = obj[@"feed"][@"subtitle"];
|
||||
a.author = obj[@"feed"][@"author"];
|
||||
a.link = obj[@"feed"][@"link"];
|
||||
a.published = obj[@"feed"][@"published"];
|
||||
a.icon = obj[@"feed"][@"icon"];
|
||||
a.etag = obj[@"header"][@"etag"];
|
||||
a.date = obj[@"header"][@"date"];
|
||||
a.modified = obj[@"header"][@"modified"];
|
||||
for (NSDictionary *entry in obj[@"entries"]) {
|
||||
FeedItem *b = [[FeedItem alloc] initWithEntity:FeedItem.entity insertIntoManagedObjectContext:moc];
|
||||
b.title = entry[@"title"];
|
||||
b.subtitle = entry[@"subtitle"];
|
||||
b.author = entry[@"author"];
|
||||
b.link = entry[@"link"];
|
||||
b.published = entry[@"published"];
|
||||
b.summary = entry[@"summary"];
|
||||
for (NSString *tag in entry[@"tags"]) {
|
||||
FeedTag *c = [[FeedTag alloc] initWithEntity:FeedTag.entity insertIntoManagedObjectContext:moc];
|
||||
c.name = tag;
|
||||
[b addTagsObject:c];
|
||||
}
|
||||
[a addItemsObject:b];
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user